血管支架直径只有几毫米,上面的金属网丝细得像头发丝,公差却常常要求在几十微米以内。这种零件放到产线上做全检,靠人眼盯显微镜不现实,靠传统接触式测量又容易划伤表面。所以这几年很多医疗器械厂家在找机器视觉方案,Halcon 正是这类场景里相当顺手的一套工具。我前后做过几个显微测量类的视觉项目,血管支架检测是其中比较典型的一个——结构复杂、反光强烈、公差严格,还要同时兼顾缺陷检测和尺寸测量。这篇文章就把完整的技术链路拆开讲一遍,包括方案设计、硬件选型、Halcon 算子链、标定方法,以及现场调试里容易踩的坑。
1. 项目全局:先看懂血管支架检测难在哪
1.1 血管支架为什么是视觉检测里难啃的骨头
血管支架本身的物理特性决定了它比普通五金件难拍得多。首先是尺寸小,支架外径通常只有 2 到 4 毫米,长度在 8 到 40 毫米不等,壁厚或丝径多在 0.05 到 0.2 毫米之间。这意味着视野很小,相机分辨率必须足够高,不然单根金属丝在图像里只占一两个像素,后续测量和缺陷判断根本做不下去。
其次是不锈钢或钴铬合金表面的镜面反射。血管支架大多经过电解抛光,表面光亮,在常规环形光源下会形成大面积高光,金属丝边缘的灰度梯度非常陡。拍出来往往是一边白得溢出、一边黑得看不清,给阈值分割带来很多麻烦。第三个难点是姿态不统一,支架是圆筒状网架结构,放在载具上容易滚动,拍照时各根丝不在同一个焦平面上,景深稍有不足,边缘就会虚。
第四个难点在于公差尺度。支架展开网孔的尺寸、支撑筋的宽度、波峰的间距、末端倒角的形状,都是临床性能的重要参数。有些关键尺寸公差只有正负几十微米,放在 2 毫米直径的零件上,比例上相当于普通机械加工里的微米级精度,视觉系统稍有标定偏差,测出来的数就不可信。
1.2 订单背后那串检测指标到底有哪些
工程上做任何项目,第一步都是把需求翻译成可执行的检测项。血管支架检测通常分成几何尺寸测量和表面缺陷检测两大类。几何测量包括外径、长度、网孔尺寸、支撑筋宽度、波形节距、壁厚、末端圆角等;缺陷检测则包括断丝、裂纹、毛刺、异物附着、锈点、压扁变形、涂层脱落等。有的客户还会要求测量支架在压握状态下的直径变化,或者预装到球囊上的折叠形态,这属于更高阶的定制需求。
不同厂家对这些项目的标准和定义不完全一致。有的把长度定义为两端最远点距离,有的定义为骨架中心线的弧长;网孔尺寸有的测内切圆,有的测对角线距离。如果需求澄清阶段没有逐项确认清楚,后面算法写完、系统平移交付之后再来改,成本会成倍增加。所以项目启动时我会先做一张检测项清单,每个尺寸明确标出定义方式、公差带、量具基准和抽样频率,这部分花的时间往往比写算法还多,但非常值得。
2. 整体方案设计和选型逻辑
2.1 相机、镜头、光源怎么配才不会白费算法工夫
视觉检测里有个基本规律:图像质量决定了算法难度的上限。血管支架这种高反光微细零件,光源和镜头选错了,后面写再多滤波和增强代码都只是修补,不如一开始就把成像做好。
镜头方面,优先考虑远心镜头。普通工业镜头在工作距离变化时放大倍率会变,血管支架本身有高度差,姿态也不是完全水平,普通镜头拍出来的尺寸在图像里会忽大忽小,像素当量不稳定。远心镜头能保证在一定深度范围内,图像放大倍率几乎不变,这对微米级测量非常重要。工作距离和视野要根据目标尺寸反推,例如视野做到 20 毫米左右,配 500 万或 1000 万像素相机,单个像素对应的物理尺寸可以控制在 3 到 5 微米,测量分辨率基本够用。
光源是成像环节里最需要花心思的部分。血管支架反光强,打光方式直接影响边缘提取效果。我常用的组合是背光和同轴光两路照明:背光用来拍支架的整体轮廓和尺寸,金属丝呈暗色、背景亮,边缘对比度好,阈值分割简单;同轴光用来拍表面缺陷,光线垂直照射后反射回来进入镜头,平整区域亮度均匀,凹凸和划痕会产生明显的灰度变化。实际项目中也可以考虑多角度低角度环形光,但要控制亮度和角度,防止大面积镜面反射把纹理细节吞掉。
相机一般用面阵 CMOS 就够,关键是传感器靶面尺寸要和镜头匹配,避免暗角。帧率不是主要矛盾,因为支架检测通常是静态拍照,真正限制节拍的是上下料时间,而不是相机的采集速度。
2.2 Halcon 在这个项目里的位置为什么合适
选 Halcon 而不是费尽心思自己写底层算法,主要原因是时间成本和可靠性。血管支架检测涉及到亚像素边缘提取、轮廓拟合、区域形态学、轮廓比较等大量图像处理算法,Halcon 在这些方面已经封装得很成熟,比如 edges_sub_pix 提取亚像素轮廓、fit_circle_contour_xld 做圆弧拟合、gen_measure_rectangle2 做矩形测量,调用起来非常稳定。这些算子经过了大量工业项目的验证,出问题的概率远低于自己从零实现的版本。
Halcon 的另一个优势是快速原型验证。同一套算法逻辑,在 C++ 里写一遍调试可能要两三天,在 Halcon 的 HDevelop 环境里两个小时就能跑通初步流程,确认可行后再导出为 C# 或 C++ 工程做集成。HDevelop 里有变量监视、图像窗口交互查看中间结果、断点调试,对算法调试来说非常高效。
当然 Halcon 也存在一些限制,比如授权费用较高、运行环境依赖 License,但这在医疗器械类项目中通常可以接受,毕竟客户更看重系统的稳定性和交付周期,而不是省软件成本。
2.3 先定流程再写代码,避免返工
血管支架检测的整体流程可以拆成五个环节:标定、定位、图像预处理、测量或缺陷判断、结果输出。标定负责建立像素和物理尺寸的映射关系,是所有尺寸测量的前提;定位用于将支架调整到统一的坐标系下,抵消载具定位偏差和支架摆放角度变化;预处理负责降噪、增强对比度、去除背景干扰;测量和缺陷判断是核心算法,利用经过定位的标准参考位置来提取特征值;结果输出阶段根据规格判定 OK 或 NG,并保存图像和数据。
这个顺序不要随意打乱。有些工程师一上来就直接做阈值分割和测量,忽略了标定和定位,结果换一只支架或者重新上料后,结果变得不稳定。定位的作用不仅仅是让图像看起来整齐,更重要的是让后续所有 ROI 选框自动对齐,这样在处理大量图像时,算法参数保持一致,不需要根据位置动态变化,稳定性显著提升。如果支架在视野内的位置和角度可以重复到像素级别,后续缺陷检测和尺寸测量会省力得多。
3. Halcon 图像处理管线逐个拆
3.1 预处理:不是所有图都要猛滤波
拿到图像后有人习惯先来一遍中值滤波或者高斯滤波。对于血管支架这种本身具有精细网格结构的零件,滤波半径过大会抹掉细小丝径的边缘细节,反而让测量失真。我的习惯是先观察原始图像的噪声类型:如果是传感器噪声明显,用轻微高斯滤波,Sigma 设置在 0.5 到 1.0 之间;如果是不锈钢纹理造成的高频干扰,用 median_image 配合较小的掩膜尺寸,比如 3x3 或 5x5。到底是滤波还是不滤波,以及滤波强度多大,应当通过处理前后边缘轮廓的亚像素位置稳定性来评估,不要只看视觉上是否变亮变干净。
Halcon 里常用的预处理流程为:先读取图像,转换为灰度图,然后根据实际需要做均值或 Gauss 滤波,再做一次对比度拉伸,例如用 scale_image_max 或 equ_histo_image 增强暗部细节。但要注意对比度拉伸对灰度值做了非线性变化,会在一定程度上改变边缘位置,因此如果后续要做高精度测量,同一条测量链路上的预处理参数必须保持一致,不能在调试中频繁更换。
背景不均匀是血管支架图像另一个典型问题,载具本身可能带有划痕、污渍、反光,而这些区域恰好和支架的边缘接近。这时可以考虑用动态阈值分割,即先估计背景灰度,再在局部范围内比较前景和背景的差异,而不是对整幅图像使用固定灰度阈值。Halcon 中的 dyn_threshold 配合 mean_image 实现动态阈值分割,在这个场景里效果比较明显。更直接的方式是将载具设计成哑光黑色,并做遮光处理,尽量让背景灰度均匀,这比在算法层面硬分割省事得多。
3.2 分割和区域筛选:找出支架的主体
预处理完成后,先要把支架主体区域从背景中提取出来。使用背光照明时,支架在图像中呈现为暗色区域,背景是亮色,直接调用 threshold 算子选择低灰度区间即可。例如灰度范围选在 0 到 80 之间,这只是初始值,实际要根据图像灰度统计来调整。threshold 得到的结果往往是包含几根断丝、阴影、灰尘点等的大量小区域,需要进一步用 connection 将连通的像素分成多个独立区域,再用 select_shape 筛选。
select_shape 是基于区域形状特征做筛选的标准算子,可以根据面积、宽度、高度、矩形度、延伸度等特征过滤掉不想要的干扰区域。例如支架主体区域通常具有较大的面积和较长的轮廓,而灰尘点、孤立噪声的面积很小,可以直接过滤掉。支架网格的形状有可能被误判为多个分离的区域,这时候还需要用 union1 或 union2 将属于同一个支架的多个区域合并回完整区域,尤其是支架的两端由于结构不连续而被分割成两块的情况。必要时还可以用 closing_circle 做闭运算连接断裂处,但这个操作要非常谨慎,闭运算会改变区域边缘轮廓,对后续基于边缘的尺寸测量有影响,仅适合做区域级判断时使用。
对于同轴光成像的缺陷检测流程,分割逻辑则完全不同。缺陷区域往往是高光区域中局部亮度异常的地方,常用 local_threshold 或动态阈值结合灰度形态学提取暗斑、亮斑,然后按缺陷典型尺寸特征筛选。比如毛刺的形态特征表现为细长突出,断丝表现为轮廓缺口,涂层脱落表现为长条状灰度异常,这些都需要有针对性的特征参数才能准确筛选。
3.3 亚像素轮廓提取:把边缘精度推到微米级
像素级边缘在血管支架拍摄条件下往往不够用。一个像素可能对应 3 到 5 微米的物理尺寸,如果直接用像素边缘测量,结果跳跃幅度很大,远远达不到几十微米公差的需求。因此必须使用亚像素边缘提取算子,让边缘定位精度达到 0.1 像素左右。
Halcon 中 edges_sub_pix 是应用最多的亚像素边缘提取算子。它有多种过滤器类型,常用的有 'canny' 和 'lumen'。Canny 边缘检测强调边缘连续性和单像素响应,适合提取清晰的支架外形;lumen 对边缘的灰度过渡模型拟合更好,在镀层边缘、弱对比度场景下能提供更稳定的亚像素精度。参数中高阈值和低阈值需要根据图像灰度梯度的绝对值来设置,设置过高会漏掉低对比度边缘,过低则会把噪声也算成边缘。一般做法是先查看梯度直方图,取一个能保持边缘完整又尽量少出现碎边缘的阈值组合。
提取到亚像素轮廓后,轮廓数据是线状的 XLD 对象,里面会包含大量长度较短的碎轮廓,不方便直接做测量。需要先用 segment_contours_xld 将边缘分解成直线段和圆弧段,再根据长度和曲率筛选真正需要的轮廓。如果目标是一个完整的支架外轮廓,还可以用 select_contours_xld 按长度过滤掉干扰碎片,必要时用 union_adjacent_contours_xld 把割裂的同一边缘重新连接起来,最终生成一条完整的、闭合的支架轮廓,供尺寸测量和缺陷分析使用。
3.4 缺陷特征判断逻辑:不是所有灰度变化都是缺陷
缺陷检测的核心不只是把“异常”找出来,还要避免把正常纹理误判为缺陷。血管支架表面的金属编织纹路、压握痕迹、激光切割痕迹在图像上都有灰度起伏,如果缺陷判定阈值设得过高,正常产品会被大批量误杀;设得过低,真正的缺陷会漏过去。项目前期需要收集足够的良品图像和不良品样本,统计出每个特征的正常波动范围,再设定合理阈值。
缺陷特征通常分成三类。一是几何特征,例如断丝表现为轮廓宽度突变、轮廓局部缺口;毛刺表现为锯齿状突起,异常区域面积小、圆形度高但延伸度与相邻骨架不同;压扁变形表现为整体长宽比、外接矩形尺寸异常。二是灰度特征,例如锈斑往往是一簇暗斑,灰度均值明显低于周围正常丝面;涂层剥落则是灰度反差很大的区域,同时有特定的纹理边缘。三是纹理特征,Halcon 中可以利用滤波响应、灰度共生矩阵等描述符做更精细的区分,但这种做法对算力消耗较高,通常只在普通形态学筛选解决不了问题的时候才使用。
实际工程中我更推荐建立分层判定策略:第一层用几何形状粗筛排除粉尘、水滴和图像噪声,第二层用灰度统计精筛识别疑似缺陷,第三层对可疑区域做局部轮廓检查,判定是否属于真正的支架本体缺陷。这种分层结构的好处是每一层只负责一部分判断,参数独立可调,现场调优时不会牵一发而动全身。
4. 血管支架尺寸测量的标定与实现
4.1 像素当量标定:测准的根本在标定
尺寸测量之前必须有可靠的像素当量标定。这里所谓的像素当量,就是每一个像素对应的物理尺寸,比如 1 像素等于 0.0035 毫米。标定方式主要有两类:使用标准标定板或使用已知尺寸的标准工件。
标定板标定的优点是精度高、通用性好,通常是棋盘格或圆点阵列板。Halcon 中可以使用 find_calib_object 自动提取标定板特征并计算标定结果,最终建立相机内参和畸变模型。对于远心镜头,标定模型与普通镜头不同,Halcon 里需要设置 camera_type 为 'area_scan_telecentric_division' 或类似选项,如果选错了类型,计算出的世界坐标依然在中心区域看着正确,但在视野边缘的测量结果会出现系统性偏差。
标准工件标定的思路更直接,找一个外径、长度经过高精度测量仪器确认过的血管支架或标准圆柱,放在视野中拍图,用算法测量出像素尺寸,再用已知物理尺寸反算像素当量。这种方式的优点是标定过程非常贴近真实工件状态,光源反射情况和支架一致,缺点是只对同一类支架有效,换型号就要重新标定。实际项目中我会两种方式配合使用:先用标定板建立镜头畸变模型,再用标准工件做最终的像素当量修正,兼顾全局精度和局部一致性。
4.2 Halcon 测量算子组合:从外径到网孔尺寸
尺寸测量的实现我一般不用只靠 Blob 区域的那种“测区域宽高”的粗糙方法,而是基于亚像素边缘轮廓做拟合。举个外径测量的典型例子:血管支架在背光下提取出整体轮廓后,左右两侧各是一段近似圆弧的 XLD 轮廓,可以用 fit_circle_contour_xld 分别拟合左右轮廓,得到两个圆心和半径,再根据圆心距离和半径计算出支架在该位置的截面宽度。如果支架截面是规则圆形,也可以直接对单侧轮廓拟合圆弧,通过半径乘以 2 得到直径,但这种方式要求支架轴线与相机光轴严格垂直,稍有角度偏差测量误差就会被放大。
对于支撑筋宽度这类小尺寸测量,常规做法是测量线与边缘垂直相交的两点间距。Halcon 的 measure_pos 算子可以定义一条测量线段,沿线段采样灰度值,再通过边缘灰度变化定位边界点。将测量线旋转到与骨架方向垂直的位置,获取边缘位置后计算两点距离,即可得到丝宽。这里有一个关键细节:单次测量的误差来源非常多,比如光照变化导致的灰度斜率变化、支架摆放角度微小不同、镜头畸变残余等,因此建议在同一条测量位置重复采集多帧图像,对多个测量点做平均,用统计值作为最终的实测数据,而不是取单帧测量值。
网孔尺寸的测量比较特殊,因为网孔形状不是规整的圆或矩形,而是由波形丝围成的多边形。我通常提取网孔周围骨架的中线或亚像素轮廓,利用相邻交点计算孔的对角长度、内切圆半径等参数。这个过程比较依赖高精度的边缘提取和交点计算,Halcon 中 get_contour_xld 获取轮廓点序列后可以自行计算交点,也可以使用 fit_line_contour_xld 拟合直线后计算其交点,两者得到的测量值含义不同,需要跟客户确认最终以哪个几何定义为验收标准。
4.3 测量重复性:为什么必须做 GR&R 验证
算法跑通之后,不能只看一个样品测一次准不准,关键要看同一工件反复装夹拍照时测量值的重复性和再现性。这是医疗器械视觉检测项目的验收重点之一。所谓重复性,指同一台设备、同一个操作员、同一工件在多次测量中结果的一致程度;再现性则指不同操作员或不同时间段内结果的一致性。
实际做法是选取 3 个覆盖公差范围的标准支架,每个支架在不同时间分别测量 10 次,记录测量结果,计算每组数据的极差和标准差。一个参考标准是每个关键尺寸的波动范围应当小于公差带的三分之一,理想情况下小于十分之一更稳。如果重复性波动过大,就要回溯到成像环节,看是光源闪烁、震动、夹具不稳,还是边缘提取参数选择不当。很多项目到了验收阶段才发现重复性不合格,往往不是算法的问题,而是硬件平台没有做防震处理,或者支架在载具里的定位方式不够可靠。
5. 缺陷判定逻辑与实际落地的三个细节
5.1 判定逻辑设计:用特征组合替代单点阈值
血管支架的缺陷形态丰富,单靠一个特征阈值几乎不可能覆盖所有情况。比较合适的做法是针对每一类缺陷设计一组特征向量,再以逻辑组合方式判断。例如锈斑类缺陷,最典型的特征是区域灰度均值显著低于正常丝面、灰度方差较大、边界不规则。真正的锈斑通常同时满足这几项条件,而单纯阴影、水渍等干扰往往只满足其中一两项,利用这种组合可以显著降低误判率。
在 Halcon 中实现并不复杂,对每个可疑区域运行 area_center、gray_features、select_shape 等算子,提取面积、灰度均值、灰度方差、矩形度、凸性等特征,然后在 HDevelop 里用一个公式把多个特征加权组合成评分,超过设定分数才判定为缺陷。这比直接用一个灰度阈值判断要稳健得多。每类缺陷都要单独建立一套特征模型,不能指望一个万能参数解决所有缺陷问题。
5.2 落地时的三个隐藏坑
第一个坑是曝光时间不稳定。现场的环境光、光源控制器老化、相机增益自动模式都会导致图像明暗发生微小变化,虽然人眼看不出来,但亚像素边缘位置会发生漂移,直接影响测量结果。解决方式是关闭相机的自动曝光和自动增益,打光使用恒流控制或反馈稳定型光源控制器,并在系统启动时做白平衡校正和亮度基准监测。
第二个坑是支架在载具中的姿态不一致。血管支架是柔性件,即便初始摆放方向一致,载具运动过程中的震动、气压变化也会让它滚动或翘起。当支架倾斜时,投影宽度会比真实尺寸大。解决方案是设计 V 型槽或磁性压持载具,并增加一个姿态检测环节:在定位算法中同时拟合支架两端端面的位置,如果发现倾斜角度超过阈值,就触发重新定位,避免把倾斜引起的尺寸变化误判为不合格品。
第三个坑是高频噪声和细小缺陷的取舍。血管支架丝径很细,缺陷往往也很小,但图像中同样存在金属纹理带来的高频噪声。很多算法调试过程中,为了让缺陷更清晰而加大锐化,结果噪声也被放大,导致误判率飙升。我的经验是先保持图像原始灰度特征,优先用几何特征识别缺陷,当几何特征无法区分时再考虑引入频域特征,不要一上来就做很强的增强处理。
6. 现场实施中的常见问题与排查心得
6.1 现场常见问题速查表
血管支架视觉检测项目从开发到交付,最容易碰到下面这些情况,我整理了一张排查对照表,基本覆盖了大部分现场问题的排查方向。
| 问题现象 | 常见原因 | 调整方向 |
|---|---|---|
| 同一工件测量结果波动大 | 支架在位姿不稳、震动、光源闪烁 | 先检查机械定位和固定方式,再排查光源驱动稳定性 |
| 边缘轮廓时断时续 | 阈值设置过高、光照不均、景深不足 | 降低分割阈值,调整光源角度,检查镜头景深范围 |
| 实际尺寸偏大或偏小但有规律 | 像素当量标定不对或镜头类型选错 | 重新做标定,确认远心镜头模型,使用标准件复核 |
| 微缺陷检测与良品误判矛盾 | 特征阈值单一或滤波过度 | 改用多特征组合判定,减少过度平滑处理 |
| 不同批次产品检测结果不一致 | 前工序电抛光效果波动 | 与工艺沟通确认批次差异,增加灰度归一化环节 |
| 系统长时间运行后结果漂移 | 光源衰减、相机温度变化 | 定期做亮度基准检测,增加光源寿命预警 |
6.2 调试阶段最值得花时间的环节
很多项目组喜欢把时间花在调阈值上,但实际经验告诉我,最值得花时间的环节是样品样本收集和需求定义。血管支架的不良品类型多样,如果前期没有收集到足够多的真实缺陷样品,算法训练和验证都没有依据。我会建议客户在项目启动前先提供三批样品:一批良品,用来确定正常的特征波动范围;一批典型不良品,覆盖每类缺陷的最明显形态;一批边界不良品,专门用来卡验收标准和误判率。有了这三批样品,算法的参数标定和验收测试才能做扎实。
实际上,输出来自于高质量的输入,视觉检测项目尤其如此。光源调试的阶段,我会带着相机在现场反复试不同角度、不同高度的照明方案,把支架各个朝向的图像都拍下来观察,直到找到一个在大多数姿态下都能稳定呈现出清晰轮廓的成像方案,然后才进入算法开发。过早进入算法阶段而忽略成像优化,往往会把问题复杂化,提高算法开发难度,拉长整个项目周期。
我在实际项目中的体会是,血管支架视觉检测成功的关键,第一步是光学成像,第二步是标定稳定性,第三步才是算法逻辑。软件算法在 Halcon 中确实强大且高效,但前提是在前面的环节把图像和标定做扎实。完成一个稳定的检测系统,往往不是靠某一个高级算子一锤定音,而是把成像、硬件定位、特征定义、统计验证这些基础环节一步步做扎实。如果手头也有类似的高精度细丝类零件检测需求,可以先从成像实验开始,用不同光源组合拍摄一版,再对比 Halcon 的边缘提取效果,你会很快找到适合项目的技术路径。