上一篇介紹了 FFT。
現在,我們已經可以很快地把圖片從空間域轉換到頻域。
轉換到頻域之後,真正好玩的地方才正要開始。
如果今天我們可以自由決定哪些頻率要留下,哪些頻率要移除的話,圖片會發生什麼變化?
今天就先來看看最常見的一種方法:
Low-pass Filter(低通濾波器)。
還記得前面提到的頻率嗎?
在影像中,低頻通常代表圖片的大致輪廓,以及亮度變化比較平緩的區域。
高頻則代表邊緣、紋理、文字等亮度快速變化的細節。
Low-pass Filter 的概念很簡單:
保留低頻,移除高頻。
也就是說,圖片的大致內容會留下來。
但是許多細節會慢慢消失。
我們平常看到的許多細節。
其實都是高頻資訊。
例如:
這些地方的亮度變化都很快。
因此,當高頻被移除之後,圖片雖然還保留原本的輪廓,但細節卻會逐漸消失,看起來就像被模糊了一樣。
前面有提到,傅立葉轉換之後,頻譜中央代表低頻,靠近四周,則代表越高的頻率。
因此如果只保留中央區域,並將其他地方全部設成 0,就等於只保留低頻資訊。
完成之後,再利用反傅立葉轉換(Inverse Fourier Transform)從頻域轉回去空間域。
就可以重新得到一張高頻被移除的圖片。
先和上一篇一樣,把圖片轉換到頻域。
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)
接著建立一個遮罩(Mask)。
rows, cols = img.shape
crow, ccol = rows // 2, cols // 2
mask = np.zeros((rows, cols), np.uint8)
radius = 50
y, x = np.ogrid[:rows, :cols]
area = (x - ccol) ** 2 + (y - crow) ** 2 <= radius ** 2
mask[area] = 1
這個遮罩代表只有中央圓形區域會被保留下來,其他高頻資訊全部移除。
接著把遮罩套用到頻譜:
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("Low-pass Spectrum")
plt.axis("off")
plt.subplot(1, 3, 3)
plt.imshow(result, cmap="gray")
plt.title("Low-pass Result")
plt.axis("off")
plt.tight_layout()
plt.show()
結果如下:

可以發現,圖片的大致輪廓仍然存在,但是細節開始消失。
整張圖片變得比較柔和,也就是我們熟悉的模糊效果。
之前介紹過 Gaussian Filter。
現在又介紹 Low-pass Filter。
那它們是不是同一件事情?
其實,目的很接近,但做法不同。
Gaussian Filter 是直接在空間域操作 Pixel,利用 Kernel 和鄰近 Pixel 做 Convolution。
Low-pass Filter 則是在頻域操作,直接把高頻資訊移除,再轉回圖片。
最後都會得到模糊的效果,只是實現的方法不同。
今天介紹了 Low-pass Filter。
它的核心概念,就是保留低頻、移除高頻,因此可以保留圖片的大致輪廓,同時讓許多細節消失。
也因為如此,Low-pass Filter 常被用來降低雜訊、平滑圖片,以及觀察影像中的整體結構。
不過,如果今天反過來思考,不要保留低頻,而是把低頻移除,只留下高頻,圖片又會變成什麼樣子?
下一篇,我們就來介紹 High-pass Filter(高通濾波器),看看只保留高頻資訊後,圖片會有哪些不同的變化。