3. 图像采集与数据预处理
图像采集,说白了就是让相机听话。你模型再强,拿到的图是糊的、歪的、曝光过度的,后面全白搭。我见过太多团队在算法上死磕,结果发现是相机触发没配好——嗯,这种坑踩一次就够了。
3.1 相机SDK二次开发:让相机听你指挥
工业相机不像手机摄像头,插上就能用。你得通过SDK跟它对话。我个人习惯把SDK调用分成三个层次:
| 层次 | 典型SDK | 核心操作 |
|---|---|---|
| 设备枚举与连接 | Halcon、MVS、Basler Pylon | 枚举相机、打开设备、获取句柄 |
| 参数配置 | 同上 | 曝光时间、增益、触发模式、ROI |
| 图像采集与回调 | 同上 | 软触发/硬触发、回调函数、缓冲区管理 |
拿海康MVS举个例子。你调用MV_CC_EnumDevices枚举设备,拿到设备信息后调用MV_CC_CreateHandle创建句柄,然后MV_CC_OpenDevice打开。配置参数时用MV_CC_SetFloatValue设曝光,用MV_CC_SetEnumValue设触发模式。最后启动采集,注册回调,图像数据就源源不断进来了。
关键点:回调函数里千万别做耗时操作。我曾经在回调里直接做图像预处理,结果丢帧丢到怀疑人生。正确的做法是回调里只做内存拷贝,把数据扔到队列里,另起线程处理。
3.2 图像格式转换:Bayer、RGB、灰度,别搞混了
工业相机输出的原始数据,大多是Bayer格式。每个像素只记录一种颜色分量,得通过插值才能变成RGB。我刚开始做视觉时,直接拿Bayer数据当灰度图用,结果检测精度惨不忍睹——后来才发现颜色信息全乱了。
常见的格式转换路径:
- Bayer → RGB: 用双线性插值或边缘感知插值。Halcon里
cfa_to_rgb一步搞定,MVS里用MV_CC_ConvertPixelType。 - RGB → 灰度: 加权平均法,公式
Gray = 0.299R + 0.587G + 0.114B。别用简单平均,人眼对绿色最敏感。 - Bayer → 灰度: 直接取绿色通道,因为Bayer阵列里绿色像素占一半,信噪比最高。
我的习惯: 如果后续只做缺陷检测,我建议直接转灰度。RGB三通道数据量是灰度的3倍,但很多缺陷在灰度图上已经足够明显。省下来的内存和算力,留给模型不香吗?
3.3 ROI提取:只关注关键区域
一张工业图像,往往只有10%-30%的区域包含有效信息。剩下的都是背景、传送带、夹具。ROI提取就是把这些无关区域切掉。
我常用的ROI提取方式:
- 固定坐标裁剪: 适用于相机和工件位置固定的场景。直接指定左上角和右下角坐标。
- 模板匹配定位: 工件位置有偏移时,先用模板匹配找到位置,再动态计算ROI。Halcon里
find_shape_model配合reduce_domain。 - 边缘检测自适应: 用Canny或Sobel找工件边缘,然后外接矩形。适合形状不固定的工件。
注意: ROI不要切得太极限。留5-10像素的余量,防止工件轻微抖动导致缺陷被切掉。我曾经为了省计算量,把ROI卡得死死的,结果一个0.5mm的划痕刚好在边界上——漏检了。
3.4 图像增强:让缺陷无处遁形
图像增强不是为了好看,是为了让缺陷特征更明显。我把它分成两类:全局增强和局部增强。
3.4.1 直方图均衡化
直方图均衡化,说白了就是把图像的灰度分布拉开。原本集中在暗区的像素,会被映射到整个0-255范围。这样原本看不清的细节就出来了。
但要注意,全局直方图均衡化容易放大噪声。我更喜欢用自适应直方图均衡化(CLAHE),它把图像分成小块,每块单独做均衡化,然后用双线性插值消除块效应。OpenCV里cv2.createCLAHE就能实现。
实战经验: 检测金属表面的细微划痕时,CLAHE的效果远好于全局均衡化。我一般把clipLimit设在2.0-3.0,tileGridSize设为8x8。太大容易过增强,太小又没效果。
3.4.2 滤波:去噪与增强
滤波是双刃剑。去噪的同时,也可能把缺陷边缘磨平了。我常用的几种滤波:
| 滤波类型 | 适用场景 | 缺点 |
|---|---|---|
| 高斯滤波 | 去除高斯噪声,平滑图像 | 边缘模糊,细节丢失 |
| 中值滤波 | 去除椒盐噪声,保留边缘 | 计算量大,不适合实时 |
| 双边滤波 | 去噪同时保留边缘 | 参数难调,速度慢 |
| 非局部均值去噪 | 高质量去噪,纹理保留好 | 极慢,离线处理用 |
我个人在工业现场用得最多的是中值滤波。虽然慢一点,但边缘保留效果最好。如果对速度有要求,我会用高斯滤波配合后续的边缘增强算子来补偿。
3.5 完整流程:从相机到预处理
把上面这些串起来,一个典型的图像采集与预处理流程是这样的:
这个流程看起来长,但实际在工业现场,大部分步骤都是固化在产线启动前的配置里。真正运行时,只有采集、转换、ROI、增强这几步在循环。
我的建议: 预处理流程一定要在项目初期就定下来。别等到模型训练完了,才发现图像格式不对或者ROI偏了。我见过一个项目,数据采集和模型训练是两拨人做的,结果采集的图是BGR,训练用的却是RGB——整整浪费了两周。
3.6 避坑指南
- 相机触发延迟: 软触发有毫秒级延迟,高速产线必须用硬触发。我曾经用软触发检测每分钟600个工件,结果每10个就漏1个。
- 缓冲区溢出: 采集速度大于处理速度时,缓冲区会满,导致丢帧。解决方案是用环形缓冲区,或者降低采集帧率。
- 图像格式陷阱: 有些相机输出的是12位或16位深度图,直接当8位用会丢失细节。记得做位深映射。
- 滤波参数过调: 滤波核太大,小缺陷直接被抹平了。我一般从3x3开始试,最多到7x7。
嗯,图像采集和预处理这部分,说白了就是给模型喂干净、标准化的数据。数据质量决定了模型的天花板,后面的训练和调参只是在逼近这个天花板。所以,别在这步偷懒。