第四章 图像特征提取:从像素到几何的跃迁

各位同学,欢迎来到机器视觉最核心的一环——特征提取。

说白了,图像处理的前面几步(滤波、增强)都是在“洗数据”。真正让机器看懂世界的,是特征提取。我个人习惯把这一步称为“从像素到语义的桥梁”。你想想看,一张200万像素的图,直接扔给控制器,它根本不知道哪里是边缘、哪里是角点。特征提取,就是帮它提炼出关键信息。

4.1 边缘检测:找到物体的“骨架”

边缘是什么?是图像中灰度剧烈变化的地方。我刚开始做视觉时,以为边缘检测就是“找黑白交界”,后来踩了坑才明白——噪声、光照不均、纹理干扰,都会让边缘变成一团乱麻。

4.1.1 Sobel算子:简单但够用

Sobel算子是最基础的边缘检测方法。它用两个3x3的卷积核,分别计算水平方向和垂直方向的梯度。

// 水平方向Sobel核
[-1, 0, 1]
[-2, 0, 2]
[-1, 0, 1]

// 垂直方向Sobel核
[-1, -2, -1]
[ 0,  0,  0]
[ 1,  2,  1]

嗯,这里要注意:Sobel对噪声比较敏感。我在项目中遇到过,如果光源有轻微频闪,Sobel会检测出大量伪边缘。我的建议是——先用高斯滤波平滑一下,再做Sobel。

4.1.2 Canny边缘检测:工业界的标配

Canny算法是我用得最多的边缘检测方法。它比Sobel聪明得多,核心步骤是:

  1. 高斯滤波去噪
  2. 计算梯度幅值和方向
  3. 非极大值抑制(只保留局部梯度最大的点)
  4. 双阈值检测(高阈值确定强边缘,低阈值连接弱边缘)

关键参数:高阈值和低阈值的比例,我一般设为2:1到3:1。比如高阈值100,低阈值50。如果边缘断断续续,说明低阈值设高了;如果伪边缘太多,说明高阈值设低了。

我曾经在一个锂电池极片检测项目中,Canny参数调了整整两天。后来发现,问题不在算法,而在光源——换了同轴光源后,边缘一下就清晰了。所以,别只盯着代码,硬件环境同样重要。

4.2 角点检测:找到图像的“特征点”

角点,说白了就是两条边缘的交点。它在图像匹配、目标跟踪中非常有用。

4.2.1 Harris角点检测

Harris算法的核心思想:用一个窗口在图像上滑动,如果窗口内灰度变化很大,说明这里有角点。

数学上,它计算一个矩阵M的特征值。如果两个特征值都很大,就是角点;一个很大一个很小,是边缘;两个都很小,是平坦区域。

我的经验:Harris对尺度变化比较敏感。如果你要检测的物体大小变化很大,建议用多尺度Harris或者直接上SIFT。

4.2.2 Shi-Tomasi角点检测:Harris的改良版

Shi-Tomasi是Harris的升级版。它直接取M矩阵的最小特征值作为角点响应。说白了,它比Harris更“挑剔”——只保留那些真正稳定的角点。

// OpenCV中的Shi-Tomasi用法
cv::goodFeaturesToTrack(
    src,        // 输入图像
    corners,    // 输出的角点坐标
    maxCorners, // 最多检测多少个角点
    qualityLevel, // 质量等级(0.01-0.1)
    minDistance   // 角点之间的最小距离
);

我记得有一次做PCB板定位,用Harris检测出了200多个角点,但大部分是焊盘的虚假角点。换成Shi-Tomasi后,只保留最稳定的4个角点,定位精度反而更高了。有时候,少即是多。

4.3 轮廓提取与拟合:从边缘到形状

边缘检测得到的是像素点,轮廓提取则是把这些点连成有意义的形状。

4.3.1 轮廓提取

OpenCV里用findContours函数。这里有个坑——输入图像必须是二值图。我建议用Canny处理后的结果作为输入。

std::vector<std::vector<cv::Point>> contours;
cv::findContours(
    binary_img,   // 二值图
    contours,     // 输出的轮廓
    RETR_EXTERNAL, // 只提取最外层轮廓
    CHAIN_APPROX_SIMPLE // 压缩轮廓点
);

避坑指南:我曾经在提取轮廓时,忘记检查轮廓的面积。结果把噪声点也当成了轮廓,导致后续拟合全部出错。记住:先过滤面积太小的轮廓,再处理。

4.3.2 轮廓拟合

拟合就是把离散的轮廓点,拟合成规则的几何形状。常用的有:

  • 直线拟合:用最小二乘法,适合检测边缘直线
  • 圆拟合:用RANSAC算法,抗噪声能力强
  • 椭圆拟合:适合检测圆形物体的透视变形

我个人习惯用RANSAC做圆拟合。为什么?因为它能自动剔除离群点。我在检测轴承内径时,即使有10%的轮廓点被划痕干扰,RANSAC依然能准确拟合出圆。

4.4 Blob分析:连通域与几何特征

Blob分析,说白了就是“找团块”。它把图像中连通的像素区域找出来,然后计算每个区域的几何特征。

4.4.1 连通域标记

连通域标记有两种方式:4邻域和8邻域。工业上我基本只用8邻域,因为它对斜向连接更敏感。

cv::Mat labels, stats, centroids;
int num_blobs = cv::connectedComponentsWithStats(
    binary_img, 
    labels, 
    stats, 
    centroids,
    8  // 8邻域
);

4.4.2 几何特征计算

标记完连通域后,我们可以计算每个Blob的:

特征含义应用场景
面积像素点个数过滤噪声、筛选目标
周长边界像素长度判断形状复杂度
质心几何中心坐标定位、跟踪
外接矩形最小包围矩形粗略定位、尺寸测量
圆形度4π×面积/周长²判断是否接近圆形
长宽比外接矩形的长/宽区分细长和扁平物体

实战技巧:我在检测药片时,先用面积过滤掉粉尘(面积小于50像素的不要),再用圆形度判断药片是否破损(圆形度小于0.8的剔除)。两步下来,误检率从5%降到了0.3%。

知识体系总览

下面这张图,是我自己总结的特征提取知识体系。你可以把它当作一个“导航图”,遇到具体问题时,先定位到对应模块。

图像特征提取知识体系 特征提取 边缘检测 角点检测 轮廓提取与拟合 Blob分析 Sobel Canny Harris Shi-Tomasi 轮廓提取 轮廓拟合 连通域标记 几何特征 每个模块都对应一套成熟的算法和参数调优经验 典型应用场景 • 边缘检测:尺寸测量、缺陷检测、定位 • 角点检测:图像匹配、相机标定、目标跟踪 • 轮廓拟合:圆形/矩形检测、物体识别 • Blob分析:颗粒计数、面积测量、缺陷分类 实际项目中,往往需要组合使用多种特征提取方法

好了,特征提取这部分内容比较多,但都是硬核干货。你可能会问:这么多方法,到底该用哪个?我的建议是——先明确你的目标:是要定位?测量?还是识别?然后从最简单的算法开始试,不行再升级。别一上来就上深度学习,很多时候Sobel+Canny就够用了。


专注资料整理