org.openpnp.vision.pipeline.stages.DetectCircularSymmetry

文章目录

org.openpnp.vision.pipeline.stages.DetectCircularSymmetry

功能

用于检测圆形对称性的一个阶段。它不要求圆形边缘完整或对比度极高,而是通过分析图像中圆形区域的径向对称性来定位圆心和直径。即使圆环存在缺口、部分遮挡或亮度不均,只要整体上具有圆对称性,就能被可靠检测。该 Stage 支持亚像素精度、局部搜索、多目标检测,并提供了对称性得分用于质量评估。

参数

参数 类型 默认值 说明
minDiameter int 10 最小检测直径(像素)。小于此值的圆将被忽略。
maxDiameter int 100 最大检测直径(像素)。大于此值的圆将被忽略。
maxDistance int 100 搜索半径(像素)。以 (center.x, center.y) 为中心,在此半径的圆内搜索候选圆心。若 searchWidthsearchHeight 为 0,则搜索区域为 (2*maxDistance+1) x (2*maxDistance+1) 的正方形。
searchWidth int 0 搜索矩形宽度(像素)。若 >0,则覆盖 maxDistance 的设定(此时搜索范围由该值决定)。0 表示自动设为 maxDistance*2
searchHeight int 0 搜索矩形高度(像素)。同理。
maxTargetCount int 1 最多要检测的目标数量。若 >1,算法会返回多个圆形(按得分排序)。
minSymmetry double 1.2 最小对称性得分阈值。得分 < 此值时视为无效。得分通常大于 1 表示存在对称性。增大该值可提高检测严格性。
corrSymmetry double 0.0 多目标时的相关对称性阈值。设最佳得分为 S_max,则其他候选圆的得分必须 ≥ S_max × corrSymmetry 才会被保留。取值范围 [0, 1]。
subSampling int 8 初始子采样步长。算法每隔 subSampling 个像素采样一次,以加速。后续会递归细化(步长逐步减小)。步长越大速度越快,但可能漏掉小尺寸圆。
superSampling int 1 最终超采样因子,用于亚像素精度。superSampling=1 无亚像素;2 表示半像素精度;4 表示 1/4 像素,以此类推。精度越高速度越慢。
symmetryScore enum OverallVarianceVsRingVarianceSum 对称性评分模式。可选值: • OverallVarianceVsRingVarianceSum:最宽容,适合部分圆环或散乱圆点。 • RingAvgeragesVarianceVsRingVarianceSum:较严格,要求各环平均亮度一致。 • RingMedianVarianceVsRingVarianceSum:最严格,用中位数代替均值,抗异常值。
diagnostics boolean false 若为 true,在输出图像上绘制检测到的圆(绿色)和十字线,便于调试。
heatMap boolean false 若为 true,叠加对称性得分的彩色热力图(得分越高颜色越暖)。
propertyName string "" 动态参数覆盖的属性名前缀。例如设置 propertyName="myCircle",则可通过 pipeline.setProperty("myCircle.diameter", 50) 在运行时覆盖直径;也可覆盖 maxDistancecenter 等。
outerMargin double 0.2 仅当 propertyName 有效且运行时指定了直径 diameter 时使用。用于计算 maxDiameter = diameter × (1 + outerMargin)
innerMargin double 0.4 类似,用于计算 minDiameter = diameter × (1 - innerMargin)

例子

generate_incomplete_circle.py

bash 复制代码
# @fn generate_incomplete_circle.py
import cv2
import numpy as np

# 图像尺寸
width, height = 500, 500
img = np.ones((height, width, 3), dtype=np.uint8) * 128  # 灰色背景

