You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于OpenCV的Python同心圆检测及圆度、偏移方向分析需求

低质量投影同心光圈的圆形识别与分析方案

需求说明

识别投影形成的低质量同心光圈中的圆形,输出量化圆度指标,并判断圆形是否存在特定方向的偏移。待识别图像存在亮度不均、边缘模糊、噪声干扰等问题。

原始代码问题

原代码结合霍夫圆变换与轮廓检测,但未针对低对比度、噪声多的投影图像做针对性预处理,且轮廓筛选逻辑过于严格,导致识别效果不佳。

改进方案与代码

核心优化方向

  • 采用自适应阈值适配局部亮度差异,替代固定阈值
  • 使用形态学闭运算增强光圈边缘,填补间隙抑制噪声
  • 优化轮廓筛选逻辑,放宽圆度阈值适配非完美圆形
  • 通过椭圆拟合判断定向偏移,同时计算圆度指标
import cv2
import numpy as np
import matplotlib.pyplot as plt

# 加载图像
image_path = '/mnt/data/IMG_1.JPG'
img = cv2.imread(image_path)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
output = img.copy()

# -------------------------- 预处理优化 --------------------------
# 自适应阈值处理,适配局部亮度差异
adaptive_thresh = cv2.adaptiveThreshold(
    gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2
)
# 形态学闭运算,填补光圈边缘间隙
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5,5))
processed = cv2.morphologyEx(adaptive_thresh, cv2.MORPH_CLOSE, kernel)

# -------------------------- 轮廓检测与筛选 --------------------------
contours, _ = cv2.findContours(processed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# 圆度计算与轮廓分析函数
def analyze_contour(contour):
    area = cv2.contourArea(contour)
    if area < 1000:  # 过滤过小噪声轮廓
        return None
    perimeter = cv2.arcLength(contour, True)
    # 圆度公式:4π×面积/周长²,完美圆为1
    circularity = (4 * np.pi * area) / (perimeter ** 2) if perimeter > 0 else 0
    
    # 最小外接圆参数
    (x, y), radius = cv2.minEnclosingCircle(contour)
    center = (int(x), int(y))
    radius = int(radius)
    
    # 椭圆拟合判断偏移
    if len(contour) >= 5:
        ellipse = cv2.fitEllipse(contour)
        (ell_center, (major_axis, minor_axis), angle) = ellipse
        axis_ratio = major_axis / minor_axis if minor_axis > 0 else 0
    else:
        axis_ratio = 1.0
        angle = 0.0
    
    return {
        "center": center,
        "radius": radius,
        "circularity": round(circularity, 3),
        "axis_ratio": round(axis_ratio, 3),
        "offset_angle": round(angle, 1)
    }

# 筛选符合条件的圆形轮廓
detected_circles = []
for cnt in contours:
    result = analyze_contour(cnt)
    # 放宽圆度阈值适配低质量图像
    if result and 0.6 < result["circularity"] < 1.4:
        detected_circles.append(result)

# 按半径排序,区分同心光圈层级
detected_circles.sort(key=lambda x: x["radius"])

# -------------------------- 可视化与结果输出 --------------------------
# 绘制识别结果
for circle in detected_circles:
    cv2.circle(output, circle["center"], circle["radius"], (0, 255, 0), 2)
    cv2.circle(output, circle["center"], 3, (0, 0, 255), -1)
    # 标注圆度与偏移信息
    text1 = f"圆度: {circle['circularity']}"
    text2 = f"偏移比: {circle['axis_ratio']}"
    y_pos = circle["center"][1] + circle["radius"] + 20
    cv2.putText(output, text1, (circle["center"][0]-60, y_pos), 
                cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,255,0), 1)
    cv2.putText(output, text2, (circle["center"][0]-60, y_pos+20), 
                cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,255,0), 1)

# 展示原始图像与识别结果
plt.figure(figsize=(12,8))
plt.subplot(121), plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)), plt.title("原始图像")
plt.axis('off')
plt.subplot(122), plt.imshow(cv2.cvtColor(output, cv2.COLOR_BGR2RGB)), plt.title("识别结果")
plt.axis('off')
plt.show()

# 输出量化指标与偏移判断
print("识别到的圆形量化指标:")
for i, circle in enumerate(detected_circles, 1):
    print(f"\n第{i}个圆:")
    print(f"  圆心坐标: {circle['center']}")
    print(f"  半径: {circle['radius']}")
    print(f"  圆度: {circle['circularity']}")
    print(f"  长轴/短轴比: {circle['axis_ratio']}")
    print(f"  偏移方向角度: {circle['offset_angle']}°")
    # 偏移判断阈值:轴比>1.1视为存在定向偏移
    if circle["axis_ratio"] > 1.1:
        print(f"  结论: 存在定向偏移,方向为{circle['offset_angle']}°")
    else:
        print(f"  结论: 无明显定向偏移")

指标说明

  • 圆度(Circularity):取值范围为01,越接近1表示轮廓越接近完美圆形。低质量图像中0.61.4的范围可有效筛选光圈圆。
  • 长轴/短轴比:大于1.1时判断为存在定向偏移,比值越大偏移程度越明显;偏移角度为椭圆长轴与水平方向的夹角。

内容的提问来源于stack exchange,提问作者Ross

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 01:24:55