org.openpnp.vision.pipeline.stages.DetectRectlinearSymmetry

文章目录

org.openpnp.vision.pipeline.stages.DetectRectlinearSymmetry

功能

检测具有矩形线性对称性的物体(例如矩形芯片、IC、排针、无源元件等)。它不依赖于清晰的边缘或完整的轮廓,而是通过分析图像在不同旋转角度下的水平和垂直截面(cross‑section)的对称性,找到使对称性最大的角度和中心位置,最终输出一个 RotatedRect(旋转矩形),包含物体的中心、尺寸和旋转角度.

参数

参数 类型 默认值 说明
expectedAngle double 0 期望的物体旋转角度(度)。算法将在该角度附近搜索。
searchDistance double 100 围绕中心的搜索半径(像素)。用于确定中心偏移的范围。
searchAngle double 45 围绕 expectedAngle 的搜索范围(度,双向)。实际搜索角度范围为 [expectedAngle - searchAngle, expectedAngle + searchAngle]
maxWidth double 100 物体的最大宽度(像素)。用于限制截面分析的范围,提高效率。
maxHeight double 100 物体的最大高度(像素)。
symmetricLeftRight boolean true 物体是否左右对称(在0°旋转时)。若为 true,使用 symmetricFunction;若为 false,使用 asymmetricFunction
symmetricUpperLower boolean true 物体是否上下对称(在0°旋转时)。若为 true,使用 symmetricFunction;若为 false,使用 asymmetricFunction
symmetricFunction SymmetryFunction FullSymmetry 当物体对称时,使用的对称评估函数。可选值:FullSymmetry, EdgeSymmetry, OutlineSymmetry, OutlineEdgeSymmetry, OutlineSymmetryMasked
asymmetricFunction SymmetryFunction OutlineSymmetryMasked 当物体不对称时,使用的对称评估函数。通常用于元件内部图案不对称但轮廓对称的情况。
minSymmetry double 10 最小对称性得分。得分 >1 表示有对称性,低于此值视为检测失败。
subSampling int 8 子采样步长。为加速,每隔 subSampling 像素采样一次。后续迭代会逐步减小该值以获得更高精度。
superSampling int 1 超采样因子,用于最终阶段的亚像素精度。1 表示无超采样,2 表示半像素精度。负值可提前停止细化。
smoothing int 5 高斯平滑核大小(像素)。用于消除由于像素网格和角度采样引起的噪声干扰。
gamma double 2.5 伽马校正指数。对像素亮度进行幂变换,gamma > 1 会增强亮部对比度,有助于检测较亮的元件。
threshold int 128 掩膜对称模式下的亮度阈值(0-255)。仅当像素亮度大于该阈值时,才视为物体的一部分。
minFeatureSize double 40 掩膜对称模式下的最小特征尺寸(像素)。用于过滤掉小的噪声斑点,只有大于该尺寸的连续掩膜区域才被视为有效特征。
diagnostics boolean false 是否在输出图像上叠加诊断信息(十字线、边界框等)。用于调试。
diagnosticsMap boolean false 是否叠加角度对比图和截面轮廓图,提供更详细的诊断信息。
propertyName String "DetectRectlinearSymmetry" 管道属性名称。如果设置,管道运行时可以通过该属性动态覆盖部分配置参数(如 centerexpectedAngle 等)。

例子

产生测试图像

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

# 图像尺寸
width, height = 800, 600

# 创建纯蓝色背景
img = np.full((height, width, 3), (255, 0, 0), dtype=np.uint8)

