目录
霍夫变换原理
映射
峰值统计
总结
OpenCv中的霍夫线检测
霍夫变换运用两个坐标空间之间的变换,将在一个空间中具有相同形状的曲线或直线映射到另一个坐标空间的一个点上形成峰值,从而把检测任意形状的问题转化为统计峰值问题。
可以看出,要搞清楚的主要问题:
比如说,当霍夫空间参数为(k,q)时:
在笛卡尔坐标平面(x、y坐标系)中的一条直线(y=kx+q)对应霍夫空间的一个点(k,q)。
反过来同样成立,笛卡尔坐标系中的一个点对应着霍夫空间种的一条直线。
并且经过验证,若笛卡尔坐标系中n点在同一直线上,那么在霍夫空间中n线就交于同一点。
以上就是映射,但是未考虑到完整的情况,如果在笛卡尔坐标系中有线是垂直x轴的(也就是k=∞),那么在霍夫空间中这个点要画到无穷远处去了。因此应对笛卡尔坐标系进行极坐标变换后再霍夫空间参数设为ρ,θ。
可以看出点映射直线,变成了点映射曲线,但是该相交还是相交。
上面已经提到,原坐标系空间中的在一条直线上的点映射成霍夫空间中的一族曲线后交于同一点。
那么峰值统计要统计的就是霍夫空间中每个点被经过的曲线数量。
为什么?因为当霍夫空间中一个点被经过的曲线越多,那就说明原空间中越多的点在同一条直线上,那就说明这条“直线”是直线的概率越大。(总所周知,直线其实就是无数个点连在一起...)
那怎么统计呢?对霍夫空间进行离散化,然后对网格单元进行检查,累加计数值最大的网格,其坐标值(ρ0, θ0)就对应图像空间中所求的直线。
原理步骤
1. 霍夫变换
2.对每一点统计峰值
3.设置阈值,得到直线
当然你也可以在霍夫变换之前进行平滑去噪、Canny边缘检测等其他操作。
opencv中存在两种方法:
1.霍夫线检测:
lines = cv.HoughLines( image, rho, theta, threshold[, lines[, srn[, stn[, min_theta[, max_theta]]]]] )
import cv2
import numpy as np
img = cv2.imread('dave.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray,50,150,apertureSize = 3)
lines = cv2.HoughLines(edges,1,np.pi/180,200)
for rho,theta in lines[0]:
a = np.cos(theta)
b = np.sin(theta)
x0 = a*rho
y0 = b*rho
x1 = int(x0 + 1000*(-b))
y1 = int(y0 + 1000*(a))
x2 = int(x0 - 1000*(-b))
y2 = int(y0 - 1000*(a))
cv2.line(img,(x1,y1),(x2,y2),(0,0,255),2)
cv2.imwrite('houghlines3.jpg',img)
2.概率霍夫线检测:
lines = cv.HoughLinesP( image, rho, theta, threshold[, lines[, minLineLength[, maxLineGap]]] )
import cv2
import numpy as np
img = cv2.imread('dave.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray,50,150,apertureSize = 3)
minLineLength = 100
maxLineGap = 10
lines = cv2.HoughLinesP(edges,1,np.pi/180,100,minLineLength,maxLineGap)
for x1,y1,x2,y2 in lines[0]:
cv2.line(img,(x1,y1),(x2,y2),(0,255,0),2)
cv2.imwrite('houghlines5.jpg',img)
相关参考:
OpenCV霍夫变换系列(前篇)-经典霍夫线变换
图像直线检测——霍夫线变换
霍夫变换直线检测(Line Detection)原理及示例