opencv 九种直线检测方法汇总 您所在的位置:网站首页 opencv实现车道线检测 opencv 九种直线检测方法汇总

opencv 九种直线检测方法汇总

2024-02-22 18:14| 来源: 网络整理| 查看: 265

文章目录 1、场景需求2、Hough_line直线检测算法2.1 Hough_line实现步骤2.2 Hough_line代码实战2.3 效果展示与分析2.4 HoughP_line代码实战2.5 效果展示与分析 3、LSD直线检测算法3.1 LSD算法简介 3.2 LSD代码实战3.3 效果展示与分析 4、FLD直线检测算法4.1 FLD算法简介4.2 FLD算法代码实战4.3 效果展示与分析5.1 EDlines算法简介5.2 EDlines算法实现步骤6.2 LSWMS算法代码实现6.3 效果展示与分析 7、CannyLines直线检测算法7.1 CannyLines算法简介7.2 CannyLines算法代码实战7.3 效果展示与分析 8、MCMLSD直线检测算法8.1 MCMLSD算法简介8.2 MCMLSD算法代码实战8.3 效果展示与分析 9、LSM直线检测算法9.1 LSM算法简介9.3 效果展示与分析 参考资料注意事项

1、场景需求

在计算机视觉领域,我们经常需要做一些特殊的任务,而这些任务中经常会用到直线检测算法,比如车道线检测、长度测量等。尽管直线检测的任务看起来比较简单,但是在具体的应用过程中,你会发现这里面还是有很大的优化空间,本文对常用的一些比较经典的直线检测算法进行汇总。

2、Hough_line直线检测算法

Hough变换是一个比较有名的计算机视觉处理算法,该算法可以用来做很多的任务,常用的任务包括直线检测、圆检测、椭圆检测等,下面我们将对该算法进行简单的分析并进行代码实战。

2.1 Hough_line实现步骤

步骤1-首先,它创建一个二维数组或累加器(用于保存两个参数的值),并将其初始设置为零; 步骤2-用r来表示行,用θ来表示列; 步骤3-数组的大小取决于你所需要的精度。假设您希望角度的精度为1度,则需要180列(直线的最大度数为180); 步骤4-对于r,可能的最大距离是图像的对角线长度。因此,取一个像素精度,行数可以是图像的对角线长度。

2.2 Hough_line代码实战 # coding=utf-8 # 导入相应的python包 import cv2 import numpy as np # 读取输入图片 img = cv2.imread('test3.jpg') # 将彩色图片灰度化 gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) # 使用Canny边缘检测 edges = cv2.Canny(gray,50,200,apertureSize = 3) # 进行Hough_line直线检测 lines = cv2.HoughLines(edges,1,np.pi/180, 200) print(lines) # 遍历每一个r和theta for i in range(len(lines)): r,theta = lines[i, 0, 0], lines[i, 0, 1] # 存储cos(theta)的值 a = np.cos(theta) # 存储sin(theta)的值 b = np.sin(theta) # 存储rcos(theta)的值 x0 = a*r # 存储rsin(theta)的值 y0 = b*r # 存储(rcos(theta)-1000sin(theta))的值 x1 = int(x0 + 1000*(-b)) # 存储(rsin(theta)+1000cos(theta))的值 y1 = int(y0 + 1000*(a)) # 存储(rcos(theta)+1000sin(theta))的值 x2 = int(x0 - 1000*(-b)) # 存储(rsin(theta)-1000cos(theta))的值 y2 = int(y0 - 1000*(a)) # 绘制直线结果 cv2.line(img,(x1,y1), (x2,y2), (0,255,0),2) # 保存结果 cv2.imwrite('test3_r.jpg', img) cv2.imshow("result", img) cv2.waitKey(0) 2.3 效果展示与分析

在这里插入图片描述 上图展示了一些Hough_line算法的直线检测效果。为了验证该算法的有效性,我选择了3个不同的具有挑战性的场景,建筑物、答题卡和门。通过观察上面的结果我们可以知道该算法基本上能够检测出图中的直线,但是检测的结果并不是很好,有很多重复和漏检的情况。除此之外,该算法最大的缺点就是需要根据图片去调节参数,关键的参数是lines = cv2.HoughLines(edges,1,np.pi/180, 200) 中的200,该值设置的越大图片中检测出来的直线数量会越少,你需要根据你自己的测试场景进行调节。

