图像边缘检测01:几种常用的算法与对应函数
在一切开始之前,请允许我先隆重介绍一下在这篇文章里面用来做实验的图片,它也是我博客主页的封面:
“暮色漫染新加坡的天际线,金融区的钢铁丛林在余晖里苏醒。玻璃幕墙裁碎夕阳,将金芒洒向睡莲摇曳的镜面。建筑如未来棱晶,莲花池接住整座城的倒影 —— 这是钢铁与柔波的和鸣,都市脉搏在水面轻颤,每片莲叶都托着金融中心的璀璨,每缕暮光都织就花园城市的浪漫,滨海湾把 “硬核” 与 “诗意”,熬成一帧流动的、属于狮城的梦。”
Sobel算法:基于一阶导数的边缘检测
(一)算法背景
图像中的边缘通常对应着像素亮度的显著变化。Sobel算法是一种经典且高效的边缘检测方法,通过计算图像在水平和垂直方向上的梯度(一阶导数)来定位边缘。
(二)算法原理
Sobel算法的核心是使用两个特定的3x3卷积核,分别计算图像在水平(x)和垂直(y)方向上的近似梯度:
- 水平方向卷积核 (检测垂直边缘):
[
G_x =
\begin{bmatrix}
-1 & 0 & 1 \
-2 & 0 & 2 \
-1 & 0 & 1 \
\end{bmatrix}
] - 垂直方向卷积核 (检测水平边缘):
[
G_y =
\begin{bmatrix}
-1 & -2 & -1 \
0 & 0 & 0 \
1 & 2 & 1 \
\end{bmatrix}
]
对图像中的每个像素,将其邻域像素值分别与这两个核进行卷积运算,得到梯度分量 (G_x) 和 (G_y)。
(三)边缘强度与方向
- 边缘强度 (梯度幅值):综合两个方向的梯度计算每个像素点的边缘强度:
[
G = \sqrt{G_x^2 + G_y^2}
]
为简化计算,实践中常用近似公式:
[
G \approx |G_x| + |G_y|
]
值 (G) 越大,该点属于边缘的可能性越高。 - 边缘方向:梯度方向指示了边缘的法线方向(垂直于边缘走向):
[
\theta = \arctan\left(\frac{G_y}{G_x}\right)
]
(\theta) 的范围通常在 (-90^\circ) 到 (90^\circ) 之间。
Sobel函数:OpenCV实现
OpenCV提供了 cv2.Sobel() 函数方便地实现Sobel边缘检测。
(一)函数原型
cv2.Sobel(src, ddepth, dx, dy, dst=None, ksize=None, scale=None, delta=None, borderType=None) |
src: 输入图像(通常为灰度图)。ddepth: 输出图像的深度(常用cv2.CV_64F或cv2.CV_8U)。dx: x方向(水平)导数的阶数(通常设为1)。dy: y方向(垂直)导数的阶数(通常设为1)。dst: 输出图像(可选)。ksize: Sobel核大小(常用3)。scale: 缩放导数值(可选)。delta: 导数值偏移量(可选)。borderType: 边界填充方式(默认为cv2.BORDER_DEFAULT)。
(二)使用示例
# Scharr() |
(三)特点
- 优点:实现简单、计算效率高,能有效检测水平和垂直边缘。
- 缺点:梯度计算是近似值,精度相对较低;对噪声有一定敏感性;只能检测特定方向的边缘。
Scharr算法:Sobel的优化版本
(一)算法背景
Sobel算法在检测非水平和垂直方向边缘时精度有所下降。Scharr算法通过优化卷积核设计,提供了更高的旋转对称性和梯度计算精度。
(二)算法原理
Scharr算法结构与Sobel相同,但使用了不同的卷积核系数,能更精确地近似图像梯度:
- 水平方向卷积核:
[
G_x =
\begin{bmatrix}
-3 & 0 & 3 \
-10 & 0 & 10 \
-3 & 0 & 3 \
\end{bmatrix}
] - 垂直方向卷积核:
[
G_y =
\begin{bmatrix}
-3 & -10 & -3 \
0 & 0 & 0 \
3 & 10 & 3 \
\end{bmatrix}
]
边缘强度 ((G = \sqrt{G_x^2 + G_y^2}) 或 (G \approx |G_x| + |G_y|)) 和方向 ((\theta = \arctan(G_y / G_x))) 的计算方式与Sobel一致。
(三)算法优势
相比Sobel算子,Scharr算子在相同大小的核(3x3)下:
- 精度更高:对边缘方向的响应更准确。
- 旋转对称性更好:检测不同角度边缘的性能更均衡。
- 抗噪性略优:系数设计有助于在保持精度的同时略微抑制噪声影响。
Scharr函数:OpenCV实现
OpenCV提供了专门的 cv2.Scharr() 函数。
(一)函数原型
cv2.Scharr(src, ddepth, dx, dy, dst=None, scale=None, delta=None, borderType=None) |
参数含义与 cv2.Sobel() 类似(dx 和 dy 通常也为1):
src,ddepth,dx,dy,dst,scale,delta,borderType.- 注意:Scharr函数没有
ksize参数,因为它固定使用优化的3x3核。
(二)使用示例
# Laplacian() |
(三)特点
- 优点:在3x3核下精度显著优于Sobel;计算效率与Sobel相当;API简单易用。
- 缺点:同样对噪声敏感;核大小固定为3x3,灵活性不如可调ksize的Sobel;本质上仍是基于一阶导数的近似。
Laplacian算法:基于二阶导数的边缘检测
(一)算法背景
Sobel和Scharr基于一阶导数(梯度变化率),而Laplacian算法基于二阶导数(梯度变化率的变化率)。它在图像灰度值发生突变(如边缘)的位置会产生零交叉或极值响应。
(二)算法原理
Laplacian算法直接计算图像的拉普拉斯算子(Laplacian Operator),即二阶导数的和:
[
\Delta f = \frac{\partial^2 f}{\partial x^2} + \frac{\partial^2 f}{\partial y^2}
]
离散图像中通过卷积核实现。常用核有:
- 4邻域 (更常用):
[
\begin{bmatrix}
0 & 1 & 0 \
1 & -4 & 1 \
0 & 1 & 0 \
\end{bmatrix}
] - 8邻域 (对对角线边缘响应更强):
[
\begin{bmatrix}
1 & 1 & 1 \
1 & -8 & 1 \
1 & 1 & 1 \
\end{bmatrix}
]
(三)边缘检测
- 计算拉普拉斯响应:用上述核之一对图像进行卷积,得到每个像素的拉普拉斯值 (L)。
- 边缘定位:
- 理论边缘点位于 (L=0) 的位置(零交叉点)。
- 实践中常通过寻找 (L) 的绝对值较大(超过阈值)的点来检测边缘,或者结合零交叉检测方法。
(四)算法特点
- 优点:对图像中的灰度突变(如细线、孤立点、边缘)非常敏感;能检测任意方向的边缘(各向同性);无需分别计算x/y方向。
- 缺点:对噪声极其敏感(二阶导数放大噪声);容易产生双像素宽边缘;检测到的边缘位置可能不如一阶方法精确。
Laplacian函数:OpenCV实现
OpenCV提供了 cv2.Laplacian() 函数。
(一)函数原型
cv2.Laplacian(src, ddepth, dst=None, ksize=None, scale=None, delta=None, borderType=None) |
src: 输入图像(通常为灰度图)。ddepth: 输出图像的深度(常用cv2.CV_64F)。dst: 输出图像(可选)。ksize: 计算二阶导数使用的孔径大小(核大小)。关键参数:ksize=1表示使用上述4邻域核。常用ksize=3(默认) 或ksize=5(更平滑)。ksize=1时实际使用ksize=3的4邻域核。scale: 缩放计算得到的拉普拉斯值(可选)。delta: 偏移量(可选)。borderType: 边界填充方式(默认为cv2.BORDER_DEFAULT)。
(二)使用示例
# Laplacian() |
(三)特点
- 优点:API简洁;能检测各方向边缘;对突变敏感。
- 缺点:结果对噪声非常敏感;需要仔细选择
ksize和后续阈值处理;输出通常需要取绝对值并转换为8位图像显示。
Sobel, Scharr, Laplacian 算法对比
下表总结了三种边缘检测算法的主要特点与差异:
| 特性 | Sobel 算法 | Scharr 算法 | Laplacian 算法 |
|---|---|---|---|
| 计算基础 | 一阶导数 (近似梯度) | 一阶导数 (优化近似梯度) | 二阶导数 (拉普拉斯算子) |
| 主要目的 | 检测边缘 (梯度幅值大的地方) | 检测边缘 (梯度幅值大的地方) | 检测灰度突变 (零交叉/极值点) |
| 方向性 | 能计算边缘方向 (θ) | 能计算边缘方向 (θ) | 各向同性 (无特定方向) |
| 精度 (3x3核) | 中等 | 高 (优于Sobel) | 高 (对突变敏感) |
| 抗噪性 | 低 | 低 (略优于Sobel) | 非常低 (噪声放大严重) |
| 边缘响应 | 单边缘响应 (单峰) | 单边缘响应 (单峰) | 双边缘响应 (零交叉) |
| 检测边缘类型 | 主要水平和垂直方向 | 各方向 (精度更均衡) | 所有方向 |
| 对细线/点响应 | 弱 | 弱 | 强 |
| 计算复杂度 | 低 | 低 (与Sobel相当) | 低 |
| OpenCV函数 | cv2.Sobel() |
cv2.Scharr() |
cv2.Laplacian() |
| 主要参数 | dx, dy, ksize |
dx, dy (核固定3x3) |
ksize (控制平滑与核类型) |
| 典型应用场景 | 快速初步边缘检测 | 需要更高精度的3x3核边缘检测 | 检测细线、孤立点、斑点、边缘增强 |
选择建议:
- 需要快速检测基本边缘且方向明确? ->
Sobel(可调ksize增加平滑)。 - 需要更精确的3x3核边缘检测? ->
Scharr。 - 需要检测所有方向的突变、细线或孤立点? ->
Laplacian(但务必结合平滑滤波如高斯模糊,即LoG)。 - 实际应用中,常将Sobel/Scharr的结果(梯度幅值)与Laplacian的零交叉信息结合,或使用更高级算法(如Canny)。
至于更高级的 Canny 算法 ,我们将在下一篇单独成文介绍。




