十六 直线检测

一、霍夫直线变换原理

推文:Opencv学习笔记-----霍夫变换直线检测及原理理解

推文:OpenCV-Python教程(9、使用霍夫变换检测直线)

Hough变换是经典的检测直线的算法。其最初用来检测图像中的直线,同时也可以将其扩展,以用来检测图像中简单的结构。

1、对于直角坐标系中的任意一点A(x0,y0),经过点A的直线满足Y0=k*X0+b.(k是斜率,b是截距)

2、那么在X-Y平面过点A(x0,y0)的直线簇可以用Y0=k*X0+b表示,但对于垂直于X轴的直线斜率是无穷大的则无法表示。因此将直角坐标系转换到极坐标系就能解决该特殊情况。

3、在极坐标系中表示直线的方程为ρ=xCosθ+ySinθ(ρ为原点到直线的距离),如图所示:

 

4、原理过程

  • 如上图,假定在一个8*8的平面像素中有一条直线,并且从左上角(1,8)像素点开始分别计算θ为0°、45°、90°、135°、180°时的ρ;
  • 图中可以看出ρ分别为1、(9√2)/2、8、(7√2)/2、-1,并给这5个值分别记一票;
  • 同理计算像素点(3,6)点θ为0°、45°、90°、135°、180°时的ρ,再给计算出来的5个ρ值分别记一票;
  • 此时就会发现ρ = (9√2)/2的这个值已经记了两票了;
  • 以此类推,遍历完整个8*8的像素空间的时候ρ = (9√2)/2就记了5票, 别的ρ值的票数均小于5票;
  • 所以得到该直线在这个8*8的像素坐标中的极坐标方程为 (9√2)/2=x*Cos45°+y*Sin45°;
  • 到此该直线方程就求出来了。(PS:但实际中θ的取值不会跨度这么大,一般是PI/180)。

二、霍夫直线检测的两种方法

1.获取灰度图像
2.canny边缘检测
3.获取霍夫直线信息
4.算出直线位置,画出每条直线

1、HoughLines霍夫变换

(1)HoughLines函数

def HoughLines(image, rho, theta, threshold, lines=None, srn=None, stn=None, min_theta=None, max_theta=None): 

cv2.HoughLines函数输出的是很多的[float, float]形式的数组,其中每个值表示检测到的线(ρ , θ)中浮点点值的参数。

cv.HoughLines(edges,1,np.pi/180,200)

第一个参数image:是canny边缘检测后的图像

第二个参数rho和第三个参数theta:对应直线搜索的步长。在本例中,函数将通过步长为1的半径和步长为π/180的角来搜索所有可能的直线。

最后一个参数threshold:是经过某一点曲线的数量的阈值,超过这个阈值,就表示这个交点所代表的参数对(rho, theta)在原图像中为一条直线

(3)代码实现

 1 import cv2 as cv
 2 import numpy as np
 3 
 4 def houghlines(image):
 5     gray = cv.cvtColor(image,cv.COLOR_BGR2GRAY)
 6     #用canny边缘检测,下阈值是50,上阈值是150,算子大小只能是1,3,5,7
 7     edges = cv.Canny(gray,150,250,apertureSize=3)
 8     # 函数将通过步长为1的半径和步长为π/180的角来搜索所有可能的直线
 9     #lines.shape = (113,1,2)
10     lines = cv.HoughLines(edges,1,np.pi/180,150)        #通过更改canny的上下阈值和houghlines的阈值来调整!!
11     for line in lines:
12         rho,theta = line[0]   #因为lines的第二维只有一个,所以得用0
13         a = np.cos(theta)
14         b = np.sin(theta)
15         x0 = rho * a
16         y0 = rho * b
17         x_max = int(x0 + 1000*(-b))
18         y_max = int(y0 + 1000*(a))
19         x_min = int(x0 - 1000*(-b))
20         y_min = int(y0 - 1000*(a))
21         #在image上画线,起点(x_max,y_max),终点(x_min,y_min),颜色(0,0,255),线条宽度1
22         cv.line(image,(x_max,y_max),(x_min,y_min),(0,0,255),1)
23     cv.imshow('imageline',image)
24 src = cv.imread('road.jpg')
25 cv.namedWindow('input image',cv.WINDOW_NORMAL)
26 cv.imshow('input image',src)
27 houghlines(src)
28 cv.waitKey(0)
29 cv.destroyAllWindows()

2、HoughLinesP概率霍夫变换(是加强版)使用简单,效果更好,检测图像中分段的直线(而不是贯穿整个图像的直线)

(1)HoughLinesP函数

 HoughLinesP(image, rho, theta, threshold, lines=None, minLineLength=None, maxLineGap=None): 

cv.HoughLinesP(edges, 1, np.pi / 180, 100, minLineLength=50,maxLineGap=10)

第一个参数是需要处理的原图像,该图像必须为cannay边缘检测后的图像;


第二和第三参数:步长为1的半径和步长为π/180的角来搜索所有可能的直线

第四个参数是阈值,概念同霍夫变换

第五个参数:minLineLength-线的最短长度,比这个线短的都会被忽略。

第六个参数:maxLineGap-两条线之间的最大间隔,如果小于此值,这两条线就会被看成一条线。

(3)代码实现

 1 import cv2 as cv
 2 import numpy as np
 3 
 4 def houghlinesp(image):
 5     gray = cv.cvtColor(image,cv.COLOR_BGR2GRAY)
 6     edges = cv.Canny(gray,50,150,apertureSize=3)
 7     lines = cv.HoughLinesP(edges,1,np.pi/180,100,minLineLength=300,maxLineGap=10)
 8     for line in lines:
 9         print(type(line))
10         x1,y1,x2,y2 = line[0]
11         cv.line(image,(x1,y1),(x2,y2),(0,0,255),2)
12     cv.imshow('line_demo',image)
13 img = cv.imread('road.jpg')
14 cv.namedWindow('input image',cv.WINDOW_FREERATIO)
15 cv.imshow('input image',img)
16 houghlinesp(img)
17 cv.waitKey(0)
18 cv.destroyAllWindows()

原文地址:https://www.cnblogs.com/pacino12134/p/9879635.html