2.4 HoughP_line代码实战

HoughP_line是Hough_line算法的改进版,具有更快的速度和更好的效果。

# coding=utf-8 # 导入相应的python包 import cv2 import numpy as np # 读取输入图片 img = cv2.imread('test3.jpg') # 将彩色图片灰度化 gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) # 使用Canny边缘检测 edges = cv2.Canny(gray,50,200,apertureSize = 3) # 进行Hough_line直线检测 lines = cv2.HoughLinesP(edges,1,np.pi/180, 80, 30, 10) # 遍历每一条直线 for i in range(len(lines)): cv2.line(img,(lines[i, 0, 0],lines[i, 0, 1]), (lines[i, 0, 2],lines[i, 0, 3]), (0,255,0),2) # 保存结果 cv2.imwrite('test3_r.jpg', img) cv2.imshow("result", img) cv2.waitKey(0) 2.5 效果展示与分析

在这里插入图片描述 上图展示了一些HoughP_line算法的直线检测效果。上图都是使用lines = cv2.HoughLinesP(edges,1,np.pi/180, 80, 30, 10) 这个固定的参数来计算出结果的,通过观察我们可以发现,HoughLinesP不仅使用起来比较方便,基本上不需要进行调节参数;除此之外,该算法能够获得更好的直线检测效果。因此,当你想用Hough直线检测算法,建议你优先使用HoughP_line算法。

3、LSD直线检测算法

LSD-项目主页-论文链接-代码链接   LSD是opencv中集成的一个直线检测算法,该算法的直线检测效果优于Hough算法,而且具有较好的检测速度,推荐使用。

3.1 LSD算法简介

LSD快速直线检测算法是由Rafael Grompone、Jeremie Jackbowicz、Jean-Michel Morel于2010年发表在PAMI上的文献《LSD:a Line Segment Dectctor》中提出的,该算法时间复杂度较霍夫变换低。LSD算法通过对图像局部分析,得出直线的像素点集,再通过假设参数进行验证求解,将像素点集合与误差控制集合合并,进而自适应控制误检的数量 。 一般来说,要检测图像中的直线,最基本的思想是检测图像中梯度变化较大的像素点集,LSD算法也正是利用梯度信息和行列线(level-line)来进行直线检测的。

3.2 LSD代码实战 # coding=utf-8 import cv2 import numpy as np # 读取输入图片 img0 = cv2.imread("test3.jpg") # 将彩色图片转换为灰度图片 img = cv2.cvtColor(img0,cv2.COLOR_BGR2GRAY) # 创建一个LSD对象 lsd = cv2.createLineSegmentDetector(0) # 执行检测结果 dlines = lsd.detect(img) # 绘制检测结果 for dline in dlines[0]: x0 = int(round(dline[0][0])) y0 = int(round(dline[0][1])) x1 = int(round(dline[0][2])) y1 = int(round(dline[0][3])) cv2.line(img0, (x0, y0), (x1,y1), (0,255,0), 1, cv2.LINE_AA) # 显示并保存结果 cv2.imwrite('test3_r.jpg', img0) cv2.imshow("LSD", img0) cv2.waitKey(0) cv2.destroyAllWindows() 3.3 效果展示与分析

在这里插入图片描述

上图展示了一些LSD算法的直线检测效果。通过观察上面的结果,我们可以发现该算法的检测结果远远优于Hough和HoughP算法;除此之外,上述的检测结果都是使用LSD算法的默认参数进行执行,如果针对特定的参数进行调节,可以取得更好的结果,这种情况一般是在你的特定需求场景中对默认的一些参数进行微调操作,往往能获得意想不到的结果。

在这里插入图片描述 上图展示了LSD直线检测算法的一些超参数,具体的细节请看该链接。需要说明的是该算法具有3中不同的模式,具体的模式如下图所示,默认情况下使用模式2(即1),但是经过测试我发现模式1(即0)通常输出的效果会更好一些,具体的情况需要你根据你的场景进行分析。

