4. 特征提取与分类
好,我们进入第四章。前面几章我们讲了怎么把图像处理好,把缺陷区域分割出来。但分割出来的区域只是一堆像素点,怎么让机器知道它到底是划痕、脏污还是气泡?这就靠特征提取和分类了。
说白了,特征提取就是把图像信息转化成数字,分类器根据这些数字做判断。我刚开始做视觉项目时,总觉得这步是纯数学,后来发现,选对特征比调分类器参数重要得多。
4.1 Blob分析:先搞清楚区域是什么
Blob分析,其实就是对分割后的连通区域做基础测量。每个连通区域就是一个Blob,我们要知道它的大小、形状、位置。
我个人习惯把Blob分析分成三步:
- 连通域标记:给每个独立区域编号
- 基础属性提取:面积、质心、外接矩形
- 筛选过滤:去掉太小或太大的噪声区域
4.2 几何特征:形状就是信息
几何特征是最直观、最稳定的特征。你想想看,划痕通常是细长的,气泡是圆形的,脏污是不规则形状。这些形状差异,用几个数值就能区分。
| 特征名称 | 计算公式 | 典型应用场景 |
|---|---|---|
| 面积 | 区域内像素总数 | 区分大缺陷与小噪声 |
| 周长 | 区域边界像素数 | 判断缺陷边缘复杂度 |
| 圆度 | 4π×面积 / 周长² | 区分圆形气泡与不规则划痕 |
| 长宽比 | 外接矩形长边/短边 | 识别细长裂纹 |
| 矩形度 | 面积 / 外接矩形面积 | 判断缺陷是否接近矩形 |
这里我要特别说一下圆度。圆度值越接近1,说明区域越圆。我曾经在检测锂电池极片时,就用圆度区分了电解液气泡(圆度>0.85)和极片划痕(圆度<0.5),准确率直接到了98%。
4.3 纹理特征:看表面,不只是看轮廓
有些缺陷形状差不多,但表面纹理不同。比如布料上的油污和磨损,形状可能都是不规则的,但油污区域纹理更均匀,磨损区域纹理更粗糙。这时候就需要纹理特征了。
4.3.1 LBP(局部二值模式)
LBP的原理很简单:比较中心像素和周围像素的大小关系。比中心大记1,比中心小记0,然后组成一个二进制数。这个数就代表了局部纹理模式。
我记得有个项目检测木材表面缺陷,用LBP直方图做特征,配合SVM分类器,对活节、死节、虫眼的分类准确率达到了95%以上。LBP对光照变化不敏感,这是它最大的优势。
// LBP特征提取核心步骤(伪代码)
for each pixel in image:
center = pixel value
binary_pattern = 0
for i in 0 to 7:
neighbor = get_neighbor(pixel, radius, i)
if neighbor >= center:
set_bit(binary_pattern, i)
lbp_image[pixel] = binary_pattern
// 统计直方图作为特征向量
histogram = compute_histogram(lbp_image, bins=256)
4.3.2 GLCM(灰度共生矩阵)
GLCM统计的是图像中特定灰度对出现的频率。它能反映纹理的粗糙度、对比度、方向性等特性。
常用的GLCM特征有:
- 对比度:纹理的清晰程度,值越大纹理越深
- 相关性:纹理的方向性,值越大方向性越强
- 能量:纹理的均匀程度,值越大纹理越规则
- 同质性:纹理的局部变化程度
4.4 基于传统机器学习的分类器
特征提取完了,接下来就是分类。传统机器学习分类器在工业场景中依然很能打,尤其是样本量不大的时候。
4.4.1 SVM(支持向量机)
SVM的核心思想是找一个超平面,把不同类别的样本分开,并且让这个超平面离最近的样本点尽可能远。
为什么SVM在工业视觉中这么受欢迎?
- 小样本学习能力强:几十个样本就能训练出可用的模型
- 泛化能力好:不容易过拟合
- 核函数灵活:线性不可分时,用RBF核映射到高维空间
我曾经用SVM做手机屏幕划痕检测,只用了200个正样本和200个负样本,RBF核+SVM,测试准确率就达到了99.2%。
// SVM训练示例(Python风格伪代码)
from sklearn import svm
// 特征矩阵:每行是一个样本的特征向量
X_train = [[area, roundness, lbp_hist[0], ...], ...]
y_train = [0, 1, 0, 1, ...] // 0:良品, 1:缺陷
// 创建SVM分类器(RBF核)
clf = svm.SVC(kernel='rbf', C=1.0, gamma='scale')
// 训练
clf.fit(X_train, y_train)
// 预测
result = clf.predict(X_test)
4.4.2 KNN(K近邻)
KNN更简单:新样本来了,找它最近的K个邻居,看这些邻居中哪类最多,新样本就属于哪类。
KNN的优点和缺点都很明显:
| 对比项 | SVM | KNN |
|---|---|---|
| 训练速度 | 中等(需要求解优化问题) | 极快(只需存储样本) |
| 预测速度 | 快 | 慢(需要计算所有距离) |
| 样本量要求 | 小样本即可 | 需要较多样本覆盖空间 |
| 对特征尺度敏感 | 是(需要归一化) | 是(必须归一化) |
| 可解释性 | 中等(支持向量可解释) | 好(直接看邻居) |
4.5 特征选择:别把所有特征都扔进去
特征不是越多越好。冗余特征会降低分类器性能,还会增加计算时间。
我常用的特征选择方法:
- 方差过滤:去掉方差接近0的特征(所有样本都一样,没区分度)
- 相关性分析:去掉高度相关的特征(比如面积和周长通常强相关,留一个就行)
- 递归特征消除:用模型训练,每次去掉最不重要的特征
4.6 实战要点总结
好了,这一章的内容就这些。最后我整理几个关键点,你在实际项目中可以对照着用:
- 先几何,后纹理:能用形状区分的,就别上纹理,计算量小很多
- 特征归一化是必须的:所有特征统一到[0,1]或[-1,1]区间
- SVM优先,KNN备选:样本少用SVM,样本多且需要快速迭代用KNN
- 验证集不能省:至少留20%的数据做验证,别在训练集上自嗨
特征提取和分类是视觉检测的决策核心。选对特征,用对分类器,你的检测系统才能真正从「看到」变成「看懂」。