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_gray | 1.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 裁剪 |
threshold | 0.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 的权重参数,避免两次遍历。
三、滤波:可分离性与结构元尺寸决定一切
滤波算子的耗时由“邻域大小 × 是否可分离 × 数据类型”三者决定。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:当形态学目的是去小噪点时,中值滤波往往能以更小窗口达到类似效果。
五、阈值分割:几乎免费,但可合并
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
下图给出四类算子的耗时占比与替代路径关系,可作为现场选型的快速参照。
把上述方法落到一个具体案例:某连接器引脚检测,原流程为 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 版本重新计时,并记录各算子耗时占比。只有把耗时数据固化下来,才能在后续增加新算子时快速判断是否超出节拍预算。