Halcon实战:5个工业质检案例教你玩转机器视觉(附完整代码)
在制造业的产线上,视觉质检早已不是“锦上添花”的选项,而是关乎良率、成本和效率的“生命线”。然而,许多工程师和集成商都面临一个共同的困境:手里握着像Halcon这样功能强大的视觉软件库,却感觉无从下手,或者只能实现一些基础功能,面对复杂的真实工业场景时,方案总是不够稳健。这背后,往往不是工具本身的问题,而是缺乏一套将强大算子与具体问题深度结合的“组合拳”思维。
这篇文章,我们就来打破这种“知道强大但不会用”的僵局。我不会泛泛而谈Halcon的2100多个算子有多厉害,而是直接切入五个在电子、机械、包装等行业中极具代表性的质检难题。每个案例,我都会像在现场调试一样,带你走一遍完整的流程:从拿到问题图像开始,分析难点在哪里,为什么常规方法会失效,然后一步步拆解,告诉你我为什么选择这几个特定的算子,它们的参数背后有什么物理意义,调优时我踩过哪些坑,最后用完整的代码把方案固化下来。我的目标是,你看完不仅能复现这五个案例,更能掌握一种解决视觉问题的通用方法论,下次遇到新项目时,能自己设计出可靠的方案。
1. 案例一:精密金属零件的亚像素尺寸测量与公差判定
在精密加工行业,零件的尺寸公差往往要求在微米级别。用传统的像素级边缘检测,一个像素的误差就可能让合格品被判为不良。这个案例,我们处理的是一个带有倒角的金属连接件,需要测量其内径、外径以及倒角的角度,公差带为±0.02mm。
核心挑战在于:金属表面可能存在反光,边缘并非理想的黑白过渡,而是带有渐变和噪声。直接二值化会丢失亚像素精度,而简单的边缘检测算子对光照变化又过于敏感。
我的思路是分三步走:首先用滤波抑制噪声但保留边缘,然后用亚像素边缘检测提取精准的边缘轮廓,最后通过几何拟合和坐标变换得到精确的尺寸。
第一步,图像预处理。我放弃了全局阈值,因为反光会导致局部过曝。这里采用动态阈值分割结合形态学来稳定区域。
* 读取图像
read_image (Image, 'metal_part_01.png')
* 转换为灰度图(如果原是彩色)
rgb1_to_gray (Image, GrayImage)
* 使用中值滤波去除椒盐噪声,同时较好保持边缘
median_image (GrayImage, ImageMedian, 'circle', 2, 'mirrored')
* 利用局部均值和标准差进行动态阈值分割,对光照不均鲁棒
var_threshold (ImageMedian, Region, 20, 20, 0.2, 2, 'dark')
* 将区域连通,并选择面积在合理范围内的区域
connection (Region, ConnectedRegions)
select_shape (ConnectedRegions, SelectedRegions, 'area', 'and', 500, 5000)
提示:
var_threshold算子的Offset参数(这里为0.2)是关键,它决定了局部对比度的灵敏度。对于低对比度边缘,需要调小此值;对于噪声大的图像,则需要调大。
第二步,亚像素边缘提取。这是精度提升的核心。我使用edges_sub_pix算子,它基于Canny或Deriche等算法,能提供子像素精度的边缘轮廓。
* 在选定的区域内部,进行亚像素边缘检测
* 使用Deriche滤波器,它在噪声抑制和边缘定位间有较好平衡
edges_sub_pix (ImageMedian, Edges, 'deriche2', 0.5, 20, 40)
* 将边缘轮廓与之前选定的区域做交集,只保留零件边缘
intersection (Edges, SelectedRegions, EdgeInRegion)
现在,我们得到了一组亚像素精度的边缘点EdgeInRegion。第三步是几何拟合与测量。内径和外径是圆,倒角是直线。
* 将边缘轮廓分割为不同的弧段,便于分别拟合
segment_contours_xld (EdgeInRegion, ContoursSplit, 'lines_circles', 5, 4, 2)
* 选择可能是圆的弧段(基于特征如圆度)
select_shape_xld (ContoursSplit, CircularArcs, 'circularity', 'and', 0.8, 1.0)
* 拟合圆,得到圆心和半径
fit_circle_contour_xld (CircularArcs, 'algebraic', -1, 0, 0, 3, 2, RowCenter, ColumnCenter, Radius, StartPhi, EndPhi, PointOrder)
* 选择可能是直线的弧段(倒角边)
select_shape_xld (ContoursSplit, LineArcs, 'contlength', 'and', 50, 1000)
* 拟合直线
fit_line_contour_xld (LineArcs, 'drop', -1, 0, 5, 2, RowBegin, ColBegin, RowEnd, ColEnd, Nr, Nc, Dist)
得到拟合的几何参数后,我们需要将其从像素单位转换到物理单位(毫米)。这需要事先进行相机标定,获取像素当量(例如,0.005 mm/pixel)。假设我们已经有了标定结果Scale。
* 物理尺寸计算
InnerDiameter := 2 * Radius[0] * Scale
OuterDiameter := 2 * Radius[1] * Scale
* 计算两条倒角线的夹角
angle_ll (RowBegin[0], ColBegin[0], RowEnd[0], ColEnd[0], RowBegin[1], ColBegin[1], RowEnd[1], ColEnd[1], Angle)
ChamferAngle := deg(Angle) // 转换为角度制
* 公差判定
IsInnerDiaOK := (InnerDiameter >= 5.98) and (InnerDiameter <= 6.02)
IsOuterDiaOK := (OuterDiameter >= 10.98) and (OuterDiameter <= 11.02)
IsAngleOK := (ChamferAngle >= 44.5) and (ChamferAngle <=

2万+

被折叠的 条评论
为什么被折叠?



