首页/在线代码库/demo2_hough_circles.py

demo2_hough_circles.py

生成一张"断成多段"的圆环图像, 用 cv2.HoughCircles 识别出完整圆, 输出 原图 | 中值滤波+边缘 | 检测结果 三栏对比图。

Python 69 行 系列:识别系列 🔒 源码仅供在线学习,不提供文件下载
完整源码 · 在线查看demo2_hough_circles.py
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
"""演示2: 霍夫梯度法检测断裂圆弧。

生成一张"断成多段"的圆环图像, 用 cv2.HoughCircles 识别出完整圆,
输出 原图 | 中值滤波+边缘 | 检测结果 三栏对比图。
"""
import os
import cv2
import numpy as np
import matplotlib.pyplot as plt
from figure_style import figures_dir, configure

configure()

OUT = figures_dir()
os.makedirs(OUT, exist_ok=True)

H, W = 320, 400
img = np.zeros((H, W), dtype=np.uint8)

cx, cy, R = 200, 160, 90


def draw_broken_circle(im, center, r, arcs, thickness=3):
    """arcs: 每段为 (start_deg, end_deg), 角度之间留缺口。"""
    for s, e in arcs:
        cv2.ellipse(im, center, (r, r), 0, s, e, 255, thickness)


# 圆周被切掉 6 段, 但每段覆盖较宽的角度, 保证霍夫投票足够
draw_broken_circle(img, (cx, cy), R, [
    (0, 70), (95, 165), (190, 260), (285, 360),
])
# 加一个内圈小圆(干扰)与少量噪点
cv2.circle(img, (cx, cy), 25, 255, 1)
rng = np.random.default_rng(1)
noise = rng.random((H, W)) > 0.998
img[noise] = 255

# 中值滤波去噪
blur = cv2.medianBlur(img, 5)
# 边缘图(用于展示)
edges = cv2.Canny(blur, 50, 150)

# 霍夫梯度法检测圆
circles = cv2.HoughCircles(blur, cv2.HOUGH_GRADIENT, dp=1, minDist=60,
                           param1=100, param2=20, minRadius=60, maxRadius=120)

res = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
n = 0
if circles is not None:
    circles = np.uint16(np.around(circles))
    for c in circles[0, :]:
        x, y, r = int(c[0]), int(c[1]), int(c[2])
        cv2.circle(res, (x, y), r, (0, 255, 0), 2)   # 绿圆
        cv2.circle(res, (x, y), 2, (0, 0, 255), 3)   # 红圆心
        n += 1

fig, axes = plt.subplots(1, 3, figsize=(13, 4.5))
for ax, im, title in zip(axes, (img, edges, res),
                         ("原图(断裂圆弧)", "Canny 边缘图", f"霍夫圆检测结果 ({n} 个圆)")):
    ax.imshow(im, cmap="gray")
    ax.set_title(title, fontsize=11)
    ax.axis("off")
fig.suptitle("示例一(续): 霍夫梯度法 — 断裂圆的识别", fontsize=14)
fig.tight_layout(rect=(0, 0, 1, 0.95))
out_path = os.path.join(OUT, "fig_hough_circles.png")
fig.savefig(out_path, dpi=150)
print(f"检测到 {n} 个圆 -> {out_path}")

输出图

fig_hough_circles.png
输出图 · fig_hough_circles.png