# 矩形参数(未旋转时)
rect_w, rect_h = 200, 120
center = (width // 2, height // 2)
angle = 30  # 逆时针旋转30度

# 方法:先在一个小画布上绘制未旋转的矩形,然后旋转并粘贴到背景上
# 创建足够大的画布(包含矩形)
canvas_w = rect_w + 100
canvas_h = rect_h + 100
canvas = np.zeros((canvas_h, canvas_w, 3), dtype=np.uint8)
canvas[:] = (255, 0, 0)  # 蓝色背景,与主图一致
# 在画布中央绘制白色矩形
cv2.rectangle(canvas, (50, 50), (50+rect_w, 50+rect_h), (255, 255, 255), -1)

# 计算旋转矩阵,绕画布中心旋转
M = cv2.getRotationMatrix2D((canvas_w/2, canvas_h/2), angle, 1.0)
rotated = cv2.warpAffine(canvas, M, (canvas_w, canvas_h), borderMode=cv2.BORDER_CONSTANT, borderValue=(255,0,0))

# 将旋转后的矩形区域叠加到主图像中心
# 找到旋转后非蓝色区域的边界
gray = cv2.cvtColor(rotated, cv2.COLOR_BGR2GRAY)
_, mask = cv2.threshold(gray, 1, 255, cv2.THRESH_BINARY)
mask_inv = cv2.bitwise_not(mask)
# 主图像中对应的区域(需要裁剪到主图范围内)
x_start = center[0] - canvas_w//2
y_start = center[1] - canvas_h//2
x_end = x_start + canvas_w
y_end = y_start + canvas_h
roi = img[y_start:y_end, x_start:x_end]
# 将旋转后的非蓝色部分复制到 ROI
roi_bg = cv2.bitwise_and(roi, roi, mask=mask_inv)
rotated_fg = cv2.bitwise_and(rotated, rotated, mask=mask)
img[y_start:y_end, x_start:x_end] = cv2.add(roi_bg, rotated_fg)

# 可选:绘制中心十字标记(绿色)
cv2.line(img, (center[0]-50, center[1]), (center[0]+50, center[1]), (0, 255, 0), 2)
cv2.line(img, (center[0], center[1]-50), (center[0], center[1]+50), (0, 255, 0), 2)

# 添加文字
cv2.putText(img, f"Rotated Rectangle, angle={angle} deg", (50, 50),
            cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 0), 2)

# 保存
cv2.imwrite("rotated_rectangle_v2.png", img)
print("已生成旋转矩形测试图像: rotated_rectangle_v2.png")

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\rotated_rectangle_v2.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.DetectRectlinearSymmetry" name="detect" enabled="true" expected-angle="30.0" search-distance="50.0" search-angle="20.0" max-width="250.0" max-height="180.0" symmetric-left-right="true" symmetric-upper-lower="true" symmetric-function="FullSymmetry" asymmetric-function="OutlineSymmetryMasked" min-symmetry="10.0" sub-sampling="4" super-sampling="2" smoothing="5" gamma="2.5" threshold="128" min-feature-size="20.0" diagnostics="true" diagnostics-map="false" property-name=""/>
      <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.DrawRotatedRects" name="draw" enabled="true" rotated-rects-stage-name="detect" thickness="2" draw-rect-center="true" rect-center-radius="4" show-orientation="true">
         <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_rotated_rectangle.png"/>
   </stages>
</cv-pipeline>

效果


END

相关推荐
LostSpeed2 天前
openpnp - stages.ScriptRun和后续stage的数据交互方法
openpnp
LostSpeed3 天前
org.openpnp.vision.pipeline.stages.ConvertModelToKeyPoints
openpnp
LostSpeed3 天前
org.openpnp.vision.pipeline.stages.ConvertColor
openpnp
LostSpeed2 个月前
openpnp2.4 - 导入kicad9.0的封装数据
openpnp
LostSpeed2 个月前
高精度juki吸嘴快拆连接器铜套座-v8 - 气密性验证
openpnp·juki吸嘴快拆连接器铜套座
LostSpeed2 个月前
openpnp - 吸嘴校验失败的处理方法
openpnp
LostSpeed2 个月前
openpnp - 测试片直径的选择 on “Calibrate precise camera ↔ nozzle N1 offsets“
openpnp
LostSpeed2 个月前
openpnp - 调试环境搭建 - use eclipse for java - v2
openpnp
LostSpeed2 个月前
openpnp - python2.7 script - 中文显示乱码,只能显示英文
python·openpnp