3. 边缘检测算法

边缘检测,说白了就是找到图像里亮度变化最剧烈的地方。你想想看,我们人眼是怎么认出物体的?靠的就是轮廓。机器也一样,边缘就是它理解世界的起点。

我刚开始做视觉项目时,第一个接触的就是边缘检测。那时候觉得这玩意儿简单,不就是算个梯度嘛。后来踩的坑多了才发现——选对算子,比调参更重要。

3.1 梯度与边缘的数学直觉

先聊点基础的。图像可以看作一个二维函数 f(x, y),像素值就是函数值。边缘在哪?在函数值突变的地方。

数学上怎么描述突变?用导数。一阶导数的极大值点,或者二阶导数的过零点,都对应着边缘位置。

核心思想:边缘 = 图像函数的局部剧烈变化。一阶导找极值,二阶导找过零。

实际图像是离散的,所以我们用差分代替微分。这就是所有边缘检测算子的数学基础。

3.2 Sobel算子:简单实用的梯度估计

Sobel算子是我个人用得最多的入门级算子。它用两个 3×3 的卷积核,分别计算水平和垂直方向的梯度。

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

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

为什么中间权重大?因为离中心像素越近,贡献越大。这其实是一种加权平滑,能稍微抑制噪声。

计算完 Gx 和 Gy 后,梯度幅值用这个公式:

G = sqrt(Gx² + Gy²)

为了效率,实际项目中常用值近似:

G ≈ |Gx| + |Gy|

我的经验:在嵌入式设备上,用值近似能省掉开方运算,速度提升明显。精度损失在可接受范围内。

Sobel的特点:

  • 计算简单,速度快
  • 对噪声有一定抑制(加权平滑)
  • 只能检测水平和垂直方向,对角边缘不敏感
  • 边缘定位精度一般,容易出现双边缘

3.3 Laplacian算子:二阶导数的过零点

Laplacian 算子是二阶微分算子。它不关心梯度方向,只关心梯度变化率。数学形式是:

∇²f = ∂²f/∂x² + ∂²f/∂y²

离散形式常用的 3×3 核:

[ 0, -1,  0]
[-1,  4, -1]
[ 0, -1,  0]

或者带对角线的版本:

[-1, -1, -1]
[-1,  8, -1]
[-1, -1, -1]

注意:Laplacian 对噪声极其敏感。我曾经在一个光照不均匀的项目里直接用 Laplacian,结果边缘没找到,全是噪点。后来必须先做高斯滤波。

Laplacian的特点:

  • 各向同性,不依赖方向
  • 对孤立点、线端响应强烈
  • 对噪声极度敏感,必须预处理
  • 会产生双边缘,需要过零点检测

3.4 Canny算子:工业界的黄金标准

说实话,Canny 是我在工业项目中最常用的算子。它不是一个简单的卷积核,而是一套完整的边缘检测流程。

Canny的四个步骤:

  1. 高斯滤波:平滑图像,抑制噪声
  2. 计算梯度幅值和方向:通常用 Sobel
  3. 非极大值抑制:沿着梯度方向,只保留局部最大值
  4. 双阈值检测:高阈值确定强边缘,低阈值连接弱边缘

关键点:非极大值抑制让边缘变细,双阈值让边缘连续。这两个步骤是 Canny 的精髓。

双阈值怎么设?我一般这样调:

  • 高阈值:梯度幅值直方图的 70%-80% 分位点
  • 低阈值:高阈值的 0.4-0.5 倍
// OpenCV 示例
cv::Mat edges;
cv::Canny(src, edges, 50, 150);  // 低阈值50,高阈值150

避坑指南:我曾经在一个反光工件检测项目里,Canny 参数调了三天。后来发现是高斯滤波的核大小没选对。核太小,噪声没滤干净;核太大,边缘被模糊。建议从 5×5 开始试。

3.5 三种算子的核心对比

对比维度 Sobel Laplacian Canny
数学基础 一阶微分 二阶微分 一阶微分 + 后处理
方向性 水平/垂直 各向同性 沿梯度方向
噪声敏感度 中等 高 低(先滤波)
边缘定位 一般 较差(双边缘) 精确
边缘连续性 差 差 好(双阈值)
计算速度 快 快 较慢
适用场景 实时性要求高、边缘简单 斑点检测、零交叉 高精度、复杂场景

3.6 如何选择?我的实战建议

没有最好的算子,只有最合适的。我一般这样选:

  • 实时性优先(比如 60fps 的产线):用 Sobel,配合简单的阈值
  • 精度优先(比如 PCB 缺陷检测):用 Canny,花时间调参
  • 需要检测孤立点或线端(比如晶圆划痕):用 Laplacian,但一定要先滤波

重要提醒:不管用哪种算子,预处理都别省。光照不均先做直方图均衡,噪声大先做高斯或中值滤波。我见过太多人直接拿原图跑边缘检测,结果一塌糊涂。

3.7 本章知识结构图

下面这张图总结了三种算子的核心逻辑和适用场景:

边缘检测算法对比框架 输入图像 Sobel 算子 Laplacian 算子 Canny 算子 Sobel 特性 一阶微分,方向敏感 速度快,噪声抑制中等 适合实时性要求高的场景 Laplacian 特性 二阶微分,各向同性 对噪声极度敏感 适合斑点/线端检测 Canny 特性 多阶段流程 非极大值抑制 + 双阈值 精度高,适合复杂场景 选择依据:实时性 vs 精度 vs 噪声环境

3.8 小结

三种算子各有各的脾气。Sobel 像一把快刀,简单直接;Laplacian 像一把手术刀,精准但娇气;Canny 像一套完整的工具箱,功能强大但需要耐心调校。

我个人建议初学者从 Canny 入手,理解边缘检测的完整流程。等用熟了,再根据实际场景去选 Sobel 或 Laplacian。记住一点:没有银弹,只有最合适的工具。