775 字
4 分钟
[计算机视觉] 边缘检测

非极大值抑制#

因为后续的边缘检测算子计算结果均是梯度幅值图,若要得到最终的边缘图,需要对梯度幅值图进行非极大值抑制

非极大值抑制的核心思想是:对于每个像素点,比较其梯度幅值与其在梯度方向上的两个邻居的梯度幅值,如果该像素点的梯度幅值不是最大的,则将其设为0

目的就是找出局部最大值,保留边缘的细节,同时抑制非边缘的噪声

Sobel算子#

Sobel算子通过计算图像在水平和垂直方向上的梯度来检测边缘

垂直方向卷积核:

Gx=[101202101]G_x = \begin{bmatrix}-1 & 0 & 1 \\ -2 & 0 & 2 \\ -1 & 0 & 1\end{bmatrix}

水平方向卷积核:

Gy=[121000121]G_y = \begin{bmatrix}1 & 2 & 1 \\ 0 & 0 & 0 \\ -1 & -2 & -1\end{bmatrix}

图像任意一点的总梯度强度(梯度幅值):

G=Gx2+Gy2G = \sqrt{G_x^2 + G_y^2}

绝对值近似GGx+GyG \approx |G_x| + |G_y|,计算更快

Prewitt算子#

Prewitt算子与Sobel算子类似,也是通过计算图像在水平和垂直方向上的梯度来检测边缘,但Prewitt不考虑更近的像素的权重,权重均为1

垂直方向卷积核:

Gx=[101101101]G_x = \begin{bmatrix}-1 & 0 & 1 \\ -1 & 0 & 1 \\ -1 & 0 & 1\end{bmatrix}

水平方向卷积核:

Gy=[111000111]G_y = \begin{bmatrix}1 & 1 & 1 \\ 0 & 0 & 0 \\ -1 & -1 & -1\end{bmatrix}

后续和Sobel算子一样

Laplacian算子#

Laplacian算子通过计算图像的二阶导数来检测边缘,能够检测到图像中灰度值变化较大的区域

Kernel=[010141010]\text{Kernel} = \begin{bmatrix}0 & 1 & 0 \\ 1 & -4 & 1 \\ 0 & 1 & 0\end{bmatrix}

计算的是中心像素与其四个邻居像素的灰度值之差的总和,因此对变化非常敏感,能检测出非常细的边缘,但导致对噪声也非常敏感

Canny算子#

Canny算子是一种多阶段的边缘检测算法,包含以下步骤:

  1. 使用高斯滤波器对图像进行平滑,减少噪声的影响
  2. 计算图像的梯度幅值和方向,使用Sobel算子Prewitt算子
  3. 进行非极大值抑制,保留局部最大值,抑制非边缘的噪声
  4. 使用双阈值算法连接边缘,确定哪些边缘是强边缘,哪些是弱边缘,并连接强边缘和弱边缘
  5. 滞后边界追踪,连接强边缘和弱边缘,形成完整的边缘图

双阈值算法#

边缘分为强边缘和弱边缘

强边缘={(x,y)G(x,y)Thigh}弱(潜在)边缘={(x,y)TlowG(x,y)<Thigh}丢弃={(x,y)G(x,y)<Tlow}\text{强边缘} = \{(x, y) | G(x, y) \geq T_{\text{high}}\} \\[1em] \text{弱(潜在)边缘} = \{(x, y) | T_{\text{low}} \leq G(x, y) < T_{\text{high}}\} \\[1em] \text{丢弃} = \{(x, y) | G(x, y) < T_{\text{low}}\}

滞后边界追踪#

对于每个强边缘像素,检查其8邻域,如果邻域内有弱边缘像素,则将该弱边缘像素也标记为强边缘,继续检查该弱边缘像素的8邻域,直到没有更多的弱边缘像素被连接为止

[计算机视觉] 边缘检测
https://a1kari8.github.io/posts/cv/edge_detect/
作者
A1kari8
发布于
2026-05-30
许可协议
CC BY-NC-SA 4.0