霍夫圆检测

霍夫圆检测算法

[[01-霍夫圆检测算法]]

任务二

编写霍夫圆检测算法函数,检测图片中的圆的位置和参数

函数格式如下:

1
2
3
4
5
6
7
8
def detect_circles(img_path):
"""
输入:图片路径
输出:[
{'center': (x,y), 'radius': r},
... # 按半径从大到小排序
]

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import cv2
import numpy as np

def detect_circles(img_path):
# 读取图片
image = cv2.imread(img_path)
if image is None:
raise ValueError("无法读取图片,请检查路径是否正确")

# 转换为灰度图像
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 使用高斯模糊减少噪声
blurred = cv2.GaussianBlur(gray, (9, 9), 2)

# 使用霍夫圆变换检测圆
circles = cv2.HoughCircles(
blurred,
cv2.HOUGH_GRADIENT,
dp=1.2, # 累加器分辨率与图像分辨率的反比
minDist=40, # 检测到的圆心之间的最小距离
param1=40, # Canny 边缘检测的高阈值
param2=40, # 累加器阈值,较小的值将检测到更多的圆
minRadius=40, # 圆的最小半径
maxRadius=150 # 圆的最大半径
)

if circles is None:
return [], image

# 将检测到的圆转换为列表,并按半径从大到小排序
circles = np.round(circles[0, :]).astype("int")
circles = sorted(circles, key=lambda x: x[2], reverse=True)

# 提取圆心和半径
result = [{'center': (x, y), 'radius': r} for (x, y, r) in circles]

# 在图像上绘制检测到的圆
for circle in circles:
center = (circle[0], circle[1])
radius = circle[2]
cv2.circle(image, center, radius, (0, 255, 0), 4) # 用绿色绘制圆
cv2.rectangle(image, (center[0] - 5, center[1] - 5), (center[0] + 5, center[1] + 5), (0, 128, 255), -1) # 用橙色绘制圆心

return result, image

# 示例调用
if __name__ == "__main__":
result, image_with_circles = detect_circles("mission2/H.png")
if result:
for circle in result:
print(f"圆心: {circle['center']}, 半径: {circle['radius']}")
# 显示结果图像
cv2.imshow('Detected Circles', image_with_circles)
cv2.waitKey(0)
cv2.destroyAllWindows()
else:
print("未检测到圆")


代码思路

先使用imread()函数读取指定路径的图片数据,保存在变量image中,如果无法读取,返回错误提示;若正常读取,先对图片数据进行预处理,因为霍夫圆变换检测函数HoughCircles()需要输入灰度图片,所以先使用cvtColor()函数转化为灰度图像,然后通过GaussianBlur()函数减少噪声,将预处理结果保存在blurred变量中。最后使用使用HoughCircles()函数对图片进行检测。期间要对 dp,minDistparam1param2, minRadius, maxRadius 六个参数不断进行调整使得输出结果理想,最后返回结果。

代码解释

根据题目要求,函数detect_circles()的输入值img_path是图片的路径

1
image = cv2.imread(img_path)

通过cv2.imread() 函数将img_path路径的图片文件加载为 NumPy 数组,数组中的每个元素分别表示像素值的BGR数值

1
2
if image is None:
raise ValueError("无法读取图片,请检查路径是否正确")

检查图片是否成功加载,当imread返回值为空(None)时,说明图片路径无效或文件损坏,抛出异常提示用户。

1
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

因为后面的HoughCircles()函数的输入需要为灰度图,所以将彩色图像转换为灰度图像。

1
blurred = cv2.GaussianBlur(gray, (9, 9), 2)

对灰度图像进行高斯模糊处理,参数(9, 9)表示卷积核大小,2为标准差,目的是减少噪声。

1
2
3
4
5
6
7
8
9
10
circles = cv2.HoughCircles(
blurred,
cv2.HOUGH_GRADIENT,
dp=1.2, # 累加器分辨率与图像分辨率的反比
minDist=40, # 检测到的圆心之间的最小距离
param1=40, # Canny 边缘检测的高阈值
param2=40, # 累加器阈值,较小的值将检测到更多的圆
minRadius=40, # 圆的最小半径
maxRadius=150 # 圆的最大半径
)

使用霍夫圆变换检测圆,使用HoughCircles()方法
cv2.HoughCircles(image, method, dp, minDist, param1= x , param2= x , minRadius= x , maxRadius= x )

  1. dp # 累加器分辨率与图像分辨率的比值
  2. minDist # 检测到的圆心之间的最小距离
  3. param1 # Canny 边缘检测的高阈值
  4. param2 # 累加器阈值,较小的值将检测到更多的圆
  5. minRadius # 圆的最小半径
  6. maxRadius # 圆的最大半径

其中
dp=1表示累加器和输入图像具有相同的分辨率,dp=2 表示累加器的宽高是输入图像的一半。

HoughCircles()方法的返回值是一个列表。

1
2
if circles is None:
return []

如果未检测到圆(circles为None),返回空列表。

1
2
circles = np.round(circles[0, :]).astype("int")
circles = sorted(circles, key=lambda x: x[2], reverse=True)

将检测到的圆坐标和半径四舍五入并转换为整数类型。
按照半径从大到小对圆进行排序。

1
result = [{'center': (x, y), 'radius': r} for (x, y, r) in circles]

构建包含圆心和半径信息的字典列表,方便后面的绘制和输出。

1
2
3
4
5
for circle in circles:
center = (circle[0], circle[1])
radius = circle[2]
cv2.circle(image, center, radius, (0, 255, 0), 4)
cv2.rectangle(image, (center[0] - 5, center[1] - 5), (center[0] + 5, center[1] + 5), (0, 128, 255), -1)

对圆心和圆进行绘制。

1
return result, image

返回结果。

运行结果

第一张图片

第二张图片

![[Pasted image 20250317223118.png]]

opencv #二维码 #QR #二维码识别

opencv #霍夫圆 #检测 #opencv #python


霍夫圆检测
https://pattianfang.github.io/2025/04/01/霍夫圆检测/
作者
Pat Tian Fang
发布于
2025年4月1日
更新于
2025年5月3日
许可协议