opencv3中加入了LSD直线检测,然后在opencv4中因为Licence原因又去掉了LSD直线检测。
除了LSD,opencv中还有其他直线检测算法。
参考:OpenCv–霍夫直线变换(检测直线)
# 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()
# 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()
参考:直线检测算法汇总
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
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倍左右。
参考:直线检测算法汇总