4. 图像预处理算子选型与加速

在 HALCON 高速视觉应用中,预处理往往不是“精度瓶颈”,而是“节拍瓶颈”。一条 500 万像素、8 bit 灰度图的生产线,若把 rgb1_to_gray、gauss_filter、gray_opening_rect、threshold 四个算子串起来,单帧耗时可能从 3 ms 膨胀到 20 ms 以上,直接吃掉相机 200 fps 的采集余量。本节围绕这四类预处理算子,讨论它们的耗时构成、选型依据与可落地的替代方案。

一、四类算子的耗时构成与量级

先建立量级概念。以下数据为在典型工控机(Intel i7-12700,HALCON 24.11,单线程,图像 2448×2048)上的示例性参考值,用于说明相对关系,实际值需以现场 count_seconds 或 get_system_time 实测为准:

算子典型耗时耗时主导因素可替代方向
rgb1_to_gray1.5~3 ms逐像素三通道加权相机端 Bayer 转换 / 硬件 ISP
gauss_filter (σ=2, 5×5)6~12 ms可分离卷积,两次一维binomial_filter、mean_image、降采样
gray_opening_rect (15×15)8~20 ms结构元尺寸平方级gray_erosion_rect+gray_dilation_rect 分离、ROI 裁剪
threshold0.5~1.5 ms单次遍历,几乎线性基本无需替代,可合并到 fast_threshold

关键结论:滤波与形态学是耗时大户,阈值分割几乎免费。优化重心应放在前两者,而不是反复调阈值参数。

二、灰度变换:能省则省,能前置则前置

灰度变换包括 rgb1_to_gray、rgb3_to_gray、scale_image、invert_image、equ_histo_image 等。它们的共同特征是逐像素、无邻域依赖,因此耗时与像素数严格成正比。

实践中有三条加速路径。第一,把转换推到采集端:多数工业相机支持在 FPGA 内完成 Bayer→Gray 或 RGB→Gray,输出即单通道,主机侧直接省掉 1.5~3 ms。第二,用查找表替代逐像素运算:当灰度变换是固定映射(如 scale_image 的线性拉伸)时,可用 lut_trans 配合 256 项 LUT,把乘法降为查表。第三,合并同类项:若后续还要做 scale_image,可把增益与偏移直接写进 rgb1_to_gray 的权重参数,避免两次遍历。

判断依据:若某灰度变换算子的耗时占比超过总预处理时间的 15%,且相机支持硬件转换,优先改相机配置,而不是优化主机代码。

三、滤波:可分离性与结构元尺寸决定一切

滤波算子的耗时由“邻域大小 × 是否可分离 × 数据类型”三者决定。gauss_filter 内部已做可分离优化,5×5 与 7×7 的差距并不悬殊;但 median_image 这类排序滤波无法分离,7×7 中值滤波的耗时可能是同尺寸高斯滤波的 5~8 倍。

替代方案按优先级排列:

  • 降采样后再滤波:若目标特征尺寸大于 4 像素,可先 zoom_image_factor 缩小 2 倍,滤波后再放大回原尺寸做定位。示例:2448×2048 缩到 1224×1024,gauss_filter 耗时约降为 1/4。
  • 用 binomial_filter 替代 gauss_filter:二项式系数为整数,无浮点运算,在 σ 较小时速度更快,且对边缘的平滑特性接近高斯。
  • 用 mean_image 替代:当只需抑制随机噪声、不关心频率响应时,均值滤波可用积分图实现,大窗口下反而比高斯快。
  • ROI 裁剪:若只关心图像中 20% 区域,先 reduce_domain 再滤波,耗时按面积比例下降。

四、形态学:结构元尺寸是平方级成本

gray_opening_rect、gray_closing_rect、gray_erosion_rect 等矩形结构元形态学算子,其耗时大致与结构元宽高的乘积成正比。15×15 的开运算比 5×5 慢约 9 倍,这是很多工程师在“把结构元调大一点去噪”时踩到的坑。

加速策略有三条。其一,拆分为腐蚀+膨胀:gray_opening_rect 本质是 gray_erosion_rect 后接 gray_dilation_rect,若中间结果还要复用(例如同时需要腐蚀图和开运算图),拆开可避免重复计算。其二,用行列分离结构元:矩形结构元可分解为水平与垂直两次一维操作,HALCON 的 *_rect 系列已内部优化,但自定义结构元时需注意。其三,改用 rank_image 或 median_image:当形态学目的是去小噪点时,中值滤波往往能以更小窗口达到类似效果。

注意:形态学结构元尺寸不要盲目取大。若 3×3 开运算已能去除目标噪点,就不要用 7×7;每增大一档,耗时约增加 4~5 倍。

五、阈值分割:几乎免费,但可合并

threshold 是单次遍历算子,2448×2048 图像约 0.5~1.5 ms,通常不是优化重点。但有两个细节值得注意:一是 fast_threshold 在满足条件时提前退出,对高对比度图像更快;二是若阈值后紧接 connection 或 select_shape,可考虑用 threshold_sub_pix 或直接在 ROI 内做阈值,减少连通域数量。

六、选型决策与实测方法

面对一个具体任务,建议按以下顺序决策:先确认是否可用相机端硬件完成灰度转换;再判断滤波是否可降采样或换用二项式;然后检查形态学结构元能否缩小或拆分;最后才考虑阈值参数。每一步都用 count_seconds 实测,而不是凭经验估算。

count_seconds (T1)
rgb1_to_gray (Image, GrayImage)
count_seconds (T2)
gauss_filter (GrayImage, Filtered, 3)
count_seconds (T3)
threshold (Filtered, Region, 80, 255)
count_seconds (T4)
* 各段耗时:T2-T1、T3-T2、T4-T3

下图给出四类算子的耗时占比与替代路径关系,可作为现场选型的快速参照。

四类预处理算子耗时占比与替代路径 相对耗时(示例,2448×2048) 灰度变换 1.5~3 ms 滤波 6~12 ms 形态学 8~20 ms 阈值分割 0.5~1.5 ms 替代/加速路径 相机端 Bayer→Gray / LUT 查表 降采样 / binomial_filter / mean_image 拆分腐蚀+膨胀 / 缩小结构元 / ROI fast_threshold / ROI 内阈值 选型决策顺序(自上而下,命中即停) ① 相机端转换 → ② 降采样/换滤波 → ③ 缩小结构元 → ④ 合并阈值/ROI 实测工具:count_seconds / get_system_time,逐段计时,定位占比最大的算子。 判断阈值:单算子占比 > 30% 时优先优化;< 10% 时可暂缓。 注:以上耗时均为示例性参考值,实际以现场硬件与 HALCON 版本实测为准。

把上述方法落到一个具体案例:某连接器引脚检测,原流程为 rgb1_to_gray → gauss_filter(5×5) → gray_opening_rect(9×9) → threshold,单帧 18 ms。优化后:相机改为输出灰度图(省 2 ms),高斯改为 binomial_filter(5×5)(省 3 ms),形态学结构元缩为 5×5 并只在引脚 ROI 内执行(省 7 ms),总耗时降至约 6 ms,满足 120 fps 节拍。这个案例说明:预处理加速的收益主要来自“换算子、缩范围、前置硬件”,而不是微调参数。

最后强调一个工程习惯:每次修改预处理链后,都要用同一帧图像、同一硬件、同一 HALCON 版本重新计时,并记录各算子耗时占比。只有把耗时数据固化下来,才能在后续增加新算子时快速判断是否超出节拍预算。