一、霍夫直线变换原理
推文: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()