一句话定义
边缘是图像亮度发生剧烈变化的位置,边缘检测用梯度算子定位这些位置,Canny 算法再通过非极大值抑制与双阈值滞后把梯度图变成干净的细边缘。
为什么重要
边缘是物体轮廓、纹理边界与深度突变在图像上最直接的投影;它既是传统视觉(角点检测、霍夫变换、分割)的输入,也是理解「深度网络到底在低层学到什么」的参照系——CNN 第一层卷积核可视化出来就是各种方向的边缘滤波器。
直观类比
沿着一条道路走(扫描图像),亮度像台阶一样突然跳变的位置就是边缘;Sobel 负责发现「这里有个台阶、朝哪个方向」,Canny 负责把同一级台阶重复报警的邻居只留一个,再用两道门槛判断这级台阶值不值得记下来。
前置知识
kp-002(卷积与核)。
核心概念
- 梯度(Gradient):亮度在 x、y 方向的变化率向量,指向增长最快的方向;边缘法向与梯度方向一致。
- Sobel 算子:一对 3×3 核,分别估计水平与垂直梯度,内置了轻微平滑。
- 梯度幅值与方向:幅值衡量「有多像边缘」,方向说明边缘朝向。
- 非极大值抑制(一维版):沿梯度方向只保留局部幅值最大的点,把粗边缘变细。
- 双阈值滞后(Hysteresis):高阈值确认强边缘,低阈值连接弱边缘,避免断裂。
- Canny 四步:高斯平滑 → 计算梯度 → 非极大值抑制 → 双阈值滞后连接。
原理与机制
梯度由两个方向的差分核卷积得到;理想阶跃边缘的导数是冲激,因此「找导数极大值」等价于「找边缘」。直接差分对噪声敏感,Canny 在推导中把「好检测、好定位、单响应」三个准则形式化为一个最优化问题,结论是先用高斯平滑再求导,近似等价于高斯一阶导数算子。非极大值抑制把每个像素的梯度方向量化到 0/45/90/135 度四个扇区,只在同方向邻域内比较幅值;双阈值后从强边缘点出发、沿 8 邻域把相连的弱边缘点并入。
公式与模型
Gx = Sobel_x * I Gy = Sobel_y * I
M(x, y) = √(Gx² + Gy²) θ(x, y) = atan2(Gy, Gx)Sobel_x 核:[[-1, 0, +1], [-2, 0, +2], [-1, 0, +1]];Sobel_y 为其转置。幅值 M 越大越像边缘,方向 θ 垂直于边缘走向。
图示
实例与案例
工业零件尺寸测量:打光后零件与背景形成强边缘,Canny 边缘 + 轮廓拟合即可亚像素级测宽。文档扫描 App 的自动裁边同样是 Canny 找到纸张四条直线边后求交点。深度学习时代边缘检测(如 HED 网络)在多尺度上学习边缘概率图,但 Canny 仍是零成本、可解释的基线。
import cv2
blur = cv2.GaussianBlur(gray, (3, 3), 0)
edges = cv2.Canny(blur, threshold1=60, threshold2=150) # 低/高阈值约 1:2 到 1:3常见误区
- 把 Canny 结果当物体轮廓:边缘只保证亮度突变,纹理、阴影、反光都会出边,轮廓级理解需要后续语义。
- 阈值拍脑袋:高阈值应设在强边缘幅值的高分位(如 90 分位),低阈值约为其一半;不同光照下需重标。
- 跳过平滑直接 Canny:噪声会形成大量碎边,反而更难清理。
- 以为输出是二值轮廓图就完事:Canny 只给边缘像素,物体级别的封闭轮廓要靠轮廓跟踪或分割算法。
与其他知识点的关系
边缘梯度是 kp-006 Harris 角点的原材料(角点 = 两方向梯度都大);kp-022 光流方程里的 Ix、Iy 同样来自梯度估计。
自测题
- Canny 中低阈值过高或过低分别会怎样?
答案要点:过高则边缘断裂;过低则把噪声弱边缘接进来,边缘变毛。
- 为什么 Sobel 核比简单差分更常用?
答案要点:它内置中心行/列加权,相当于先做一次平滑再差分,抗噪更好。
- 非极大值抑制沿什么方向比较?
答案要点:沿梯度方向(垂直于边缘走向),保留幅值局部最大的点以获得单像素宽边缘。
延伸阅读
- Canny 1986《A Computational Approach to Edge Detection》
- kp-006 看梯度如何进一步定位角点