第4章 经典边缘检测算子(上)

Roberts算子 · Prewitt算子 · Laplacian算子 — 原理与代码实现

边缘是图像中灰度发生剧烈变化的位置,经典的微分算子通过卷积核近似梯度。本章深入讲解三种基础算子的数学原理、特性与 Python 实现,为后续 Canny 等高级算子打下根基。

算子类型核大小方向敏感性对噪声
Roberts一阶差分2×2对角敏感
Prewitt一阶导数3×3水平/垂直有一定抑制
Laplacian二阶导数3×3各向同性非常敏感

1. Roberts 交叉梯度算子

Roberts 算子利用局部差分寻找边缘,采用 2×2 对角差分:

核定义:
Gx = [[1, 0], [0, -1]]    Gy = [[0, 1], [-1, 0]]

梯度幅值近似为 |Gx| + |Gy|。优点是计算极快,但对噪声敏感。

1 0 0 -1 Gx (对角差分) 0 1 -1 0 Gy (对角差分)
import cv2
import numpy as np

def roberts_edge(image):
    # 2x2 核
    kernel_x = np.array([[1, 0], [0, -1]], dtype=np.float32)
    kernel_y = np.array([[0, 1], [-1, 0]], dtype=np.float32)
    grad_x = cv2.filter2D(image, cv2.CV_32F, kernel_x)
    grad_y = cv2.filter2D(image, cv2.CV_32F, kernel_y)
    edge = cv2.magnitude(grad_x, grad_y)
    return cv2.convertScaleAbs(edge)

2. Prewitt 算子

Prewitt 使用 3×3 核,在中心行/列赋予更高权重,平滑噪声的同时计算梯度:

水平核 Gx: [[-1, 0, 1], [-1, 0, 1], [-1, 0, 1]]
垂直核 Gy: [[-1, -1, -1], [0, 0, 0], [1, 1, 1]]

相比 Roberts,Prewitt 对噪声有更好的鲁棒性,且能分别提取水平与垂直边缘。

-101 -101 -101 Gx (水平) -1-1-1 000 111 Gy (垂直)
def prewitt_edge(image):
    kernel_x = np.array([[-1, 0, 1],
                         [-1, 0, 1],
                         [-1, 0, 1]], dtype=np.float32)
    kernel_y = np.array([[-1, -1, -1],
                         [ 0,  0,  0],
                         [ 1,  1,  1]], dtype=np.float32)
    grad_x = cv2.filter2D(image, cv2.CV_32F, kernel_x)
    grad_y = cv2.filter2D(image, cv2.CV_32F, kernel_y)
    edge = cv2.magnitude(grad_x, grad_y)
    return cv2.convertScaleAbs(edge)

3. Laplacian 算子

Laplacian 是二阶微分算子,各向同性,对边缘产生零交叉。常用 3×3 核:

标准核: [[0, 1, 0], [1, -4, 1], [0, 1, 0]]   或带对角扩展 [[1,1,1],[1,-8,1],[1,1,1]]

由于二阶导数对噪声极度敏感,通常先做高斯平滑再应用 Laplacian (LoG)。

010 1-41 010 Laplacian 核
def laplacian_edge(image):
    # 使用 OpenCV 内置 Laplacian
    lap = cv2.Laplacian(image, cv2.CV_32F, ksize=3)
    edge = cv2.convertScaleAbs(lap)
    return edge

# 或者自定义核
def laplacian_custom(image):
    kernel = np.array([[0, 1, 0],
                       [1, -4, 1],
                       [0, 1, 0]], dtype=np.float32)
    lap = cv2.filter2D(image, cv2.CV_32F, kernel)
    return cv2.convertScaleAbs(lap)

算子对比示意图

Roberts 2×2 对角差分 · 最快 Prewitt 3×3 水平/垂直 · 抗噪 Laplacian 3×3 二阶导 · 各向同性 复杂度  →  增加 对噪声敏感度  →  增加