Hough变换是一种检测、定位直线和解析曲线的有效方法。是把二值图变换到Hough参数空间,在参数空间用极值点的检测来完成目标的检测和分割 。
原理
首先,我们可知对一直角坐标系中的直线其方程可写为:ρ=xsinθ+ycosθ\rho=xsin\theta+ycos\thetaρ=xsinθ+ycosθ,即参数ρ\rhoρ和θ\thetaθ可确定一条直线。
其中ρ\rhoρ是原点到直线的距离,θ\thetaθ是该直线的法线与X轴的夹角。
那么对于X-Y平面内的点(x0,y0)可以转换为:ρ=x0sinθ+y0cosθ=Asin(α+θ)\rho=x_0sin\theta+y_0cos\theta=Asin(\alpha+\theta)ρ=x0sinθ+y0cosθ=Asin(α+θ),其中α=arctan(x0/y0);A=x02+y02\alpha=arctan(x_0/y_0);A=\sqrt {x_0^2+y_0^2}α=arctan(x0/y0);A=x02+y02。这在ρ\rhoρ-θ\thetaθ平面中是一条正弦曲线,而初始角α\alphaα和振幅AAA随x0和y0的值而变。
如果将X-Y平面内一条直线上的点都变换到ρ\rhoρ-θ\thetaθ平面中,所有的正弦曲线都将经(ρ0\rho_0ρ0,θ0\theta_0θ0),所有正弦曲线在ρ\rhoρ-θ\thetaθ平面中的其他位置都不相交。
也就是说,原直线上的点经转换后经过点(ρ0\rho_0ρ0,θ0\theta_0θ0)的次数为无穷次,其他位置均为一次。
因此,为检测图像中的直线,我们只需建立二维数组A(ρ\rhoρ,θ\thetaθ),对二值图像上的目标点以θ\thetaθ不断变化算出ρ\rhoρ,使得A中的对应元素累加,即A(ρ\rhoρ,θ\thetaθ)+=1,最后找到数组中最大值的点就是二值图中最长直线的参数。
代码
def Hough(img,origin,delta=0):
res=origin.copy()
thetas=np.deg2rad(np.arange(0.0,180.0,1))
row,col=img.shape
rhomax=int(round(np.sqrt(row*row+col*col)))
#因为ρ会存在负值,所以要先右移,后面减去即可
A=np.zeros((2*rhomax,len(thetas)),np.int32)
for x in range(row):
for y in range(col):
if img[x,y]>0:
for i in range(len(thetas)):
rho=int(round(x*np.cos(thetas[i])+y*np.sin(thetas[i])))
rho+=rhomax
A[rho,i]+=1
#数组中最大值索引
(maxr,maxt)= np.unravel_index(A.argmax(),A.shape)
theta=thetas[maxt]
#标记出最长直线
for x in range(row):
for y in range(col):
if img[x,y]>0:
rho=int(x*np.cos(theta)+y*np.sin(theta))
rho+=rhomax
if abs(rho-maxr)<=delta:
res[x,y]=[0,0,255]
return maxr-rhomax,theta,res