1. 程式人生 > >OpenCV傅立葉變換

OpenCV傅立葉變換

傅立葉變換可以將影象的時域訊號轉換到頻域,通過頻域我們可以看到訊號的另一面。我們可以在頻域對影象進行濾波等處理,然後通過傅立葉反變換,將頻域影象轉換回時域,就可以看到處理後的影象。

實際應用中,更多的是在頻域進行濾波器設計,設計合適的濾波器,然後將濾波器經過傅立葉反變換生成時域濾波器,最後在時域進行濾波操作。

下面通過一個例子,看看如何使用OpenCV進行傅立葉變換及其反變換。

import cv2
import numpy as np
import matplotlib.pyplot as plt

image = cv2.imread(r'pics/lena.png', cv2.IMREAD_GRAYSCALE)

dft = cv2.dft(np.float32(image), flags=cv2.DFT_COMPLEX_OUTPUT)
dft_shift = np.fft.fftshift(dft)
magnitude_spectrum = 20*np.log(cv2.magnitude(dft_shift[:, :, 0], dft_shift[:, :, 1]))

匯入相應的包後,先讀取灰度影象,使用OpenCV的dft函式,可以進行傅立葉變換,之後使用numpy的fft模組的fftshift對頻域進行中心化,這樣更便於觀察我們的頻域影象。最後我們求取了頻域的分貝表示的幅值,便於繪製。
image_back = np.fft.ifftshift(dft_shift)
image_back = cv2.idft(image_back)
image_back = cv2.magnitude(image_back[:, :, 0], image_back[:, :, 1])

接下來,我們直接對傅立葉變換後的資料進行了去中心化,然後利用OpenCV的idft函式進行了傅立葉反變換。之後重新求取反變換後的影象幅值,這樣,我們就還原了原來的影象。
rows, cols = image.shape
center_x, center_y = int(rows/2), int(cols/2)
dft_shift[center_x-30:center_x+30, center_y-30:center_y+30] = 0
filter_back = np.fft.ifftshift(dft_shift)
filter_back = cv2.idft(filter_back)
filter_back = cv2.magnitude(filter_back[:, :, 0], filter_back[:, :, 1])

接下來我們更進一步,使用傅立葉變換後的dft_shitf資料,將其中心部分半徑為30的頻率值置為0。之後同樣進行了去中心化和傅立葉反變換,求取幅值後,就得到了濾波後的影象。
plt.subplot(221), plt.imshow(image, 'gray'), plt.title('Origin')
plt.subplot(222), plt.imshow(magnitude_spectrum, 'gray'), plt.title('Fourier TransForm')
plt.subplot(223), plt.imshow(image_back, 'gray'), plt.title('Origin Back')
plt.subplot(224), plt.imshow(filter_back, 'gray'), plt.title('Transform Back')
plt.show()

之後繪製了上面的四個影象,結果如下圖。


右上角的影象就是頻率譜,影象中越亮的部分代表頻率幅值越大,上面的程式碼我們濾除了中心最亮的亮點,實際上就是濾除了最高頻的部分,也就是說我們進行了低通濾波。

另外,需要特別說明一下,右下角是低通濾波後的影象,如果放大來看,可以看到振鈴現象,這是由於我們使用的頻域濾波器有陡峭的邊緣,會導致振鈴的發生,其數學原理不再贅述,有很多文章進行了說明,可以查閱。