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

如何稳定精准测量圆角矩形旋转角度以适配工业PNP设备

解决方案:圆角矩形旋转角度高精度测量优化

问题回顾

我用diplib编写Python脚本,用于测量圆角矩形产品的中心与旋转角度,数据将驱动工业PNP设备完成面板精准放置。当前采用Feret.MinAng测量旋转角度存在偏差——该方法仅取对象两侧最远像素对,而非对边平均距离;即使对目标做形态学开运算,仍有约0.05度误差,同时担心光源波动会影响测量的稳定性与一致性,寻求优化方案。

原代码

import diplib as dip
import numpy as np
import matplotlib.pyplot as pp

# 加载图像
img = dip.ImageRead('back6.png')
img = img(1)

gm = dip.Norm(dip.GradientMagnitude(img))

water = dip.Watershed(gm, connectivity=1, maxDepth=6, flags={'correct', 'labels'})
water = dip.SmallObjectsRemove(water, 8000)

blocks = dip.MeasurementTool.Measure(water, img, features=['Mass'])
blocks = dip.ObjectToMeasurement(water, blocks['Mass'])

blocks[blocks < 31000000] = 0

result = dip.MeasurementTool.Measure(water, img, features=['Center'])
print(result)

board = (blocks > 3100000)
board = dip.FillHoles(board)
rect = dip.Opening(board, 35)

dip.viewer.Show(board)
dip.viewer.Show(rect)

result = dip.MeasurementTool.Measure(dip.Label(board), img, features=['Center', 'Feret'])
print(result)

result = dip.MeasurementTool.Measure(dip.Label(rect), img, features=['Center', 'Feret'])
print(result)

target = dip.Overlay(img, rect-dip.BinaryErosion(rect, 1, 1))
dip.viewer.Show(target)

dip.viewer.Show(dip.Overlay(img, board-dip.BinaryErosion(board, 1, 1)))

circle = dip.Image(target.Sizes(), 1, 'SFLOAT')
circle.Fill(0)

dip.DrawBandlimitedBall(circle, diameter=10, origin=result[1]['Center'])

circle /= dip.Maximum(circle)

target *= 1 - circle
target += circle * dip.Create0D([255,10,0])

dip.viewer.Show(target)

测试与效果

  • 测试图片:![深色背景下的圆角矩形产品图]
  • 轮廓追踪效果:![清晰显示产品轮廓与稳定中心标记的效果图]
  • 误差情况:![形态学开运算后Feret.MinAng仍有约0.05度误差的截图]

优化方案

1. 用图像矩替换Feret角计算主轴方向

Feret角依赖单点对,易受圆角、噪声干扰。改用**图像矩(Image Moments)**计算主轴方向,基于目标所有像素的分布趋势,鲁棒性更强:

# 替换原Feret测量逻辑,改用Orientation特征
result = dip.MeasurementTool.Measure(dip.Label(rect), img, features=['Center', 'Orientation'])
# 将弧度转换为角度
angle_deg = dip.RadiansToDegrees(result[1]['Orientation'])
print(f"主轴角度:{angle_deg}度")

矩计算的是目标整体分布的平均趋势,能有效抵消圆角和局部噪声带来的偏差,精度远高于Feret角。

2. 加入光源波动抗性的预处理流程

针对光照波动,添加灰度归一化+自适应阈值预处理,抵消光照不均和强度波动:

# 加载图像后加入预处理步骤
# 灰度归一化,统一图像亮度范围
img_normalized = dip.Normalize(img, lower=0, upper=255)
# 自适应阈值分割,替代梯度+分水岭的复杂流程
thresholded = dip.AdaptiveThreshold(img_normalized, windowSize=15, offset=10)
# 后续分割、形态学处理基于thresholded执行

自适应阈值能在局部区域动态调整阈值,抵消光照不均;灰度归一化则统一整体亮度,降低光源强度波动的影响。

3. 轮廓点最小二乘拟合矩形

若矩计算仍有细微误差,可提取目标轮廓后做最小二乘拟合,进一步平均圆角带来的偏差:

# 提取目标轮廓
contours = dip.FindContours(rect)
# 整理轮廓点坐标
points = []
for contour in contours:
    points.extend(contour.T)
points = np.array(points)
# 用PCA做最小二乘拟合主轴
from sklearn.decomposition import PCA
pca = PCA(n_components=2)
pca.fit(points)
# 转换为角度
angle_pca = np.arctan2(pca.components_[0,1], pca.components_[0,0])
angle_pca_deg = dip.RadiansToDegrees(angle_pca)
print(f"PCA拟合角度:{angle_pca_deg}度")

通过拟合所有轮廓点,相比Feret角的单点对,精度和稳定性更优。

4. 多帧平均抵消随机噪声

若设备支持连续采集,对多帧测量结果做平均,抵消单次采集的随机噪声和光源波动:

# 示例:3帧平均逻辑
angles = []
for _ in range(3):
    # 替换为实时图像采集逻辑
    img = dip.ImageRead('back_frame.png')
    # 执行预处理、分割、角度测量流程
    # ...
    angles.append(angle_deg)
avg_angle = np.mean(angles)
print(f"多帧平均角度:{avg_angle}度")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 07:18:11