跳轉到

4.1 梯度與Sobel運算子#

概念說明#

影像 I(x, y) 的梯度 (gradient) 是一階偏微分向量:

∇I = (∂I/∂x, ∂I/∂y)

∂I/∂x 大表示水平方向亮度變化劇烈(垂直邊緣),∂I/∂y 大表示垂直方向變化劇烈(水平邊緣)。兩個純量組合出兩個有用物理量:

  • 梯度大小 (magnitude):|∇I| = √(gx² + gy²),數值越大邊緣越強。
  • 梯度方向 (orientation):θ = atan2(gy, gx),是亮度增加最快的方向;邊緣本身與之垂直。

數位影像上用小核心近似微分。最簡單是一階差分 [−1, 1],但對雜訊極敏感且無對稱性。Sobel 運算子 (1968) 把差分與平滑合成一個 3×3 核心——中央列/行權重加倍,等價於「先做 3 像素平均平滑、再做中央差分」:

Gx = [[−1, 0, 1], [−2, 0, 2], [−1, 0, 1]]  Gy = [[−1, −2, −1], [0, 0, 0], [1, 2, 1]]

注意兩核心都是可分離的:Gx = [1,2,1]ᵀ · [−1,0,1],因此計算很快。Sobel 的優點:(1) 內建平滑,抗雜訊優於純差分;(2) 對稱的權重使方向估計較穩定。

與 Sobel 同期的還有 Prewitt(中央權重為 1)與 Scharr(權重 [3, 10, 3],對小 σ 旋轉不變性更佳)。實務上 3×3 Sobel 是預設選擇;需要更高精度方向時用 Scharr 或更大核心。

門檻化:算出梯度大小後,以門檻 T 分類——|∇I| ≥ T 判為邊緣。T 的選擇是雜訊與漏檢的折衷,這個問題在下一節由 Canny 的雙門檻機制更優雅地解決。

演算法步驟#

  1. (建議)先做輕度高斯平滑抑制雜訊。
  2. 用 Gx 對影像做卷積得 gx,用 Gy 得 gy。
  3. 計算大小 M = √(gx² + gy²),方向 θ = atan2(gy, gx)。
  4. 將 M 正規化到 0~255 供檢視。
  5. 以門檻 T 二值化 M,或直接把 M 當作邊緣強度圖使用。

Python 程式碼範例#

import numpy as np
from PIL import Image

# 40x40 影像:左半 50、右半 180 的垂直邊緣 + 少量雜訊
rng = np.random.default_rng(3)
img = np.where(np.arange(40) < 20, 50, 180).astype(np.float64)
img = np.tile(img, (40, 1)) + rng.normal(0, 5, (40, 40))

Gx = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]], dtype=np.float64)
Gy = np.array([[-1, -2, -1], [0, 0, 0], [1, 2, 1]], dtype=np.float64)

def conv(img, K):
    r = K.shape[0] // 2
    P = np.pad(img, r, mode="edge")
    H, W = img.shape
    out = np.zeros((H, W))
    for y in range(H):
        for x in range(W):
            out[y, x] = (P[y:y+3, x:x+3] * K).sum()
    return out

gx, gy = conv(img, Gx), conv(img, Gy)
mag = np.sqrt(gx**2 + gy**2)
ang = np.degrees(np.arctan2(gy, gx))

print("理論梯度 ∂I/∂x = 130, ∂I/∂y = 0")
print("邊緣處 gx:", gx[20, 20], " gy:", gy[20, 20])
print("梯度大小:", mag[20, 20].round(1), " 方向(度):", ang[20, 20].round(1))
print("均勻區域 mag:", mag[5, 5].round(2))

# 門檻化
T = 100
edge = (mag >= T).astype(np.uint8) * 255
print("門檻", T, "偵測到的邊緣像素數:", (edge > 0).sum())

執行後:邊緣處 gx ≈ 4×130 = 520(Sobel 的 ∂I/∂x 近似值是差分和的 1/8,這裡未除以 8,故為 8×130/2 的尺度),gy ≈ 0,方向接近 0°;均勻區域(雜訊)梯度僅個位數。門檻 100 能把雜訊完全濾掉、只留真正的邊緣線。

複雜度分析#

兩個 3×3 卷積各 O(H·W·9),加上大小與方向的逐像素三角函數 O(H·W),總計 O(H·W)。因 Gx、Gy 可分離,用兩次一維卷積可降至 O(H·W·6) 次乘加。空間 O(H·W)(gx、gy、M 各一份)。若只要大小不要方向,可省 atan2(相對昂貴)。門檻化 O(H·W)。

練習#

  1. 把範例影像的邊緣改成 45° 斜邊,計算 gx、gy 與方向角,驗證方向是否如理論(邊緣法向 45°)。
  2. 實作 Scharr 核心 gx = [[−3,0,3],[−10,0,10],[−3,0,3]],與 Sobel 比較在 σ=2 雜訊下邊緣位置估計的穩定度。
  3. 對一張真實照片的灰階版求梯度大小圖,統計 M 的直方圖;討論門檻 T 該落在直方圖的哪個區域,以及 T 太低/太高各發生什麼。