原理
x-y坐标系中直线方程为y=ax+b
x-y坐标系中的每一个点在,在a-b坐标系中对应一条直线
x-y坐标系*线的点集,在a-b坐标系中对应一个线束(射影几何中的概念),线束的中心(a’,b’),在x-y平面中可以确定一条直线
但是直线方程y=ax+b不能表示斜率无限大的直线,所用改用直线方程:
xcosθ+ysinθ=ρ
x-y坐标系上的每一点在参数空间θ-ρ对应一条正弦线
x-y坐标系上共线的点集,在θ-ρ空间中有一组正弦线,并且交于一点(θ’,ρ’),在x-y平面中可确定一条直线
将图像空间(x-y平面)中所有点映射到θ-ρ空间(实际上是二维矩阵),这个二维矩阵叫做“累计数组”或“累加器”。累计数组中值较大的元素,往往对应着图像中的直线。
若图像平面上有直线L1(长度300像素)和L2(长度20像素),在累计数组中分别对应两个元素a1(其值≥300,为什么是≥300?图像中必然存在其它很多干扰点对应的正弦线穿过元素对应的θ-ρ空间中的点)和a2(其值≥20)
所以有两个问题需要注意:
第一,如何找到累计数组中的大值元素;
第二,有些大值元素在图像中并无确切直线与之对应;
对于第一个问题的解决办法较多。对于第二个问题,恐怕要预先知道图中直线的数量。
Matlab中hough函数的应用
检测函数
[H, theta, rho] = hough(BW)
[H, theta, rho] = hough(BW,ParameterName, ParameterValue)
BW:二值图
ParameterName:'RhoResolution'或'Theta'
RhoResolution-指定在累计数组中(检测极值)的检测间隔?默认为1
Theta-指定检测的角度范围(不超过-90~90度)以及间隔,例如-90:0.5:89.5,默认-90:1:89
H:累计数组
Theta:H对应的θ,实际上H的大小就是Rho×Theta
Rho:H对应的ρ
这两个参数值的注意,RhoResolution太大覆盖不到极值点,检测到一些不对应直线的次极值,如下图左;Theta范围设置小了显然会把某些极值排除在外,如下图右。故Theta推荐使用全范围,并小的角度间隔,如-90:0.5:89.5
然而,参数RhoResolution还有些问题。
下图左为原图,下图右为canny检测到的边缘。
[H, theta, rho] = hough(f,'RhoResolution',1.2,'Theta',-90:0.5:89.5);% 检测到如下结果:
将参数RhoResolution减小至0.2,却检测到如下结果:(表示不解)
将参数RhoResolution减小至10,却检测到如下结果:
峰值提取
peaks = houghpeaks(H,numpeaks)
peaks = houghpeaks(...,param1, val1, param2, val2)
H:累计数组;
Numpeaks:指定需要检测的峰值个数;
Param1:可以是'Threshold'或'NHoodSize'
'Threshold'-指定峰值的域值,默认是0.5*max(H(:))
'NHoodSize'-是个二维向量[m,n],检测到一个峰值后,将峰值周围[m,n]内元素置零。
画直线段
lines = houghlines(BW,theta, rho, peaks)
lines = houghlines(...,param1, val1, param2, val2)
BW:二值图
Theta、rho、peaks:分别来自函数hough和houghpeaks
Lines:结构数组,大小等于检测到的直线段数,每个单元包含
Point1、point2:线段的端点
Theta、rho:线段的theta和rho