Hough变换检测直线

1、原理
对于一幅二值图像(一般由对普通图像进行边缘提取得到),对于这些边缘中的直线进行识别和检测是通过以下原理进行的。对于每个点A,通过这个点的直线可以用两个参数来描述,我们一般使用斜率k和截距b。对于所有通过这个 点的直线,随着k和b的变换,于是在k和b的参数空间也构成了一条直线。直线上的每个点,都代表着一对(k,b)参数,也就是对应通过指定点的一条直线。对于另外一个点B,通过它的所有直线在参数空间也构成一条直线。这条直线和前一条直线相交,交点就代表既过点A又过点B的直线。推广开来,如果在参数空间有很多直线都交于一点,就说明交点(k,b)代表的这条直线在图像上会通过很多点,这就是我们检测出来的直线。

在实际中,由于斜率k有可能为无穷大,此时通过在参数空间检测交点的方式就会失效。因此一般采用另外两组参数, ρ θ 。其中 ρ 代表由原点(一般是图像中心)到直线的距离, θ 代表直线的倾角。在这个参数空间里,过一点A的所有直线映射到参数空间会形成一条正弦曲线。同样的,交点代表同时过几个点的直线,相交于同一点的曲线越多,说明这组参数所代表的直线越显著。
(本来应该配几张图的,但赶稿要紧,等有空再来添几张图吧)

2、Matlab函数
知道了原理,我们就可以自己来实现Hough变换检测直线的代码。但实际上这个算法已经非常成熟了,Matlab里就有现成的函数可以用。具体的代码可以参考冈萨雷斯的《数字图像处理》这本书。虽然可以不用自己写代码,但是理解原理能够方便我们更加透彻地理解这些函数的用法和各个参数的意义。

在Matlab里,要用hough变换进行直线检测需要用到3个函数。hough,houghpeaks和houghlines。其实一般还需要先进行边缘检测,使用的函数是edge,这里就不说了。

首先是hough函数。hough函数的一般用法是
[H,theta,rho]=hough(bw,’ThetaResolution’,val1,’RhoResolution’,val2);
其中bw是输入的二值图像,后两个参数分别指定 θ ρ 的分辨精度,如果不指定,就都是1。其中 θ 的取值为-90°~90°, ρ 的取值为-r~r,r为图像对角线长度的一半,这是图像中心到图像上任意直线的最长距离。输出参数theta和rho列出了在指定分辨精度下 θ rho 的离散取值点,H是一个矩阵,有时称为hough变换矩阵,是一个 Nρ 行, Nθ 列的矩阵,矩阵的行列坐标代表一组 θ ρ 的参数,每个矩阵元素的值代表相交于这组参数下曲线的数目。

接下来是houghpeaks函数。这个函数是在hough函数后面使用,因为它要用到hough函数的输出参数。这个函数的作用是在hough变换矩阵中找峰值,因为H矩阵中的元素值越大,代表这组参数代表的直线经过的点越多,即这条直线越显著。它的用法是:
peaks=houghpeaks(H,Npeaks,’Threshold’,val1,’NHoodSize’,val2);
其中H就是上一步得到的hough变换矩阵,Npeaks代表在这个矩阵中找最多Npeaks个峰值。可选参数Threshold指定了峰值的判断阈值,即超过某个值就认为是峰值,默认值是0.5*max(H(:));NHoodSize指定了邻域抑制的邻域大小,即一个峰值的附近不允许有另一个峰值,靠的太近的峰值应该认为是同一个。默认值是不小于size(H)/50的最小奇数。

找出峰值以后,接下来就是利用houghlines根据peaks列出的参数对,生成检测出来的直线。其用法为:
lines=houghlines(bw,theta,rho,peaks);
输入参数bw为原始的二值图像,因为检测出的直线参数还需要和原图像对应起来进行查找和判定。
theta和rho就是第一步使用hough函数时得到的输出参数,peaks为上一步得到的峰值位置。因为peaks代表的峰值位置只是H矩阵里峰值元素的坐标,即只是行列坐标的索引,具体代表的参数theta和rho,还是要通过查找之前生成的theta和rho向量,才能知道。
输出参数lines是一个结构体向量,结构体有下面4个属性:
point1: 检测出的直线起点
point2: 直线终点
theta: 直线的theta参数
rho: 直线的rho参数
根据直线的起点和终点,就能在图像上画出检测出的线段。
根据theta和rho参数,也能画出检测出的直线,不过只能画出直线,不能确定起始点和终止点。

你可能感兴趣的:(技术理论)