圆的表示式是:
其中aa和bb表示圆心坐标,rr表示圆半径,因此标准的霍夫圆检测就是在这三个参数组成的三维空间累加器上进行圆形检测,此时效率就会很低,所以OpenCV中使用霍夫梯度法进行圆形的检测。
霍夫梯度法将霍夫圆检测范围两个阶段,第一阶段检测圆心,第二阶段利用圆心推导出圆半径。
- 圆心检测的原理:圆心是圆周法线的交汇处,设置一个阈值,在某点的相交的直线的条数大于这个阈值就认为该交汇点为圆心。
- 圆半径确定原理:圆心到圆周上的距离(半径)是相同的,确定一个阈值,只要相同距离的数量大于该阈值,就认为该距离是该圆心的半径。
原则上霍夫变换可以检测任何形状,但复杂的形状需要的参数就多,霍夫空间的维数就多,因此在程序实现上所需的内存空间以及运行效率上都不利于把标准霍夫变换应用于实际复杂图形的检测中。霍夫梯度法是霍夫变换的改进,它的目的是减小霍夫空间的维度,提高效率。
cv2.HoughCircles()函数:
circles = cv.HoughCircles(image, method, dp, minDist, param1=100, param2=100, minRadius=0,maxRadius=0 )
- image:输入图像,应输入灰度图像
- method:使用霍夫变换圆检测的算法,它的参数是CV_HOUGH_GRADIENT
- dp:霍夫空间的分辨率,dp=1时表示霍夫空间与输入图像空间的大小一致,dp=2时霍夫空间是输入图像空间的一半,以此类推
- minDist为圆心之间的最小距离,如果检测到的两个圆心之间距离小于该值,则认为它们是同一个圆心
- param1:边缘检测时使用Canny算子的高阈值,低阈值是高阈值的一半。
- param2:检测圆心和确定半径时所共有的阈值
- minRadius和maxRadius为所检测到的圆半径的最小值和最大值
返回:
- circles:输出圆向量,包括三个浮点型的元素——圆心横坐标,圆心纵坐标和圆半径
由于霍夫圆检测对噪声比较敏感,所以首先对图像进行中值滤波。
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
# 1 读取图像,并转换为灰度图
planets = cv.imread("./1.jpg")
gay_img = cv.cvtColor(planets, cv.COLOR_BGRA2GRAY)
# 2 进行中值模糊,去噪点
img = cv.medianBlur(gay_img, 7)
# 3 霍夫圆检测
circles = cv.HoughCircles(img, cv.HOUGH_GRADIENT, 1.4, 100, param1=200, param2=90, minRadius=0, maxRadius=400)
# 4.整数化,#把circles包含的圆心和半径的值变成整数
circles = np.uint16(np.around(circles))
# 5 将检测结果绘制在图像上
for i in circles[0, :]: # 遍历矩阵每一行的数据
# 绘制圆形
cv.circle(planets, (i[0], i[1]), i[2], (0, 255, 0), 2)
# 绘制圆心
cv.circle(planets, (i[0], i[1]), 2, (0, 0, 255), -1)
# 6 图像显示
plt.figure(figsize=(10, 8), dpi=100)
plt.imshow(planets[:, :, ::-1])
plt.title('霍夫变换圆检测')
plt.xticks([]), plt.yticks([])
plt.show()
注意:在使用circle()函数时,传递的circles包含的圆心和半径的值需要变成整数,否则会出现以下错误
原图