# 定义圆心、半径、线宽
center = (width // 2, height // 2)
radius = 80
thickness = 8

# 1. 绘制一个完整的圆(用于对比)
cv2.circle(img, center, radius, (0, 0, 0), thickness)

# 2. 绘制一个缺了 120° 的圆弧(缺口在右下象限)
#   角度从 30° 到 150° 不画,其他角度画
# 方法:先画完整圆,再用背景色覆盖缺口部分(或直接用 ellipse 画弧)
# 简便方法:绘制圆弧(ellipse 函数可指定起始和终止角度)
# 注意 OpenCV 的 ellipse 角度从 0° 开始(右侧水平),顺时针为正
# 这里制造一个 90° 的缺口
start_angle = 60
end_angle = 180  # 缺口 120°
# 在缺口区域用背景色覆盖
mask = np.zeros((height, width), dtype=np.uint8)
cv2.ellipse(mask, center, (radius, radius), 0, start_angle, end_angle, 255, -1)
# 将缺口区域的圆线条擦除(用背景色)
img[mask == 255] = [128, 128, 128]

# 3. 添加一个更小的、只有半圆的圆形标记(用于测试多目标)
center2 = (width - 100, 100)
radius2 = 30
cv2.ellipse(img, center2, (radius2, radius2), 0, 0, 180, (0, 0, 0), thickness - 2)

# 可选:添加一些噪声点,测试鲁棒性
noise = np.random.randint(0, 30, (height, width, 3), dtype=np.uint8)
mask_noise = np.random.random((height, width)) < 0.02
img[mask_noise] = cv2.add(img[mask_noise], noise[mask_noise])

# 保存图像
output_path = "test_circular_symmetry.png"
cv2.imwrite(output_path, img)
print(f"测试图像已生成: {output_path}")

cv-pipeline

bash 复制代码
<cv-pipeline>
   <stages>
      <cv-stage class="org.openpnp.vision.pipeline.stages.ImageRead" name="read" enabled="true" file="D:\3rd\openpnp_prj\openpnp-official\openpnp-test-images\my_test\test_circular_symmetry.png" color-space="Bgr" handle-as-captured="false"/>
      <cv-stage class="org.openpnp.vision.pipeline.stages.ConvertColor" name="gray" enabled="true" conversion="Bgr2Gray"/>
      <cv-stage class="org.openpnp.vision.pipeline.stages.BlurGaussian" name="blur" enabled="true" kernel-size="5" property-name="BlurGaussian"/>
      <cv-stage class="org.openpnp.vision.pipeline.stages.DetectCircularSymmetry" name="detect" enabled="true" min-diameter="30" max-diameter="200" max-distance="100" search-width="0" search-height="0" max-target-count="2" min-symmetry="1.1" corr-symmetry="0.8" outer-margin="0.2" inner-margin="0.4" sub-sampling="4" super-sampling="2" symmetry-score="OverallVarianceVsRingVarianceSum" property-name="" diagnostics="true" heat-map="false"/>
      <cv-stage class="org.openpnp.vision.pipeline.stages.ImageRecall" name="recall" enabled="true" image-stage-name="read"/>
      <cv-stage class="org.openpnp.vision.pipeline.stages.DrawCircles" name="draw" enabled="true" circles-stage-name="detect" thickness="2">
         <color r="0" g="255" b="0" a="255"/>
      </cv-stage>
      <cv-stage class="org.openpnp.vision.pipeline.stages.ImageWrite" name="save" enabled="true" file="output_detected_circles.png"/>
   </stages>
</cv-pipeline>

效果

END

相关推荐
LostSpeed1 天前
org.openpnp.vision.pipeline.stages.FilterContours
openpnp
LostSpeed1 天前
org.openpnp.vision.pipeline.stages.DrawTemplateMatches
openpnp
LostSpeed1 天前
org.openpnp.vision.pipeline.stages.DrawImageCenter
openpnp
LostSpeed2 天前
org.openpnp.vision.pipeline.stages.DilateModel
openpnp
LostSpeed2 天前
org.openpnp.vision.pipeline.stages.DetectEdgesCanny
openpnp
LostSpeed2 天前
org.openpnp.vision.pipeline.stages.DetectRectlinearSymmetry
openpnp
LostSpeed4 天前
openpnp - stages.ScriptRun和后续stage的数据交互方法
openpnp
LostSpeed5 天前
org.openpnp.vision.pipeline.stages.ConvertModelToKeyPoints
openpnp
LostSpeed5 天前
org.openpnp.vision.pipeline.stages.ConvertColor
openpnp