前言
要理解傅里葉變換,我們首先需要了解圖像處理。在圖像處理的過程中,一般分為空間域處理和頻率域處理。
空間域處理是直接對圖像內的像素進行處理。空間域處理主要劃分為灰度變換和空間濾波兩種形式。灰度變換是對圖像內的單個像素進行處理,比如調節對比度和處理閾值等。控制濾波處理涉及圖像質量的改變,例如前面的圖像平滑處理。空間域處理的優點:計算簡單方便,運算速度更快
頻率域處理時先將圖像變換到頻率域,然后在頻率域對圖像進行處理,最后在通過反變換將圖像從頻率域變換到空間域。傅里葉變換是應用最廣泛的一種頻率域變換,它能夠將圖像從空間域變換到頻率域,而逆傅里葉變換能夠將頻率域信息變換到空間域內。
傅里葉變化
法國數學家傅里葉指出,任何周期函數都可以表示為不同頻率的正弦函數和的形式。
在圖像的處理中,傅里葉變換就是將圖像分解為正弦分量和余弦分量兩部分,即將圖像從空間域轉換到頻率域。數字圖像經過傅里葉變化后,得到的頻率域的值是復數。因此顯示傅里葉變換的結果需要使用實數圖像加虛數圖像,或者幅度圖像加相位圖像的形式。
因為幅度圖像包含了原圖像中我們所需要的大部分信息,所以在圖像的處理過程中,通常僅使用幅度圖像。當然,如果希望先在頻率域內對圖像進行處理,再通過傅里葉變換得到修改后的空間域圖像,就必須同時保留幅度圖像和相位圖像。
對圖像進行傅里葉變換后,我們會得到圖像中的低頻與高頻信息。低頻信息對應圖像內變化緩慢的灰度分量。高頻信息對應圖像內變換越來越快的灰度分量,是由灰度的尖銳過度造成的。例如,在一副大草原的圖像中有一頭獅子,低頻信息就對應著廣袤的草原,而高頻信息對應著獅子的輪廓等各種邊界及噪聲信息。
傅里葉變換的作用,就是為了將圖像從空域轉換到頻域,并在頻率域內實現對圖像內特定對象的處理,然后再對經過處理的頻率域圖像進行逆傅里葉變換得到空間域圖像。其主要用處包括:圖像增強,圖像去噪,邊緣檢測,特征提取,圖像壓縮,圖像加密等。
實現傅里葉變化
在Numpy包中,它給我們提供了numpy.fft.fft2()函數實現傅里葉變換。其完整定義如下:
def fft2(原始圖像):
需要注意的是,原始圖像必須是灰度圖像,其返回值是ndarray類型。
下面,我們來實現傅里葉變換,并觀察得到的頻譜圖像:
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread("4.jpg", 0)#1
f = np.fft.fft2(img)#2
fshift = np.fft.fftshift(f)#3
spectrum = 20 * np.log(np.abs(fshift))#4
#5
plt.subplot(121)
plt.imshow(img)
plt.axis('off')
#6
plt.subplot(122)
plt.imshow(spectrum)
plt.axis('off')
#7
plt.show()
上面代碼以此代表的意思如下:
1.使用OpenCV以灰度圖像的形式讀取
2.實現傅里葉變換
3.經過2傅里葉變換函數處理之后。此時,圖像頻譜中的零頻率分量位于頻譜圖像的左上角,為了便于觀察,這里通過函數np.fft.fftshift將零頻譜成分移動到頻域圖像的中心位置。
4.對圖像進行傅里葉變換之后,得到的是一個復數數組。為了顯示為圖像,需要將它們的值調整到[0,255]的灰度空間內,通過20 * np.log(np.abs(fshift))實現。
5.以灰度圖像的形式繪制原圖
6.以灰度圖像的形式繪制頻域圖
7.顯示2個圖
運行之后,效果如下:
實現逆傅里葉變化
既然我們在實現傅里葉變換之時,將零頻譜移動到了圖像中間。那么,在逆變換的時候,我我們就需要將其移回去,該移回去的逆函數是np.fft.ifftshift()。而移回去之后,才可以進行逆傅里葉變換。
逆傅里葉變換函數為np.fft.ifft2()。它返回空域信息是一個復數數組,同樣需要我們將信息調整到[0,255]之間。使用公式為:np.abs(逆傅里葉變換結果)。
下面,我們實現傅里葉變換以及逆傅里葉變換。代碼如下所示:
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread("4.jpg", 0)
#傅里葉變換
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)
ishift=np.fft.ifftshift(fshift)
iimg=np.fft.ifft2(ishift)
iimg=np.abs(iimg)
print(iimg)
print(img)
plt.subplot(121)
plt.imshow(img,cmap="gray")
plt.axis('off')
plt.subplot(122)
plt.imshow(iimg,cmap="gray")
plt.axis('off')
plt.show()
高通濾波與低通濾波
經過前文的介紹,我們知道在一副圖像內,同時存在著高頻信號和低頻信號。而濾波器你可以把它想象成平時生活中的漏斗,它能夠允許一定頻率的分量通過或者拒絕其通過。
我們通過濾波器的作用方式,將其分為低通濾波器與高通濾波器。(題外話,此高通非彼高通,皮一下)
低通濾波器:允許低頻信號通過。低通濾波器使高頻信號衰減而對低頻信號放行,會使圖像變得模糊
高通濾波器:允許高頻信號通過。高通濾波器使低頻信號衰減而讓高頻信號通過,將增強圖像中尖銳的細節,但是會導致圖像的對比度降低。
頻域處理就是對圖像的高頻或低頻信號進行處理后,再進行逆傅里葉變換返回空間域。
下面,我們來通過傅里葉的正逆操作,實現高通濾波。代碼如下:
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread("4.jpg", 0)
# 傅里葉變換
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)
#屏蔽低頻信號
rows, cols = img.shape
row_half, col_half = int(rows / 2), int(cols / 2)
fshift[row_half-20:row_half+20,col_half-20:col_half+20]=0
#逆傅里葉變換
ishift=np.fft.ifftshift(fshift)
iimg=np.fft.ifft2(ishift)
iimg=np.abs(iimg)
plt.subplot(121)
plt.imshow(img, cmap="gray")
plt.axis('off')
plt.subplot(122)
plt.imshow(iimg, cmap="gray")
plt.axis('off')
plt.show()
上面的代碼中,主要通過3行代碼屏蔽低頻信號,代碼如下:
rows, cols = img.shape
row_half, col_half = int(rows / 2), int(cols / 2)
fshift[row_half-20:row_half+20,col_half-20:col_half+20]=0
我們通過前文知道,np.fft.fftshift會將零頻率分量移動到圖像的中心區域,那么從中心區域向外擴散就是從低到高。所以,我們只要將中心周圍部分的低頻信號屏蔽,就保留的高頻信號,也就是實現了高通濾波。
這里我們選擇從中心向外擴散30半徑,將其內部的所有低頻信號全部賦值為0即可。運行之后,我們會得到高通濾波的圖像,同時該圖像的邊緣信息得以保留。