> 文章列表 > 霍夫变换及应用

霍夫变换及应用

霍夫变换及应用

霍夫变换及应用

霍夫变换概述

⚫ 霍夫变换(Hough Transform)是图像处理中的一种特征提取技术, 该过程在一个参数空间中通过计算累计结果的局部最大值得到一个符合该特定形状的集合作为霍夫变换的结果。
⚫ 霍夫变换在OpenCV中主要分两种:

霍夫线变换—检测直线(线段)

霍夫圆变换—检测圆

⚫ 用到的函数:

cv2.HoughLines()—标准霍夫变换、多尺度霍夫变换cv2.HoughLinesP()—累计概率霍夫变换cv2.HoughCricles()—霍夫圆变换

1)霍夫线变换

霍夫线变换是一种寻找直线的方法, 一般在使用霍夫变换前首先将图像进行边缘检测处理, 一般霍夫变换的输入为边缘二

值图。OpenCV支持三种不同的霍夫线变换, 包括:

◆标准霍夫变换(SHT)

◆多尺度霍夫变换(MSHT)------是SHT在多尺度下的一个变种

◆累计概率霍夫变换(PPHT)------是SHT的改进, 在一定范围内进行霍夫变换(减少计算时间和运算量)

使用函数对应关系:

标准霍夫变换(SHT)------cv2.HoughLines()函数

多尺度霍夫变换(MSHT)------cv2.HoughLines()函数

累计概率霍夫变换(PPHT)------cv2.HoughLinesP()函数

霍夫线变换原理简介:

霍夫变换及应用
标准霍夫变换—cv2.HoughLines()
霍夫变换及应用
⚫ src: 输入原图像(一般为8位单通道二值图像)
⚫ lines: 经过霍夫变换后检测线条的输出矢量, 每一条线由两个元素的矢量(ρ, Θ)表示, 其中ρ是离坐标原点的距离, Θ是弧度线条旋转角度(0表示垂直线, π/2度表示水平线)
⚫ rho: 以像素为单位的距离精度, 另一种表述方式是直线搜索时的进步尺寸的单位半径
⚫ theta: 以弧度为单位的角度精度, 另一种表述方式是直线搜索时的进步尺寸的角度单位

⚫ threshold: 累加平面的阈值参数, 即识别某部分为一条直线时它在累加平面中必须达到的值, 大于阈
值threshold的线段才可以被检测通过并返回到结果中
⚫ srn: 默认值0, 对于多尺度的霍夫变换, 这是第三个参数进步尺寸rho的除数距离
⚫ stn: 默认值0, 对于多尺度霍夫变换, 表示单位角度theta

代码示例

gray = cv2 .cvtColor(img,Cv2.COLOR BGR2GRAY)
edges = cv2 .Canny(gray,50,150,aperturesize = 3)
cv2 .imshow("Canny" ,edges)#print np.pi # n
lines = cv2.HoughLines (edges,1,np.pi/180,150)
lines2 = lines[:,0,:]
for rho,theta in lines2[:]:print 'rho=*s'rhoprint 'theta=%0.2f'%(theta*180/np.pi)a = np.cos(theta)b = np.sin(theta)x0 = a*rho yO= b*rho81= int(x0 + 1000*(-b))x1= int(y0 + 1000*(a))- 1000*(-b))x2= int(x0y2 = int(y0 - 1000*(a))cv2 .line (img,(x1,y1) , (x2 ,y2) , (0,0,255) ,2)cv2.circle (img,(x0,y0) ,2,(0,255,0),-1, CV2.LINE AA)
cv2 .imshow(' show', img)

霍夫变换及应用

累计概率霍夫变换—cv2.HoughLinesP()

霍夫变换及应用
⚫src: 输入原图像(一般为8位单通道二值图像)
⚫lines: 经过霍夫变换后检测线条的输出矢量, 每一条线由4个元素矢量(x_1,y_1,x_2,y_2)表示, 其中(x_1,y_1)和(x_2,y_2)是检测到线段的结束点
⚫rho: 以像素为单位的距离精度, 另一种表述方式是直线搜索时的进步尺寸的单位半径
⚫theta: 以弧度为单位的角度精度, 另一种表述方式是直线搜索时的进步尺寸的角度单位
⚫threshold: 累加平面的阈值参数, 即识别某部分为一条直线时它在累加平面中必须达到的值, 大于阈值threshold的线段才可以被检测通过并返回到结果中
⚫minLineLength: 默认值0, 表示最低线段的长度, 小于则不显示
⚫maxLineGap: 默认值0, 允许将同一行点与点之间连接起来的最大距离
代码示例:

img = cv2 .imread('1.jpg')
rows = img.shape[0]cols = img.shape[1]
print rows, cols
#img = cv2.GaussianBlur (img,(3,3) ,0)gray = cv2.cvtColor (img,cv2 .COLOR BGR2GRAY)edges = cv2.Canny(gray,50,150,aperturesize = 3)
cv2 .imshow("Canny" ,edges)
#print np.pi # n
minLineLength = 100
maxLineGap = 10
lines = cv2.HoughlinesP(edges,1,np.pi/180,100 ,minLineLength ,maxLineGap)
lines2 = lines[:,0,:]
for x1,y1,x2,y2 in lines2[:]:cv2 .line (img, (x1,y1) , (x2 ,y2) , (0,0,255) ,2)
cv2 .imshow(' show',img)
cv2 .waitKey(0)
cv2.destroyAllwindows ()

霍夫变换及应用

2)霍夫圆变换

