3. 图像采集与可复现数据管理

在工业视觉项目里,算法效果不稳定,很多时候问题并不出在算子参数,而是出在“数据入口”。同一批工件,今天用 GigE 相机在线抓取,明天用昨天保存的 PNG 回放,光照、曝光、增益、镜头工作距离稍有变化,图像灰度分布就会漂移,后续的阈值分割、模板匹配、测量结果自然无法复现。因此,可复现工程的第一步,是把“图像从哪来、以什么参数来、以什么名字存、怎么划分、附带什么信息”这五件事固定下来。

相机接口:先分清在线采集与离线回放

HALCON 通过图像采集接口(image acquisition interface)统一访问不同厂商相机。常见的有 GigEVision2、GenICamTL、USB3Vision、DirectShow,以及针对特定品牌的 Basler、uEye 等接口。接口名通过 open_framegrabber 的第一个参数指定,例如:

open_framegrabber ('GigEVision2', 0, 0, 0, 0, 0, 0, 'progressive',
                    -1, 'default', -1, 'false', 'default',
                    '192.168.1.10', 0, -1, AcqHandle)
grab_image (Image, AcqHandle)

这里 '192.168.1.10' 是相机标识,'default' 表示使用相机当前配置。关键点在于:在线采集与离线回放必须能互相替代。工程上通常把采集封装成一个函数,在线时调用 grab_image,离线时用 read_image 读取同一命名规则的图像序列,二者输出同一类型的 HObject,后续处理代码完全不变。这样调试阶段可以用离线图快速迭代,上线时只切换数据源。

图像文件与序列命名:让文件名承载可追溯信息

工业现场最容易失控的是命名。建议采用“固定字段 + 定长序号”的结构,例如:

LineA_Station03_Cam01_20240517_000123.png
工件类型_工位_相机_日期_序号

字段之间用下划线分隔,序号用 6 位定长补零,保证按文件名排序即按采集顺序排序。HALCON 读取序列时可用 list_files 配合 tuple_sort,或直接用 read_sequence。若同一工位存在多相机,建议在文件名中保留相机编号,避免多路图像混叠。对于需要保存中间结果的场景,可在文件名后追加处理阶段后缀,如 _raw、_seg、_measure,但原始采集图必须保持只读,任何处理结果另存,不得覆盖原图。

采集参数固化:把“当时怎么拍的”写进配置

可复现的核心是参数固化。影响图像灰度的主要参数包括曝光时间、增益、光源亮度、镜头光圈、工作距离、触发模式。这些参数不能只存在于操作员记忆里,而应写入一份采集配置文件,与图像序列同目录保存。示例配置如下:

[camera]
interface = GigEVision2
device = 192.168.1.10
exposure_us = 8000
gain_db = 0
trigger = software

[optics]
lens = 25mm
working_distance_mm = 320
aperture = F5.6

[lighting]
channel = 1
intensity = 72
mode = continuous

每次采集前读取该配置并通过 set_framegrabber_param 下发,例如 set_framegrabber_param (AcqHandle, 'ExposureTime', 8000)。采集完成后,把实际生效值再回读一次并记录,防止相机未接受某参数而静默使用默认值。这一步是很多项目复现失败的隐藏原因。

数据集划分与元数据记录

数据集划分要避免“同一工件既在训练又在测试”。正确做法是按工件或按批次划分,而不是按图像随机划分。例如 100 个工件,70 个用于建立模板与调参,30 个用于验证;同一工件的多张图像只能落在同一侧。划分结果写入 split.csv,字段包括文件名、工件号、批次、划分标签、采集配置版本。

元数据建议至少记录:采集时间、相机型号与序列号、曝光/增益、光源强度、配置版本号、操作员、图像尺寸与像素格式。这些信息可以写入 CSV,也可以嵌入文件名。元数据的作用是当结果异常时,能快速定位是“这批图本身拍得不一样”,还是“算法参数变了”。

建议把“采集配置版本号”作为元数据主键之一。同一版本号对应同一组曝光、增益、光源参数,复现时先核对版本号,再谈算法。
图像采集与可复现数据管理链路 在线采集 GigEVision2 / USB3 open_framegrabber grab_image 离线回放 read_image / read_sequence 同一命名规则 同一 HObject 类型 采集参数固化 曝光时间 8000 µs 增益 0 dB 光源强度 72 工作距离 320 mm 光圈 F5.6 触发 software set_framegrabber_param 采集后回读校验 序列命名与存储 LineA_Station03_Cam01_20240517_000123.png 字段:工件_工位_相机_日期_序号 原始图只读,处理结果另存 数据集划分 按工件/批次划分,不按图像随机划分 70 工件调参 / 30 工件验证 split.csv:文件名,工件号,批次,标签 元数据记录(与图像同目录) 采集时间 · 相机型号/序列号 · 曝光/增益 · 光源强度 · 配置版本号 · 操作员 · 图像尺寸/像素格式 作用:结果异常时区分“图像拍得不一样”还是“算法参数变了” 配置版本号 = 复现主键

一个可执行的采集与归档流程

把上述内容串成一个可执行流程,建议按以下顺序落地。第一步,读取 acquisition.ini,用 open_framegrabber 打开相机,逐项 set_framegrabber_param 下发曝光、增益、触发模式。第二步,采集前先抓一帧预览,用 min_max_gray 检查灰度范围,若最大灰度接近 255 说明过曝,需下调曝光或光源;若最大灰度低于 120 说明欠曝,需上调。第三步,正式采集并按命名规则写盘,同时把实际生效参数追加写入 metadata.csv。第四步,按工件号划分数据集,生成 split.csv。第五步,离线复现时先读 split.csv 和 metadata.csv,核对配置版本号,再 read_image 回放。

不要用“随机划分”处理同一工件的多张图像。同一工件的不同角度、不同光照图高度相关,随机划分会让验证集泄漏训练信息,指标虚高,上线后失效。

最后强调一点:可复现不是“把图存下来”这么简单,而是让采集参数、命名规则、划分逻辑、元数据四者形成闭环。只要配置版本号一致、命名可排序、划分按工件隔离、元数据可查,即使换一台电脑、换一个操作员,也能用同一批图跑出同一组结果。这才是工业视觉工程从“能跑”走向“可交付”的关键一步。