傅里葉變換
傅里葉變換(Fourier Transform,簡稱FT)常用于數(shù)字信號處理央碟,它的目的是將時間域上的信號轉(zhuǎn)變?yōu)轭l率域上的信號寒波。隨著域的不同,對同一個事物的了解角度也隨之改變崇堰,因此在時域中某些不好處理的地方沃于,在頻域就可以較為簡單的處理。同時海诲,可以從頻域里發(fā)現(xiàn)一些原先不易察覺的特征繁莹。傅里葉定理指出“任何連續(xù)周期信號都可以表示成(或者無限逼近)一系列正弦信號的疊加√蒯#”
傅里葉變換可以應用于圖像處理中咨演,經(jīng)過對圖像進行變換得到其頻譜圖。從譜頻圖里頻率高低來表征圖像中灰度變化劇烈程度敬辣。圖像中的邊緣信號和噪聲信號往往是高頻信號雪标,而圖像變化頻繁的圖像輪廓及背景等信號往往是低頻信號。這時可以有針對性的對圖像進行相關操作溉跃,例如圖像除噪村刨、圖像增強和銳化等。
Numpy實現(xiàn)傅里葉變換
Numpy中的fft模塊撰茎,相關函數(shù)如下:
- 計算一維傅里葉變換
numpy.fft.fft(a, n=None, axis=-1, norm=None)
- 計算二維的傅里葉變換
numpy.fft.fft2(a, n=None, axis=-1, norm=None)
- 計算n維的傅里葉變換
numpy.fft.fftn()
- 計算n維實數(shù)的傅里葉變換
numpy.fft.rfftn()
- 返回傅里葉變換的采樣頻率
numpy.fft.fftfreq()
- 將FFT輸出中的直流分量移動到頻譜中央
numpy.fft.shift()
Numpy中的 FFT包提供了函數(shù) np.fft.fft2()可以對信號進行快速傅里葉變換嵌牺,其函數(shù)原型如下所示,該輸出結(jié)果是一個復數(shù)數(shù)組(Complex Ndarry)。
fft2(a, s=None, axes=(-2, -1), norm=None)
- a表示輸入圖像逆粹,陣列狀的復雜數(shù)組
- s表示整數(shù)序列募疮,可以決定輸出數(shù)組的大小。輸出可選形狀(每個轉(zhuǎn)換軸的長度)僻弹,其中s[0]表示軸0阿浓,s[1]表示軸1。對應fit(x,n)函數(shù)中的n蹋绽,沿著每個軸芭毙,如果給定的形狀小于輸入形狀,則將剪切輸入卸耘。如果大于則輸入將用零填充退敦。如果未給定’s’,則使用沿’axles’指定的軸的輸入形狀
- axes表示整數(shù)序列蚣抗,用于計算FFT的可選軸侈百。如果未給出,則使用最后兩個軸翰铡《塾颍“axes”中的重復索引表示對該軸執(zhí)行多次轉(zhuǎn)換,一個元素序列意味著執(zhí)行一維FFT
- norm包括None和ortho兩個選項锭魔,規(guī)范化模式(請參見numpy.fft)网梢。默認值為無
頻率分布圖譜,其中越靠近中心位置頻率越低赂毯,越亮(灰度值越高)的位置代表該頻率的信號振幅越大
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
#讀取圖像
img = cv2.imread('data/test3.jpg', 0)
#快速傅里葉變換算法得到頻率分布
f = np.fft.fft2(img)
#默認結(jié)果中心點位置是在左上角,
#調(diào)用fftshift()函數(shù)轉(zhuǎn)移到中間位置
fshift = np.fft.fftshift(f)
#fft結(jié)果是復數(shù), 其絕對值結(jié)果是振幅
fimg = np.log(np.abs(fshift))
#展示結(jié)果
plt.figure(figsize=(10, 4))
plt.subplot(121), plt.imshow(img, 'gray'), plt.title('Original Fourier')
plt.axis('off')
plt.subplot(122), plt.imshow(fimg, 'gray'), plt.title('Fourier Fourier')
plt.axis('off')
plt.show()
Numpy實現(xiàn)傅里葉逆變換
傅里葉逆變換,是傅里葉變換的逆操作拣宰,將頻譜圖像轉(zhuǎn)換為原始圖像的過程党涕。通過傅里葉變換將轉(zhuǎn)換為頻譜圖,并對高頻(邊界)和低頻(細節(jié))部分進行處理巡社,接著需要通過傅里葉逆變換恢復為原始效果圖膛堤。頻域上對圖像的處理會反映在逆變換圖像上,從而更好地進行圖像處理晌该。
圖像逆傅里葉變換主要使用的函數(shù)如下所示:
- 實現(xiàn)圖像逆傅里葉變換肥荔,返回一個復數(shù)數(shù)組
numpy.fft.ifft2(a, n=None, axis=-1, norm=None)
- fftshit()函數(shù)的逆函數(shù),它將頻譜圖像的中心低頻部分移動至左上角
numpy.fft.fftshift()
- 將復數(shù)轉(zhuǎn)換為0至255范圍
iimg = numpy.abs(逆傅里葉變換結(jié)果)
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
plt.figure(figsize=(10, 4))
#讀取圖像
img = cv.imread('data/test3.jpg', 0)
#傅里葉變換
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)
res = np.log(np.abs(fshift))
#傅里葉逆變換
ishift = np.fft.ifftshift(fshift)
iimg = np.fft.ifft2(ishift)
iimg = np.abs(iimg)
#展示結(jié)果
plt.subplot(131), plt.imshow(img, 'gray'), plt.title('Original Image')
plt.axis('off')
plt.subplot(132), plt.imshow(res, 'gray'), plt.title('Fourier Image')
plt.axis('off')
plt.subplot(133), plt.imshow(iimg, 'gray'), plt.title('Inverse Fourier Image')
plt.axis('off')
plt.show()
OpenCV實現(xiàn)傅里葉變換
OpenCV 中相應的函數(shù)是cv2.dft()和用Numpy輸出的結(jié)果一樣朝群,但是是雙通道的燕耿。第一個通道是結(jié)果的實數(shù)部分,第二個通道是結(jié)果的虛數(shù)部分姜胖,并且輸入圖像要首先轉(zhuǎn)換成 np.float32 格式誉帅。其函數(shù)原型如下所示:
dst = cv2.dft(src, dst=None, flags=None, nonzeroRows=None)
- src表示輸入圖像,需要通過np.float32轉(zhuǎn)換格式
- dst表示輸出圖像,包括輸出大小和尺寸
- flags表示轉(zhuǎn)換標記蚜锨,其中DFT_INVERSE執(zhí)行反向一維或二維轉(zhuǎn)換档插,而不是默認的正向轉(zhuǎn)換;DFT_SCALE表示縮放結(jié)果亚再,由陣列元素的數(shù)量除以它郭膛;DFT_ROWS執(zhí)行正向或反向變換輸入矩陣的每個單獨的行,該標志可以同時轉(zhuǎn)換多個矢量氛悬,并可用于減少開銷以執(zhí)行3D和更高維度的轉(zhuǎn)換等则剃;DFT_COMPLEX_OUTPUT執(zhí)行1D或2D實數(shù)組的正向轉(zhuǎn)換,這是最快的選擇圆雁,默認功能忍级;DFT_REAL_OUTPUT執(zhí)行一維或二維復數(shù)陣列的逆變換,結(jié)果通常是相同大小的復數(shù)數(shù)組伪朽,但如果輸入數(shù)組具有共軛復數(shù)對稱性轴咱,則輸出為真實數(shù)組
- nonzeroRows表示當參數(shù)不為零時,函數(shù)假定只有nonzeroRows輸入數(shù)組的第一行(未設置)或者只有輸出數(shù)組的第一個(設置)包含非零烈涮,因此函數(shù)可以處理其余的行更有效率朴肺,并節(jié)省一些時間;這種技術對計算陣列互相關或使用DFT卷積非常有用
由于輸出的頻譜結(jié)果是一個復數(shù)坚洽,需要調(diào)用cv2.magnitude()函數(shù)將傅里葉變換的雙通道結(jié)果轉(zhuǎn)換為0到255的范圍戈稿。其函數(shù)原型如下:
cv2.magnitude(x, y)
- x表示浮點型X坐標值,即實部
- y表示浮點型Y坐標值讶舰,即虛部
- 最終輸出結(jié)果為幅值
import numpy as np
import cv2
from matplotlib import pyplot as plt
plt.figure(figsize=(10, 4))
#讀取圖像
img = cv.imread('data/test3.jpg', 0)
#傅里葉變換
dft = cv2.dft(np.float32(img), flags = cv2.DFT_COMPLEX_OUTPUT)
#將頻譜低頻從左上角移動至中心位置
dft_shift = np.fft.fftshift(dft)
#頻譜圖像雙通道復數(shù)轉(zhuǎn)換為0-255區(qū)間
result = 20*np.log(cv2.magnitude(dft_shift[:,:,0], dft_shift[:,:,1]))
#顯示圖像
plt.subplot(121), plt.imshow(img, cmap = 'gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(result, cmap = 'gray')
plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])
plt.show()
OpenCV實現(xiàn)傅里葉逆變換
OpenCV 中鞍盗,通過函數(shù)cv2.idft()實現(xiàn)傅里葉逆變換,其返回結(jié)果取決于原始圖像的類型和大小跳昼,原始圖像可以為實數(shù)或復數(shù)般甲。其函數(shù)原型如下所示:
dst = cv2.idft(src[, dst[, flags[, nonzeroRows]]])
- src表示輸入圖像,包括實數(shù)或復數(shù)
- dst表示輸出圖像
- flags表示轉(zhuǎn)換標記
- nonzeroRows表示要處理的dst行數(shù)
import numpy as np
import cv2
from matplotlib import pyplot as plt
plt.figure(figsize=(10, 4))
#讀取圖像
img = cv.imread('data/test3.jpg', 0)
#傅里葉變換
dft = cv2.dft(np.float32(img), flags = cv2.DFT_COMPLEX_OUTPUT)
dftshift = np.fft.fftshift(dft)
res1= 20*np.log(cv2.magnitude(dftshift[:,:,0], dftshift[:,:,1]))
#傅里葉逆變換
ishift = np.fft.ifftshift(dftshift)
iimg = cv2.idft(ishift)
res2 = cv2.magnitude(iimg[:,:,0], iimg[:,:,1])
#顯示圖像
plt.subplot(131), plt.imshow(img, 'gray'), plt.title('Original Image')
plt.axis('off')
plt.subplot(132), plt.imshow(res1, 'gray'), plt.title('Fourier Image')
plt.axis('off')
plt.subplot(133), plt.imshow(res2, 'gray'), plt.title('Inverse Fourier Image')
plt.axis('off')
plt.show()
圖像濾波
傅里葉變換的目的并不是為了觀察圖像的頻率分布(至少不是最終目的)鹅颊,更多情況下是為了對頻率進行過濾敷存,通過修改頻率以達到圖像增強、圖像去噪堪伍、邊緣檢測锚烦、特征提取、壓縮加密等目的帝雇。
過濾的方法一般有三種:低通(Low-pass)涮俄、高通(High-pass)、帶通(Band-pass)摊求。
高通濾波
高通濾波器是指通過高頻的濾波器禽拔,衰減低頻而通過高頻刘离,常用于增強尖銳的細節(jié),但會導致圖像的對比度會降低睹栖。該濾波器將檢測圖像的某個區(qū)域硫惕,根據(jù)像素與周圍像素的差值來提升像素的亮度。
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
plt.figure(figsize=(10, 4))
#讀取圖像
img = cv.imread('data/test3.jpg', 0)
#傅里葉變換
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)
#設置高通濾波器
rows, cols = img.shape
crow,ccol = int(rows/2), int(cols/2)
fshift[crow-30:crow+30, ccol-30:ccol+30] = 0
#傅里葉逆變換
ishift = np.fft.ifftshift(fshift)
iimg = np.fft.ifft2(ishift)
iimg = np.abs(iimg)
#顯示原始圖像和高通濾波處理圖像
plt.subplot(121), plt.imshow(img, 'gray'), plt.title('Original Image')
plt.axis('off')
plt.subplot(122), plt.imshow(iimg, 'gray'), plt.title('Result Image')
plt.axis('off')
plt.show()
低通濾波
低通濾波器是指通過低頻的濾波器野来,衰減高頻而通過低頻恼除,常用于模糊圖像。低通濾波器與高通濾波器相反曼氛,當一個像素與周圍像素的插值小于一個特定值時豁辉,平滑該像素的亮度,常用于去燥和模糊化處理舀患。
import cv2
import numpy as np
from matplotlib import pyplot as plt
plt.figure(figsize=(10, 6))
#讀取圖像
img = cv.imread('data/test3.jpg', 0)
#傅里葉變換
dft = cv2.dft(np.float32(img), flags = cv2.DFT_COMPLEX_OUTPUT)
fshift = np.fft.fftshift(dft)
#設置低通濾波器
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
#掩膜圖像和頻譜圖像乘積
f = fshift * mask
# print(f.shape, fshift.shape, mask.shape)
#傅里葉逆變換
ishift = np.fft.ifftshift(f)
iimg = cv2.idft(ishift)
res = cv2.magnitude(iimg[:,:,0], iimg[:,:,1])
#顯示原始圖像和低通濾波處理圖像
plt.subplot(121), plt.imshow(img, 'gray'), plt.title('Original Image')
plt.axis('off')
plt.subplot(122), plt.imshow(res, 'gray'), plt.title('Result Image')
plt.axis('off')
plt.show()