[OpenCV筆記] 12. 傅立葉轉換實作
1.前言
影像處理通常分為空間域處理與頻率域處理。傅立葉轉換是頻率域影像處理中常見的方法之一。關於傅立葉轉換的原理介紹,請參考<從傅立葉轉換到訊號處理>。
透過傅立葉轉換,我們可以依據需求,設計高通濾波器或低通濾波器來進行影像處理。
1.1.高通濾波器與低通濾波器
- 低通濾波器,讓低頻訊號通過,會使影像模糊。
- 高通濾波器,讓高頻訊號通過,會增強影像中尖銳的細節,導致影像對比度降低。
何謂低頻訊號呢? 何謂高頻訊號呢?
- 低頻訊號對應影像內變化緩慢的灰階分量。以草原中獅子圖為例,低頻訊號對應顏色趨於一致的草原。
- 高頻訊號對應影像內變化越來越快的灰階分量。以草原中獅子圖為例,高頻訊號對應獅子的邊緣等資訊。
2.程式實作
實現傅立葉轉換的模組,numpy和opencv都有內建相應模組,可彈性使用。
相關用法與結果呈現如下:
2.1. numpy傅立葉轉換
<來源:Greatway9999>import numpy as np
import cv2
import matplotlib.pyplot as plt
img = cv2.imread('Lenna.jpg', cv2.IMREAD_GRAYSCALE)
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)
magnitude_spectrum = 20*np.log(np.abs(fshift)) #將值轉換成0~255間
#繪圖
plt.subplot(121)
plt.imshow(img, cmap='gray')
plt.title('original')
plt.axis('off')
plt.subplot(122)
plt.imshow(magnitude_spectrum, cmap='gray')
plt.title('result')
plt.axis('off')
plt.show()
2.2.傅立葉逆轉換
<來源:Greatway9999>
import numpy as np
import cv2
import matplotlib.pyplot as plt
img = cv2.imread('Lenna.jpg', cv2.IMREAD_GRAYSCALE)
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)
ishift = np.fft.ifftshift(fshift)
iimg = np.fft.ifft2(ishift)
iimg = np.abs(iimg)
plt.subplot(121)
plt.imshow(img, cmap='gray')
plt.title('original')
plt.axis('off')
plt.subplot(122)
plt.imshow(iimg, cmap='gray')
plt.title('iimg')
plt.axis('off')
plt.show()
2.3. numpy 高通濾波器實作
<來源:Greatway9999>import numpy as np
import cv2
import matplotlib.pyplot as plt
img = cv2.imread('Lenna.jpg', cv2.IMREAD_GRAYSCALE)
# Step1 傅立葉轉換
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)
#Step2 將低頻分量值歸0
rows, cols = img.shape
crow, ccol = int(rows/2), int(cols/2) #找影像中心
fshift[crow-30:crow+30, ccol-30:ccol+30] = 0 #將低頻分量值歸0
# Step3 逆傅立葉轉換
ishift = np.fft.ifftshift(fshift)
iimg = np.fft.ifft2(ishift)
iimg = np.abs(iimg)
plt.subplot(121)
plt.imshow(img, cmap='gray')
plt.title('original')
plt.axis('off')
plt.subplot(122)
plt.imshow(iimg, cmap='gray')
plt.title('iimg')
plt.axis('off')
plt.show()
2.4.OpenCV的傅立葉轉換
<來源:Greatway9999># 重點:將影像轉換成 np.float32格式
import numpy as np
import cv2
import matplotlib.pyplot as plt
img = cv2.imread('Lenna.jpg', cv2.IMREAD_GRAYSCALE)
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)
dft = cv2.dft(np.float32(img), flags = cv2.DFT_COMPLEX_OUTPUT)
dftshift = np.fft.fftshift(dft)
result = 20*np.log(cv2.magnitude(dftshift[:,:,0], dftshift[:,:,1]))
plt.subplot(121)
plt.imshow(img, cmap='gray')
plt.title('original')
plt.axis('off')
plt.subplot(122)
plt.imshow(result, cmap='gray')
plt.title('result')
plt.axis('off')
plt.show()
2.5.OpenCV的低通濾波器實作
<來源:Greatway9999>import numpy as np
import cv2
import matplotlib.pyplot as plt
img = cv2.imread('Lenna.jpg', cv2.IMREAD_GRAYSCALE)
# Step1 傅立葉轉換
dft = cv2.dft(np.float32(img), flags = cv2.DFT_COMPLEX_OUTPUT)
dftshift = np.fft.fftshift(dft)
#Step2 將高頻濾掉,只讓低頻通過。透過遮罩方式進行
rows, cols = img.shape
crow, ccol = int(rows/2), int(cols/2) #找影像中心
mask = np.zeros((rows, cols, 2), np.uint8) #建立遮罩
mask[crow-30:crow+30, ccol-30:ccol+30] = 1 #將指定區域的值設為1
fShift = dftshift * mask #將高頻濾掉,保留低頻
# Step3 逆傅立葉轉換
ishift = np.fft.ifftshift(fShift)
iImg = cv2.idft(ishift)
iImg = cv2.magnitude(iImg[:,:,0], iImg[:,:,1])
plt.subplot(121)
plt.imshow(img, cmap='gray')
plt.title('original')
plt.axis('off')
plt.subplot(122)
plt.imshow(iImg, cmap='gray')
plt.title('iImg')
plt.axis('off')
plt.show()
---
參考資料:
0 留言