OpenCV API:
circle = cv2.HoughCircles(image, method, dp, minDist, param1=100, param2=100, minRadius=0, maxRadius=0)
参数:
- image:输入图像(灰度图)
- method:使用霍夫变换圆检测的算法,参数为cv2.HOUGH_GRADIENT
- dp:霍夫空间的分辨率,dp=1时表示霍夫空间与输入图像空间的大小一致,dp=2时霍夫空间是输入图像空间的一半,以此类推
- minDist:为圆心之间的最小距离,如果检测到的两个圆心之间距离小于该值,则认为它们是同一个圆心
- param1:边缘检测时使用Canny算子的高阈值,低阈值是高阈值的一半
- param2∶检测圆心和确定半径时所共有的阈值
- minRadius和maxRadius:为所检测到的圆半径的最小值和最大值
返回值:
circles:输出圆向量,包括三个浮点型的元素――圆心横坐标,圆心纵坐标和圆半径。
原理
圆的表示式是:
其中a和b表示圆心坐标,r表示圆半径,因此标准的霍夫圆检测就是在这三个参数组成的三维空间累加器上进行圆形检测,此时效率就会很低.
OpenCV中使用霍夫梯度法进行圆形的检测。
霍夫梯度法
霍夫梯度法将霍夫圆检测范围两个阶段,第一阶段检测圆心,第二阶段利用圆心推导出圆半径。
圆心检测的原理∶圆心是圆周法线的交汇处,设置一个阈值,在某点的相交的直线的条数大于这个阈值就认为该交汇点为圆心。
圆半径确定原理:圆心到圆周上的距离(半径)是相同的,确定一个阈值,只要相同距离的数量大于该阈值,就认为该距离是该圆心的半径。
原则上霍夫变换可以检测任何形状,但复杂的形状需要的参数就多,霍夫空间的维数就多,因此在程序实现上所需的内存空间以及运行效率上都不利于把标准霍夫变换应用于实际复杂图形的检测中。霍夫梯度法是霍夫变换的改进,它的目的是减小霍夫空间的维度,提高效率。
代码编写
由于霍夫圆检测对噪声比较敏感,所以首先对图像进行中值滤波。
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
src = cv.imread("E:\\circle.png")
img = src.copy()
img_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
# 进行中值滤波
dst_img = cv.medianBlur(img_gray, 7)
# 霍夫圆检测
circle = cv.HoughCircles(dst_img, cv.HOUGH_GRADIENT, 1, 50,
param1=100, param2=100, minRadius=0, maxRadius=10000)
print(circle)
# 将检测结果绘制在图像上
for i in circle[0, :]: # 遍历矩阵的每一行的数据
# 绘制圆形
cv.circle(img, (int(i[0]), int(i[1])), int(i[2]), (255, 0, 0), 10)
# 绘制圆心
cv.circle(img, (int(i[0]), int(i[1])), 10, (255, 0, 0), -1)
# 显示图像
fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(10, 8), dpi=100)
axes[0].imshow(src[:, :, ::-1])
axes[0].set_title("原图")
axes[1].imshow(img[:, :, ::-1])
axes[1].set_title("霍夫圆检测后的图像")
plt.show()