|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
0 v9 t/ @$ w4 w. w霍夫变换Hough6 K! B7 }" J e1 D
霍夫变换(Hough)是一个非常重要的检测间断点边界形状的方法。它通过将图像坐标空间变换到参数空间,来实现直线与曲线的拟合。
( I' f8 b# y* a _9 Z- b5 U" s: p1 Z9 K
1.直线检测
; z' w! ~ t2 F6 d( S) f# ]0 j* m5 `! r3 s& v+ ^2 M/ J, `) X
1.1 直线坐标参数空间$ f) `: T; G6 J
R$ E, p$ u, N0 r6 f在图像x−y坐标空间中,经过点(xi,yi)的直线表示为:
( s" B4 A3 ]2 R7 Y8 W
]( O, g* ]/ A1 d. d# Eyi=axi+b(1)
! @9 C1 u8 p' {
* g/ b6 Y$ d+ @5 Y; W其中,参数a为斜率,b为截矩。 3 e% b$ {5 i3 `
0 n# c+ o' J: y) n通过点(xi,yi)的直线有无数条,且对应于不同的a和b值。
$ p- k. Y u: S K3 I! P& G' l" l+ n* S0 o' A
如果将xi和yi视为常数,而将原本的参数a和b看作变量,则式子(1)可以表示为:+ A3 Q! N" H" V/ `
: f9 O6 _7 c7 H0 `5 N B3 nb=−xia+yi(2)2 J, A; ]' m1 a7 \+ @
H" P3 c- Y3 V! A; w" x这样就变换到了参数平面a−b。这个变换就是直角坐标中对于(xi,yi)点的Hough变换。( R/ A' z. M% o6 w" G
$ _4 f: i5 y/ s7 P, G该直线是图像坐标空间中的点(xi,yi)在参数空间的唯一方程。考虑到图像坐标空间中的另一袋奶(xj,yj),它在参数空间中也有相应的一条直线,表示为:
2 k8 f: n3 p z% M p6 @' T! J, n
b=−xja+yj(3)
4 G" u, A& d1 T/ k
" r) N3 `, G7 R1 i# q+ Z这条直线与点(xi,yi)在参数空间的直线相交于一点(a0,b0),如图所示:
8 D3 P I' T/ x$ s& u! h% v# l ?7 X" a
. z- q" U3 E8 ^
$ i4 F9 l, v8 z, o( J
图像坐标空间中过点(xi,yi)和点(xj,yj)的直线上的每一点在参数空间a−b上各自对应一条直线,这些直线都相交于点(a0,b0),而a0、b0就是图像坐标空间x−y中点(xi,yi)和点(xj,yj)所确定的直线的参数。
: s; j0 }! n% w# R/ k, c; V2 x' u
4 H4 Z# i1 z) V2 G! l* m反之,在参数空间相交于同一点的所有直线,在图像坐标空间都有共线的点与之对应。根据这个特性,给定图像坐标空间的一些边缘点,就可以通过Hough变换确定连接这些点的直线方程。
* v8 E6 K& o v7 q' Q
$ g, |: ~% [/ [0 F" ^! c
( u: c+ l* R$ J& u7 M. x具体计算时,可以将参数空间视为离散的。建立一个二维累加数组A(a,b),第一维的范围是图像坐标空间中直线斜率的可能范围,第二维的范围是图像坐标空间中直线截矩的可能范围。开始时A(a,b)初始化为0,然后对图像坐标空间的每一个前景点(xi,yi),将参数空间中每一个a的离散值代入式子(2)中,从而计算出对应的b值。每计算出一对(a,b),都将对应的数组元素A(a,b)加1,即A(a,b)=A(a,b)+1。所有的计算结束之后,在参数计算表决结果中找到A(a,b)的最大峰值,所对应的a0、b0就是源图像中共线点数目最多(共A(a,b)个共线点)的直线方程的参数;接下来可以继续寻找次峰值和第3峰值和第4峰值等等,它们对应于原图中共线点略少一些的直线。
1 U7 z+ \8 j. H! T/ O
" L* r( D# u$ w4 i$ ?$ l7 d( G注意:由于原图中的直线往往具有一定的宽度,实际上相当于多条参数极其接近的单像素宽直线,往往对应于参数空间中相邻的多个累加器。因此每找到一个当前最大的峰值点后,需要将该点及其附近点清零,以防算法检测出多条极其邻近的“假”直线。" p/ Q3 j. _5 \( @
( }! [$ Y+ h0 W8 s6 S3 f# w5 w
. j" c5 w7 ?6 t5 X! B# P8 t; R对于上图的Hough变换空间情况如下图所示。
6 F$ r: I; ~; V: ^+ G1 r
1 t0 m- j/ K5 `* V- K! B
" X% |5 F+ J* E0 w/ E
) h ~- X% d7 r
这种利用二维累加器的离散方法大大简化了Hough变换的计算,参数空间a−b上的细分程度决定了最终找到直线上点的共线精度。上述的二维累加数组A也被称为Hough矩阵。
* o) e- I( ^' A0 v
( e# O! z' M" X* Q注意:使用直角坐标表示直线,当直线为一条垂直直线或者接近垂直直线时,该直线的斜率为无限大或者接近无限大,从而无法在参数空间$a-b$上表示出来。为了解决这个问题,可以采用极坐标。
# ?( |) w9 |# E, I5 @( c) l4 ~) o( S3 `
. z& S6 N) \0 ?/ g1.2 极坐标参数空间
; E$ G4 U* i2 d1 u4 U, J+ c' R0 n, e- Z& z9 C- B. @
极坐标中用如下参数方程表示一条直线。
( X! R8 X6 e8 W1 j' f" {
2 a+ U4 b+ I0 a1 d: G% V+ Mρ=xcosθ+ysinθ(4) ~: V. M9 T) z* {
# M' ?$ I7 U. ]+ I其中,ρ代表直线到原点的垂直距离,θ代表x轴到直线垂线的角度,取值范围为±90°,如图所示。 ; @9 M9 U1 n. \% z( P( d
- c1 I' ?. G7 {7 S$ y" m: ~
) D3 Y1 E/ G/ y2 X与直角坐标类似,极坐标中的Hough变换也将图像坐标空间中的点变换到参数空间中。 6 g( ^3 o% p N( Z7 t
在极坐标表示下,图像坐标空间中共线的点变换到参数空间中后,在参数空间都相交于同一点,此时所得到的ρ、θ即为所求的直线的极坐标参数。与直角坐标不同的是,用极坐标表示时,图像坐标空间的共线的两点(xi,yi)和(xj,yj)映射到参数空间是两条正弦曲线,相交于点(ρ0,θ0),如上图所示。
6 Z' j& S% B- E! v8 o2 }7 ~: S3 Q8 w8 A0 e, N9 `
具体计算时,与直角坐标类似,也要在参数空间中建立一个二维数组累加器A,只是取值范围不同。对于一副大小为D×D的图像,通常ρ的取值范围为[−2–√D/2,2–√D/2],θ的取值范围为[−90°,90°]。计算方法与直角坐标系中累加器的计算方法相同,最后得到最大的A所对应的(ρ,θ)。) a% ]6 p3 Q3 R+ s( O' g# Z9 h! P
9 a3 n0 `6 X$ Y
2.曲线检测
& n+ g! j$ Y% a! E4 d4 s8 h+ d9 L- C# _
Hough变换同样适用于方程已知的曲线检测。, }% r8 ]1 U5 |8 r4 M3 \
$ c+ m' Q6 ~5 s, P# |图像坐标空间中的一条已知的曲线方程也可以建立其相应的参数空间。由此,图像坐标空间中的一点,在参数空间中就可以映射为相应的轨迹曲线或者曲面。- k# u& k- m; z; h7 X Y( e
& ?9 \: o. a6 ~% `& F) J
若参数空间中对应各个间断点的曲线或者曲面能够相交,就能找到参数空间的极大值以及对应的参数;若参数空间中对应各个间断点的曲线或者曲面不能相交,则说明间断点不符合某已知曲线。
: N }1 n: D/ M4 W" p% V5 v! M9 K. O0 ?$ n# w4 ~6 n; ^5 t
Hough变换做曲线检测时,最重要的是写出图像坐标空间到参数空间的变换公式。
l* {2 P4 H9 l5 b9 b2 ]4 i: i
" `. D9 Q$ {( ~) j& g9 q% y例如,对于已知的圆方程,其直角坐标的一般方程为:
( G* a3 p( A2 H3 Q1 d: e) @$ M/ E6 [/ H* y& ?5 {
(x−a)2+(y−b)2=r2(5)
! A9 r e6 d7 Z/ J- d* M! L. v' I; _$ K$ \8 L7 `
其中,(a,b)为圆心坐标,r为圆的半径。 " n* ?* e( k: |8 _+ @5 V) U4 o
/ i, x1 N n# j% E: X$ Y
那么,参数空间可以表示为(a,b,r),图像坐标空间中的一个圆对应参数空间中的一个点。
& _& X' _- a& o" w& Y3 u1 B; P+ h7 G6 H; Z5 J4 M$ ^; ]. q7 W
具体计算时,与前面讨论的方法相同,只是数组累加器为三维A(a,b,r)。
/ Z! O8 c$ l4 l. U. A( d1 k6 k" W _* H% k
计算过程是让a,b在取值范围内增加,解出满足上式的r值,每计算出一个(a,b,r)值,就对相应的数组元素A(a,b,r)加1.计算结束后,找到的最大的A(a,b,r)所对应的a,b,r就是所求的圆的参数。3 ~ c" e) m# M' L( g; A/ L' }
: I0 U! |; f9 ]8 {* R与直线检测一样,曲线检测也可以通过极坐标形式计算。 1 V3 c4 b$ c* E$ w/ A4 R
/ k! J2 s/ P! Z4 z6 T9 @- a
注意:通过Hough变换做曲线检测,参数空间的大小将随着参数个数的增加呈指数增长的趋势。所以在实际使用时,要尽量减少描述曲线的参数数目。因此,这种曲线检测的方法只对检测参数较少的曲线有意义。6 b9 N* r3 W; L+ v* k2 x9 x5 Z4 E8 y
, y6 [+ [3 G1 a$ L1 C% ]9 w
' q$ p# k' G# i: w! N3.任意形状的检测
& {- I/ Q V2 R# C6 Q- j1 u
4 I( A% P- s* H) J7 z Z3 o9 r这里所说的任意形状的检测,是指应用广义Hough变换去检测某一任意形状边界的图形。它首先选取该形状中的任意点(a,b)为参考点,然后从该任意形状图形的边缘每一点上,计算其切线方向ϕ和到参考点(a,b)位置的偏移矢量r,以及r与x轴的夹角α。6 [6 O) ^( f2 N3 c( c) H5 j! m( {+ @
5 N8 c% z, r1 `5 {4 l* b5 t! R参考点(a,b)的位置可由下式算出: + R: {% h6 \' A& N8 w) B% w0 ^1 E
/ [: Q* G) o! A ^4 S
a=x+r(ϕ)cos(α(ϕ))(6)
1 P! i4 |/ M" ~7 v" J+ {: s, J2 E( A2 F& W9 j- o
b=x+r(ϕ)sin(α(ϕ))(7)
- M* T: n7 u$ e, l( ^$ e) P1 P: o) _! y7 m, b1 R' [
8 K+ C2 }6 Q* m; A: E0 g* E
2.Hough变换直线检测的Matlab实现
# ^; V! f6 ^8 z; D; X2 d9 c5 K7 t [& {
通过Hough在二值图像中检测直线需要以下3个步骤。 . C3 |) l* U6 |3 \4 k; w. L
·>(1)利用hough()函数执行霍夫变换,得到霍夫矩阵。 0 _( h0 u' x" D G
·>(2)利用houghpeaks()函数在霍夫矩阵中寻找峰值点。
! }7 v1 w7 M" P ]$ P" W·>(3)利用houghlines()函数在之前2步结果的基础上得到原二值图像中的直线信息。) ~$ R1 w) i! M G, t! X! N
9 ?. R% x, s. W. e
2.1 霍夫变换–Hough+ v$ \# g+ y9 f7 n
# L* z; B( W" O' ] Z调用形式:
, n7 N/ l# Q" t; r4 ~3 t6 c. [6 t, S: l% B- ?' R
[H,theta,rho]=hough(BW,param1,value1,param2,value2)
- I1 f( i3 p: ?; K& r& K5 g( w+ F; e
参数说明:
1 b4 T% i1 ]4 b- `* r9 s+ C" N; w* k, [+ e. o
·BW是边缘检测后的二值图像; ; O2 B3 u! G. ^; M( j' m& S
·可选参数对param1,value1和param2,value2的合法取值如下:/ m/ `+ B% E# L
% v( K8 d$ u2 A
param取值 含义
) c1 r& [5 B! @( Y& v0 ZThetaResolution Hough矩阵中θ轴方向上单位区间的长度(以“度”为单位),可取(0,90)区间上的实数,默认为1* w' e0 [; g. B% t
RhoResolution Hough矩阵中\rho轴方向上单位区间的长度,可取(0,norm(size(BW)))区间上的实数,默认为1
1 i2 ]& I% k j. p
* p, G# n9 n$ C; y* Z
* Q$ H7 K# d+ R& e* w% T+ ]返回值:
4 S6 ~% ?; [, D# a* r1 o) c& |·H是变换得到的霍夫矩阵
% T- u3 R: E0 Z) M1 r) J" \·theta,rho分别对应于Hough矩阵每一列和每一行的\theta和\rho值组成的向量。9 e, Q6 ?5 e. ~7 _- C3 u
5 B9 y# _+ \+ ~: N' J/ R. D- 补充:[m,n] = size(X)
- 补充:norm的用法,matlab help norm
- NORM Matrix or vector norm.
- For matrices...
- 对于矩阵...
- NORM(X) is the largest singular value of X, max(svd(X)).
- NORM(X)是X的最大奇异值
- NORM(X,2) is the same as NORM(X).
- NORM(X,1) is the 1-norm of X, the largest column sum,
- = max(sum(abs(X))).
- NORM(X,inf) is the infinity norm of X, the largest row sum,
- = max(sum(abs(X'))).
- NORM(X,'fro') is the Frobenius norm, sqrt(sum(diag(X'*X))).
- NORM(X,P) is available for matrix X only if P is 1, 2, inf or 'fro'.
- For vectors...
- 对于向量...
- NORM(V,P) = sum(abs(V).^P)^(1/P).
- 返回向量A的p范数
- NORM(V) = norm(V,2).
- 返回向量A的2范数,即欧几里德范数。二范数等价于平方和开平方,Sqrt(X1^2+X2^2+...+Xn^2)
" U5 e: Q0 x+ _5 W6 y- F; b
* s/ \6 Z7 J; Y3 p7 C1 H0 @3 `$ U9 N& ? i. [, K/ t4 ?
2.2 寻找峰值–houghpeaks
) ^+ y: o' s1 }6 f) I) o6 A& s/ i) U+ e# X; L) f$ a. e' z( N+ e
调用形式:
: q/ q& l/ Q3 L$ u# H; `) G# O' x) Q: F
peaks=houghpeaks(H,numpeaks,param1,value1,param2,value2)2 Y" W2 p' {( ]! w& [5 a2 C
" P3 |; y7 z1 I
参数说明: 4 }7 e" R0 z5 {* {) s. j x1 q! [
·H是hough()函数得到的霍夫矩阵 0 W& {* n! G# a0 m( _9 g
·numpeaks是要寻找的峰值数目,默认为1
! l" e) `/ H2 L' U2 s·可选参数对param1,value1和param2,value2的合法取值如下:; }& x% u$ s0 G: \
& e' l7 `# N+ D) W, X
param取值 含义
( B$ \7 Z. w. A4 XThreshold 峰值的阈值,只有大于该阈值的店才被认为是可能的阈值,取值>0,默认为0.5×max(H(:))$ q; v% j, b ]5 g! O0 a: k" ~2 o
NHoodSize 在每次检测出一个峰值后,NhoodSize指出了在该峰值周围需要清零的领域信息。以[m,n]的形式给出,其中m、n均为正的奇数。默认为大于等于size(H)/50的最小奇数。
q9 W3 w- z) e2 |$ t8 g. k5 F" I( e! Y; R; w! P+ s) l3 j; O ]' W
+ [! L, v R. f5 d$ ?1 ]" |返回值: " u) l% a: i# V4 ?6 r. }" K
·peaks是一个Q×2的矩阵,每行的两个元素分别是某一峰值点再hough矩阵中的行、列索引,Q为找到的峰值点的数目。8 @+ t a4 p; W L9 u7 _3 r& R1 a
- @, p: g) M8 i& r. f b
% H+ O2 \6 z$ d, l5 Z- w2.3 提取直线段–houghlines+ r9 O8 E1 X9 w' d" `$ W6 w
. |- I! [0 C( [4 ^. s8 y
调用形式:
9 T$ K% a/ z7 ]8 o. O2 h8 u
2 I, K( @2 z8 X4 h Hlines=houghlines(BW,theta,rho,peaks,param1,value1,param2,value2)
% ]1 H) e, f( Z0 r. ~5 z0 w: B3 X5 @# T
参数说明: x" I/ H# n: `1 T. b1 q
·BW是边缘检测后的二值图像
' x9 @! }+ k- E·theta,rho分别对应于Hough矩阵每一列和每一行的θ和ρ值组成的向量。有hough()函数返回。
6 ^$ O# {( _0 Y·peaks是一个包含峰值点信息的Q×2的矩阵,由houghpeaks()函数返回。 2 ~3 E4 P: b" G7 P, }" w+ b
·可选参数对param1,value1和param2,value2的合法取值如下:# r# A9 r7 L* j9 D
* J& s# N m3 A8 P; m! r1 e1 g
param取值 含义- K+ ^: i' a7 I3 g
FillGap 线段合并的阈值:如果对应于Hough矩阵某一个单元格(相同的θ和ρ)的两条线段之间的距离小于 FillGap,则合并为一个直线段。默认值为20.
& q) k0 u+ f! [0 ^3 |MinLength 检测的直线段的最小长度阈值:如果检测出的直线段长度大于MinLength,则保留;丢弃小于MinLength的直线段。默认值为40.5 k5 z: E9 @% W1 @3 D; h
/ d8 N8 n: x5 w) V+ r
; {" A% `: C$ F+ Q返回值: 0 }+ m7 ?" L9 b2 Z) n
·lines是一个结构体数组,数组长度是找到的直线条数,而每一个数组元素(直线段结构体)的内部结构如下:: L+ [4 w: u; \3 D9 ]8 b
& W @! h5 w) O( J. |
域 含义9 G5 J+ K) o4 j) [' p
point1 直线段的端点14 F& ]1 Y( M, m& P- I# u: ~$ {
point2 直线段的端点23 b. v0 H& s2 P% {$ s
thea 对应在霍夫矩阵中的θ
0 |0 P" H% @! Q1 Qrho 对应在霍夫矩阵中的ρ* Y4 [8 N" X/ B. j) s) _
9 O" z3 E- I8 m3 R
: C9 e6 ^8 U! M6 q- v2.4 Hough变换的matlab实现
5 D& i5 L# J) ~$ y# z
, W1 o6 D' \9 Q! e C# h5 m( fmatlab中输入帮助命令:
4 z7 u1 z" Q( e: H4 ~0 o( Ehelp hough; help houghpeaks; help houghlines " W( z0 h* K, z, l2 g
就可以看到代码示例,很详细,其实用好帮助文档一切问题都可以解决。
6 h3 L5 f& o/ E+ P
& E" r" F& q c% V7 l* e1 s" nExample
8 X9 ?: }+ t" r' L9 C1 B) d0 Q) n" E/ y* Q" v6 z& a, \
Search for line segments corresponding to five peaks in the Hough
# q1 X4 K$ G& w6 b! Xtransform of the rotated circuit.tif image. Additionally, highlight
3 Z1 |( x9 d% Z5 L, Sthe longest segment.$ C" u9 m3 o/ [& g+ ~1 V
7 H* Q+ a! ], v6 U' x/ n3 K% }5 g
- I = imread('circuit.tif');
- rotI = imrotate(I,33,'crop');
- BW = edge(rotI,'canny');
- [H,T,R] = hough(BW);
- imshow(H,[],'XData',T,'YData',R,'InitialMagnification','fit');
- xlabel('\theta'), ylabel('\rho');
- axis on, axis normal, hold on;
- P = houghpeaks(H,5,'threshold',ceil(0.3*max(H(:))));
- x = T(P(:,2));
- y = R(P(:,1));
- plot(x,y,'s','color','white');
- % Find lines and plot them
- lines = houghlines(BW,T,R,P,'FillGap',5,'MinLength',7);
- figure, imshow(rotI), hold on
- max_len = 0;
- for k = 1:length(lines)
- xy = [lines(k).point1; lines(k).point2];
- plot(xy(:,1),xy(:,2),'LineWidth',2,'Color','green');
- % plot beginnings and ends of lines
- plot(xy(1,1),xy(1,2),'x','LineWidth',2,'Color','yellow');
- plot(xy(2,1),xy(2,2),'x','LineWidth',2,'Color','red');
- % determine the endpoints of the longest line segment
- len = norm(lines(k).point1 - lines(k).point2);
- if ( len > max_len)
- max_len = len;
- xy_long = xy;
- end
- end
- % highlight the longest line segment
- plot(xy_long(:,1),xy_long(:,2),'LineWidth',2,'Color','cyan');8 ^2 d, N9 N- n& X
$ h8 Z; ~( \8 h* W: N, h2 s/ j& F) k/ E5 ]8 Z. F- p% M# ^1 H
& T1 V$ k1 ~# e! T; O2 q
|
|