霍夫圆变换的基本原理和霍夫线变换大体上类似, 只是点对应的二维极径极角空间被三维的圆心点x, y和半径r空间取代, 如果用完全一样的方法运算量较大, 运行速度较慢, 所以采用“霍夫梯度法”来做圆变换。

4.1 霍夫梯度法的原理

霍夫梯度法的原理是这样的。
[1] 首先对图像应用边缘检测,比如用canny边缘检测。
[2] 然后,对边缘图像中的每一个非零点,考虑其局部梯度,即用Sobel () 函数计算x和y方向的Sobel一阶导数得到梯度。
[3] 利用得到的梯度,由斜率指定的直线上的每一个点都在累加器中被累加,这里的斜率是从一个指定的最小值到指定的最大值的距离。
[4] 同时,标记边缘图像中每一个非0像素的位置。
[5] 然后从二维累加器中这些点中选择候选的中心,这些中心都大于给定阅值并且大于其所有近邻。这些候选的中心按照累加值降序排列,以便于最支持像素的中心首先出现。
[6] 接下来对每一个中心,考虑所有的非0像素。
[7] 这些像素按照其与中心的距离排序。从到最大半径的最小距离算起,选择非0像素最支持的一条半径。8.如果一个中心收到边缘图像非0像素最充分的支持,并且到前期被选择的中心有足够的距离,那么它就会被保留下来
这个实现可以使算法执行起来更高效,或许更加重要的是,能够帮助解决三维累加器中 会产生许多噪声并且使得结果不稳定的 稀疏分布问题。

霍夫梯度法”的缺点:

(1)可能在输出结果中产生噪声

(2)如果累加器阈值设置较低, 算法需要较长时间, 每一个中心只选择一个圆, 对于同心圆只选择一个

(3)如果新的中心很接近已接受的中心, 则不会被保留下来

霍夫圆变换—cv2.HoughCircles()

霍夫变换及应用
⚫src: 输入原图像(一般为8位单通道图像)
⚫circles: 经过霍夫变换后检测圆的输出矢量, 每个矢量包含三个元素的浮点矢量(x, y, radius)
⚫method: 使用的检测方法, 默认只有一种cv2.HOUGH_GRADIENT
⚫dp: 用来检测圆心的累加器图像的分辨率与输入图像之比的倒数, 且此参数允许创建一个比输入图像分辨率低的累加器。如dp=1, 累加器和输入如下具有相同分辨率; dp=2, 累加器只有输入图像一半大的宽度和高度
⚫minDist: 霍夫变换检测到圆的圆心之间的最小距离, 分辨两个不同圆
⚫param1: 默认值100, 它是第三个参数method设置的对应参数, 表示传递给Canny边缘算子的高阈值, 低阈值是高阈值的一半
⚫param2: 默认值100,它是第三个参数method设置的对应参数, 表示检测阶段圆心累加器阈值,越小, 则会检测到越多不存在的圆, 越大, 更多真正的圆被检测到
⚫minRadius/maxRadius: 表示圆半径的最小值/最大值

代码示例:

img = cv2 .imread('3 .jpg',0
img = cv2 .medianBlur (img,5)
cimg = cv2.cvtColor(img,cv2.COLOR GRAY2BGR)
circles = cv2.HoughCircles (img,cv2.HOUGH GRADIENT,2,50param1=200,param2=100,minRadius=100,maxRadius=500)
circles = np.uint16(np.around(circles))
for i in circles[0,:]:# draw the outer circlecv2.circle(cimg,(i[0] ,i[1]) ,i[2],(0,255,0) ,2)# draw the center of the circlecv2.circle (cimg,(i[0],i[1]) ,2,(0,0,255) ,3)
cv2.imshow('detected circles',cimg)
cv2 .waitKey(0)
cv2.destroyAllWindows ()

霍夫变换及应用