3、工业视觉检测基础:相机选型与光源设计、图像采集与预处理、传统图像处理算法的局限性
各位同学,欢迎来到第三章。这一章咱们聊聊工业视觉检测的「地基」。
说实话,很多做算法的人容易忽视这部分。觉得相机选型、光源设计那是硬件工程师的事。我当年也这么想,结果呢?在项目现场被折腾得够呛。你算法再牛,图像拍出来是糊的、对比度不够,神仙也救不了。
所以,这一章我会把我在风电叶片检测项目里踩过的坑、积累的经验,毫无保留地讲给你听。
3.1 相机选型:别只看像素,要看「能不能看清」
相机选型,说白了就是回答一个问题:你要检测的最小缺陷,在图像上至少占几个像素?
我个人习惯,先定分辨率,再看帧率,最后考虑接口和传感器类型。
3.1.1 分辨率怎么定?
举个例子。风电叶片上的裂纹,宽度可能只有0.2mm。你希望一个裂纹在图像上至少占3个像素,才能被算法稳定检测到。那么每个像素对应的实际尺寸(即像素当量)就是:
像素当量 = 裂纹宽度 / 像素数 = 0.2mm / 3 ≈ 0.067mm/pixel
假设你要拍摄的视场(FOV)是500mm宽,那么需要的水平分辨率就是:
分辨率 = FOV / 像素当量 = 500mm / 0.067mm/pixel ≈ 7463 pixel
嗯,这就意味着你至少需要一颗800万像素的相机。我在项目中遇到过,有人用200万像素的相机去拍大视场,结果裂纹在图像上就一两个像素,边缘检测根本跑不出来。白费功夫。
3.1.2 传感器类型:CCD vs CMOS
现在工业相机主流是CMOS。CCD虽然噪声低,但速度慢、功耗高,已经逐渐被淘汰了。不过,如果你做的是高精度静态检测,比如叶片出厂前的终检,CCD的全局快门和低噪声还是有优势的。
| 参数 | CCD | CMOS |
|---|---|---|
| 噪声 | 低 | 中等(但现代CMOS已大幅改善) |
| 帧率 | 低 | 高 |
| 功耗 | 高 | 低 |
| 成本 | 高 | 低 |
| 适用场景 | 静态高精度 | 动态、高速、产线 |
3.2 光源设计:打光打得好,算法少烦恼
你想想看,图像的本质是什么?是物体对光的反射。光源设计,就是人为地制造出「目标区域亮、背景区域暗」的对比度。
我曾经在叶片表面裂纹检测上栽过跟头。当时用环形光正面打,结果裂纹和表面纹理混在一起,阈值分割根本分不开。后来换成低角度条形光,让裂纹产生明显的阴影,效果立竿见影。
3.2.1 常见光源类型与选型
- 环形光源: 适合检测字符、划痕。但容易产生反光,不适合高反光表面。
- 条形光源: 我最常用的。低角度照射能突出表面凹凸,裂纹、凹坑一目了然。
- 同轴光源: 适合高反光物体,比如金属表面。但光强较弱,不适合大面积照明。
- 背光源: 测量轮廓、尺寸时用。叶片检测中较少用到。
3.2.2 颜色与波长
光源颜色不是随便选的。白色光虽然通用,但特定波长能增强对比度。比如,叶片表面是深色,裂纹是浅色,用蓝色光(波长450nm左右)可以增强裂纹与背景的灰度差。
3.3 图像采集与预处理:从硬件到数据的「最后一公里」
相机和光源选好了,接下来就是采集和预处理。这一步做不好,后面的算法全是空中楼阁。
3.3.1 采集参数设置
曝光时间、增益、白平衡,这三个参数要反复调。我的经验是:先固定曝光时间,再调增益,最后微调白平衡。增益不要超过6dB,否则噪声会爆炸。
# 示例:使用OpenCV设置相机参数(假设相机支持)
import cv2
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_EXPOSURE, -5) # 曝光时间,单位取决于相机驱动
cap.set(cv2.CAP_PROP_GAIN, 0) # 增益,0为最低
cap.set(cv2.CAP_PROP_WHITE_BALANCE_BLUE_U, 100) # 白平衡
3.3.2 预处理三板斧
- 去噪: 中值滤波对椒盐噪声效果好,高斯滤波对高斯噪声效果好。我习惯先用中值滤波,因为叶片表面常有灰尘颗粒。
- 增强对比度: 直方图均衡化(HE)或自适应直方图均衡化(CLAHE)。CLAHE能避免局部过曝,更适合光照不均匀的场景。
- 几何校正: 叶片表面是曲面,拍摄时会有透视畸变。用标定板做相机标定,然后做透视变换。
# 预处理示例
import cv2
import numpy as np
img = cv2.imread('blade_crack.jpg', 0)
# 1. 中值滤波去噪
img_denoised = cv2.medianBlur(img, 5)
# 2. CLAHE增强
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
img_enhanced = clahe.apply(img_denoised)
# 3. 几何校正(假设已获得变换矩阵M)
# img_corrected = cv2.warpPerspective(img_enhanced, M, (width, height))
3.4 传统图像处理算法的局限性:为什么我们还需要深度学习?
好了,前面讲了那么多传统方法。现在我要泼一盆冷水了。
边缘检测、阈值分割,这些方法在实验室里跑得挺好。但到了风电叶片现场,你会发现:根本不够用。
3.4.1 边缘检测的「脆弱」
Canny边缘检测,参数调了半天,换一个光照条件就全废了。为什么?因为边缘检测本质上是基于梯度变化。光照一变,梯度就变,阈值就得重调。
我在项目里试过,同一个叶片,上午拍和下午拍,Canny检测出来的边缘完全不一样。上午能检测到的裂纹,下午就断断续续了。
3.4.2 阈值分割的「死穴」
阈值分割假设目标和背景的灰度值有明显差异。但风电叶片表面有纹理、有污渍、有修补痕迹,灰度分布极其复杂。你设一个全局阈值,要么漏检,要么过检。
我曾经试过Otsu大津法,自动找阈值。结果呢?它把叶片表面的胶带残留当成了裂纹,把真正的裂纹给漏了。这就是传统方法的局限——缺乏语义理解。
- 光照敏感: 换一个环境光,参数就得重调。
- 缺乏鲁棒性: 对噪声、纹理、污渍等干扰非常脆弱。
- 无法理解语义: 它不知道什么是「裂纹」,只知道「灰度变化大的地方」。
3.4.3 为什么深度学习能解决?
深度学习,说白了就是让模型自己学习「什么是裂纹」。它不依赖固定的梯度阈值,而是从大量数据中学习裂纹的纹理、形状、上下文特征。光照变了?没关系,只要训练数据里包含不同光照下的裂纹,模型就能学会。
这也是为什么,从下一章开始,我们要正式进入深度学习的世界。
好了,这一章的内容就到这里。从相机选型到光源设计,从图像采集到预处理,再到传统算法的局限,我们一步步把工业视觉检测的「地基」打牢了。下一章,我们会正式进入深度学习的世界,看看卷积神经网络是如何「看懂」裂纹的。