4、FLD直线检测算法 4.1 FLD算法简介

FLD直线检测算法是在该论文中被引入的,该论文中尝试着使用直线特征来代替原始的SURF点特征进行建筑物识别。与点特征进行相比,线特征具有更容易发现和更好的鲁棒性,线特征基本上不会受到光照、遮挡、视角变化的影响。下面展示了该算法的直线检测效果,从图中我们可以看出,线特征比点特征更好一些。 在这里插入图片描述

4.2 FLD算法代码实战 # coding=utf-8 import cv2 import numpy as np # 读取输入图片 img0 = cv2.imread("test3.jpg") # 将彩色图片转换为灰度图片 img = cv2.cvtColor(img0,cv2.COLOR_BGR2GRAY) # 创建一个LSD对象 fld = cv2.ximgproc.createFastLineDetector() # 执行检测结果 dlines = fld.detect(img) # 绘制检测结果 # drawn_img = fld.drawSegments(img0,dlines, ) for dline in dlines: x0 = int(round(dline[0][0])) y0 = int(round(dline[0][1])) x1 = int(round(dline[0][2])) y1 = int(round(dline[0][3])) cv2.line(img0, (x0, y0), (x1,y1), (0,255,0), 1, cv2.LINE_AA) # 显示并保存结果 cv2.imwrite('test3_r.jpg', img0) cv2.imshow("LSD", img0) cv2.waitKey(0) cv2.destroyAllWindows() 4.3 效果展示与分析

在这里插入图片描述 上图展示了FLD直线检测算法的检测效果。通过观察我们可以发现该算法具有很好的检测效果,基本上可以检测出图中所有的直线,和LSD的性能类似,具体使用哪种算法需要你根据自己的应用场景去进行选择。

5、EDlines直线检测算法 EDlines-论文链接-代码链接

5.1 EDlines算法简介

Dlines直线检测算法是在该论文中提出的。本文提出了一个快速、无参数的线段检测器,命名为EDLines (Akinlar and Topal, 2011),它产生强大的和准确的结果,比最快的已知线段检测器速度更快,达到11倍;换句话说,the LSD by Grompone von Gioi et al. (2008a,b, 2010). 我们的探测器还包括一个线的验证步骤定于亥姆霍兹原理Helmholtz principle (Desolneux et al., 2008),这让它控制错误检测的数量。 EDLines得到的结果,我们看到的是,LSD非常相似,有所有主要的线段检测,并有极少数误报。此外, EDLines运行实时以炫目的速度为9.45毫秒,约10倍的速度比LSD对给定的图像。

5.2 EDlines算法实现步骤

步骤1-首先,给定一个灰度图像,运行新的边缘检测、边缘绘制(ED)算法,产生一套干净的,像素相邻的链,我们称之为边缘。边缘线段直观地反应对象的边界。 步骤2-然后,利用直线度准则,即最小二乘直线拟合法,从生成的像素链中提取线段。 步骤3-最后,线的验证步骤定于亥姆霍兹原理Helmholtz principle (Desolneux et al., 2008; Grompone von Gioi et al.,2008a)是用来消除虚假线段的检测。

5.3 EDlines算法代码实战 下面仅仅展示了主函数的代码,具体的代码请在网盘链接中下载。

#include "EDLib.h" #include using namespace cv; using namespace std; int main() { //***************************** ED Edge Segment Detection ***************************** //Detection of edge segments from an input image string img_name = "test3.jpg"; Mat testImg = imread(img_name, 0); // imshow("Source Image", testImg); //Call ED constructor ED testED = ED(testImg, SOBEL_OPERATOR, 36, 8, 1, 10, 1.0, true); // apply ED algorithm //Show resulting edge image Mat edgeImg = testED.getEdgeImage(); //imshow("Edge Image - PRESS ANY KEY TO CONTINUE", edgeImg); //waitKey(); //Output number of segments int noSegments = testED.getSegmentNo(); std::cout


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有