霍夫变换Hough
霍夫变换(Hough)是一个非常重要的检测间断点边界形状的方法。它通过将图像坐标空间变换到参数空间,来实现直线与曲线的拟合。主要用途就是找到图片中的直线或圆形区域。
1.直线检测
1.1 直线坐标参数空间
在图像x−y
坐标空间中,经过点
(xi,yi)
的直线表示为:
yi=axi+b(1)
其中,参数a为斜率,b为截矩。
通过
点(xi,yi)的直线有无数条,且对应于不同的
a和b
值。
如果将xi
和
yi
视为常数,而将原本的参数a和b看作变量,则式子(1)可以表示为:
b=−xia+yi(2)
这样就变换到了参数平面a−b
。这个变换就是直角坐标中对于
(xi,yi)
点的Hough变换。
该直线是图像坐标空间中的点(xi,yi)
在参数空间的唯一方程。考虑到图像坐标空间中的另一袋奶
(xj,yj)
,它在参数空间中也有相应的一条直线,表示为:
b=−xja+yj(3)
这条直线与点(xi,yi)
在参数空间的直线相交于一点
(a0,b0),如图所示:
图像坐标空间中过点
(xi,yi)和点
(xj,yj)的直线上的每一点在参数空间
a−b上各自对应一条直线,这些直线都相交于点
(a0,b0),而
a0、b0就是图像坐标空间
x−y中点
(xi,yi)和点
(xj,yj)
所确定的直线的参数。
反之,在参数空间相交于同一点的所有直线,在图像坐标空间都有共线的点与之对应。根据这个特性,给定图像坐标空间的一些边缘点,就可以通过Hough变换确定连接这些点的直线方程。
具体计算时,可以将参数空间视为离散的。建立一个二维累加数组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峰值等等,它们对应于原图中共线点略少一些的直线。
import
numpy
as
np
import
matplotlib.pyplot
as
plt
import
cv2
import
imgHelp
image
=
cv2.imread(
'imgs/5.jpg'
)
gray
=
cv2.GaussianBlur(cv2.cvtColor(image,cv2.COLOR_RGB2GRAY),(
7
,
7
),
3
)
fft_img
=
imgHelp.fftPic(gray,
30
)
h_threshold
=
100
l_threshold
=
50
edges
=
cv2.Canny(gray,l_threshold,h_threshold)
rho
=
1
theta
=
np.pi
/
180
threshold
=
150
min_line_length
=
1
max_line_gap
=
10
line_image
=
np.copy(image)
lines
=
cv2.HoughLinesP(edges, rho, theta, threshold, np.array([]),min_line_length, max_line_gap)
for
line
in
lines:
for
x1,y1,x2,y2
in
line:
cv2.line(line_image,(x1,y1),(x2,y2),(
255
,
0
,
0
),
5
)
circles_im
=
np.copy(image)
circles
=
cv2.HoughCircles(edges, cv2.HOUGH_GRADIENT,
1
,
minDist
=
35
,
param1
=
100
,
param2
=
20
,
minRadius
=
20
,
maxRadius
=
40
)
circles
=
np.uint32(np.around(circles))
for
i
in
circles[
0
,:]:
cv2.circle(circles_im,(i[
0
],i[
1
]),i[
2
],(
0
,
255
,
0
),
2
)
f,(a1,a2,a3,a4,a5,a6)
=
plt.subplots(
1
,
6
,
figsize
=
(
600
,
400
))
a1.set_title(
"oraginal image"
)
a1.imshow(image)
a2.set_title(
"gra"
)
a2.imshow(gray,
cmap
=
"gray"
)
a3.set_title(
"fft"
)
a3.imshow(fft_img,
cmap
=
"gray"
)
a4.set_title(
"edges"
)
a4.imshow(edges,
cmap
=
"gray"
)
a5.set_title(
"line_image"
)
a5.imshow(line_image)
a6.set_title(
"circles_im"
)
a6.imshow(circles_im)
plt.show()