opencv3中加入了LSD直线检测,然后在opencv4中因为Licence原因又去掉了LSD直线检测。

除了LSD,opencv中还有其他直线检测算法。

1、霍夫变换检测直线

参考:OpenCv–霍夫直线变换(检测直线)

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、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、EDlines直线检测算法

EDlines-论文链接-代码链接

4.1 EDlines算法简介
  EDlines直线检测算法是在该论文中提出的。本文提出了一个快速、无参数的线段检测器,命名为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对给定的图像。

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

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

#include "EDLib.h"
#include <iostream>

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 << "Number of edge segments: " << noSegments << std::endl;
		
	//Get edges in segment form (getSortedSegments() gives segments sorted w.r.t. legnths) 
	std::vector< std::vector<Point> > segments = testED.getSegments();
	
	
	//***************************** EDLINES Line Segment Detection *****************************
	//Detection of line segments from the same image
	EDLines testEDLines = EDLines(testImg);
	Mat lineImg = testEDLines.getLineImage();	//draws on an empty image
	imwrite("test3_r.jpg", lineImg);
	// imshow("Line Image 1 - PRESS ANY KEY TO CONTINUE", lineImg);

	//Detection of lines segments from edge segments instead of input image
	//Therefore, redundant detection of edge segmens can be avoided
	testEDLines = EDLines(testED);
	lineImg = testEDLines.drawOnImage();	//draws on the input image
	imwrite("test3_a.jpg", lineImg);
	imshow("Line Image 2  - PRESS ANY KEY TO CONTINUE", lineImg);

	//Acquiring line information, i.e. start & end points
	vector<LS> lines = testEDLines.getLines();
	int noLines = testEDLines.getLinesNo();
	std::cout << "Number of line segments: " << noLines << std::endl;
	waitKey();

我们可以发现:1)该算法能获得和LSD类似的检测结果;2)该算法抑制了一部分小的误检的直线;3)该算法具有更快的运行速度,是LSD的10倍左右。

参考:直线检测算法汇总

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