上一篇介紹了 Low-pass Filter。
我們把高頻移除,只保留低頻。
結果發現,圖片的大致輪廓仍然存在,但許多細節都消失了,看起來就像被模糊了一樣。
那如果今天,我們反過來操作,不要低頻,只留下高頻,圖片會變成什麼樣子?
這就是今天要介紹的 High-pass Filter(高通濾波器)。
前幾篇介紹過,低頻代表的是圖片的大致輪廓和平滑區域。
高頻則包含了亮度快速變化的資訊,例如:
因此,High-pass Filter 的概念就是:
保留高頻,移除低頻。
也就是說,圖片中平滑的部分會被大幅減少。
而邊緣和細節則會被保留下來。
大部分物體的內部,其實亮度變化都很平滑。
真正亮度變化劇烈的地方,通常都會出現在物體的邊界。
因此,當低頻被移除之後,剩下來的大多就是亮度快速變化的位置。
也就是我們看到的邊緣。
前面的步驟和 Low-pass Filter 幾乎完全相同。
先把圖片轉換到頻域。
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread("dog.jpeg", cv2.IMREAD_GRAYSCALE)
# Fourier Transform
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)
接著建立遮罩。
和上一篇不同的是,這次不是保留中央,而是把中央移除。
rows, cols = img.shape
crow, ccol = rows // 2, cols // 2
mask = np.ones((rows, cols), np.uint8)
radius = 50
y, x = np.ogrid[:rows, :cols]
area = (x - ccol) ** 2 + (y - crow) ** 2 <= radius ** 2
mask[area] = 0
套用遮罩。
filtered = fshift * mask
最後再轉回空間域。
# 移回原本位置
ishift = np.fft.ifftshift(filtered)
# Inverse Fourier Transform
result = np.fft.ifft2(ishift)
# 取絕對值
result = np.abs(result)
將結果畫出來。
plt.figure(figsize=(12, 4))
plt.subplot(1, 3, 1)
plt.imshow(img, cmap="gray")
plt.title("Original")
plt.axis("off")
plt.subplot(1, 3, 2)
plt.imshow(np.log(np.abs(filtered) + 1), cmap="gray")
plt.title("High-pass Spectrum")
plt.axis("off")
plt.subplot(1, 3, 3)
plt.imshow(result, cmap="gray")
plt.title("High-pass Result")
plt.axis("off")
plt.tight_layout()
plt.show()
結果如下:

可以發現,圖片的大致輪廓幾乎消失了。
留下來的,大多都是邊緣和細節。
這也是 High-pass Filter 最典型的效果。
之前介紹過 Sobel、Prewitt 和 Laplacian,它們也會把邊緣找出來。
那和 High-pass Filter 有什麼不同?
最大的差別就在於:它們工作的方式不同。
Sobel、Prewitt 和 Laplacian 都是在空間域中,利用不同的 Kernel 去計算亮度變化。
High-pass Filter 則是在頻域中,直接移除低頻資訊,再透過反傅立葉轉換得到結果。
雖然最後都能強調邊緣,但背後使用的方法不一樣。
High-pass Filter 常見的用途包括:
它也經常作為其他影像處理演算法的前處理,幫助後續分析更加容易。
今天介紹了 High-pass Filter。
它會移除圖片中的低頻資訊,只保留高頻,因此可以讓邊緣、紋理和其他細節更加明顯。
搭配上一篇介紹的 Low-pass Filter,可以發現頻域處理最大的特色,就是能直接決定要保留哪些頻率、移除哪些頻率,而不同的頻率組合,也會產生截然不同的影像效果。
不過,頻域分析只是影像處理的方法之一。
接下來,我們會回到空間域,介紹另一種非常重要的特徵。
如果想讓電腦知道圖片中的「角落」在哪裡,而不只是找出邊緣,該怎麼做?
下一篇,我們就來介紹 Harris Corner Detection,看看電腦如何找到圖片中的角點。