20.1 原理
霍夫圆变换的基本原理和上个教程中提到的霍夫线变换类似,只是点对应的二维极径极角空间被三维的圆心点x, y 还有半径r 空间取代。
对直线来说,一条直线能由参数极径极角 (r,θ) 表示。
而对圆来说,我们需要三个参数来表示一个圆,如上文所说现在原图像的边缘图像的任意点对应的经过这个点的所有可能圆是在三维空间有下面这三个参数来表示了,其对应一条三维空间的曲线。那么与二维的霍夫线变换同样的道理, 对于多个边缘点越多这些点对应的三维空间曲线交于一点那么他们经过的共同圆上的点就越多,类似的我们也就可以用同样的阈值的方法来判断一个圆是否被检测到,这就是标准霍夫圆变换的原理,但也正是在三维空间的计算量大大增加的原因,标准霍夫圆变化很难被应用到实际中: ,这里的
表示圆心的位置 (下图中的绿点) 而 r 表示半径, 这样我们就能唯一的定义一个圆了, 见下图:
出于上面提到的对运算效率的考虑, OpenCV实现的是一个比标准霍夫圆变换更为灵活的检测方法: 霍夫梯度法, 也叫2-1霍夫变换(21HT), 它的原理依据是圆心一定是在圆上的每个点的模向量上, 这些圆上点模向量的交点就是圆心, 霍夫梯度法的第一步就是找到这些圆心, 这样三维的累加平面就又转化为二维累加平面. 第二步根据所有候选中心的边缘非0像素对其的支持程度来确定半径。
20.2 cv2. HoughCircle()
原型:
cv2.HoughCircles(image, method, dp, minDist, circles, param1, param2, minRadius, maxRadius)
参数:
- image: 必须是二值图像,推荐使用canny边缘检测的结果图像;
- method:定义检测图像中圆得方法。目前唯一实现得方法是cv2.HOUGH_GRADIENT
- dp:累加器分辨路与图像分辨率得反比。值越大,累加器数组越小
- minDist:检测到得圆的中心(x,y)的最小距离。如果minDist太小,则可能导致检测到多个相邻的圆。如果minDist太大,则可能导致很多圆检测不到。
- param1:用于处理边缘检测的梯度值方法
- param2:cv2.HOUGH_GRADIENT方法的累加器阈值。阈值越小,检测到的圈子越多。
- minRadius:半径的最小大小(以像素为单位)
- maxRadius:半径的最大大小(以像素为单位)
20.3 示例
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('C:\\Users\\liyou\\Downloads\\eyes.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#灰度图像
print(gray.shape)
#hough transform
circles1 = cv2.HoughCircles(gray,cv2.HOUGH_GRADIENT,1,
100,param1=100,param2=30,
minRadius=50,maxRadius=100)
print(circles1)
if circles1 is not None:
circles = circles1[0,:,:]#提取为二维
circles = np.uint16(np.around(circles))#四舍五入,取整
for i in circles[:]:
cv2.circle(img,(i[0],i[1]),i[2],(255,0,0),5)#画圆
cv2.circle(img,(i[0],i[1]),2,(255,0,255),10)#画圆心
plt.figure(figsize=(12.8,4.8))
plt.subplot(121),plt.imshow(gray,'gray'),plt.title('Gray'), plt.xticks([]),plt.yticks([])
plt.subplot(122),plt.imshow(img), plt.title('HoughCircle'),plt.xticks([]),plt.yticks([])
else:
print('霍夫圆检测结果为空')