網(wǎng)站被墻了怎么辦百度推廣合作
理論
傅立葉變換用于分析各種濾波器的頻率特性。對(duì)于圖像,使用?2D離散傅里葉變換(DFT)?查找頻域。快速算法稱為?快速傅立葉變換(FFT)?用于計(jì)算DFT。
Numpy中的傅立葉變換
首先,我們將看到如何使用Numpy查找傅立葉變換。Numpy具有FFT軟件包來執(zhí)行此操作。np.fft.fft2()?為我們提供了頻率轉(zhuǎn)換,它將是一個(gè)復(fù)雜的數(shù)組。它的第一個(gè)參數(shù)是輸入圖像,即灰度圖像。第二個(gè)參數(shù)是可選的,它決定輸出數(shù)組的大小。如果它大于輸入圖像的大小,則在計(jì)算FFT之前用零填充輸入圖像。如果小于輸入圖像,將裁切輸入圖像。如果未傳遞任何參數(shù),則輸出數(shù)組的大小將與輸入的大小相同。
現(xiàn)在,一旦獲得結(jié)果,零頻率分量(DC分量)將位于左上角。如果要使其居中,只需通過函數(shù)?np.fft.fftshift()?即可完成。(它更容易分析)。找到頻率變換后,就可以找到幅度譜。
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
img = cv.imread('messi5.jpg',0)
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)
magnitude_spectrum = 20*np.log(np.abs(fshift))
plt.subplot(121),plt.imshow(img, cmap = 'gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(magnitude_spectrum, cmap = 'gray')
plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])
plt.show()
結(jié)果如下:
可以在中心看到更多白色區(qū)域,這表明低頻內(nèi)容更多。
因此,您已經(jīng)進(jìn)行了頻率變換,您可以在頻域中執(zhí)行一些操作,例如高通濾波和重建圖像,若進(jìn)行逆DFT。為此,您需用尺寸為60x60的矩形窗口遮罩來消除低頻。然后,使用?np.fft.ifftshift()?應(yīng)用反向移位,以使DC分量再次出現(xiàn)在左上角。然后使用?np.ifft2()?函數(shù)找到逆FFT 。同樣,結(jié)果將是一個(gè)復(fù)數(shù)。
rows, cols = img.shape
crow,ccol = rows//2 , cols//2
fshift[crow-30:crow+31, ccol-30:ccol+31] = 0
f_ishift = np.fft.ifftshift(fshift)
img_back = np.fft.ifft2(f_ishift)
img_back = np.real(img_back)
plt.subplot(131),plt.imshow(img, cmap = 'gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(132),plt.imshow(img_back, cmap = 'gray')
plt.title('Image after HPF'), plt.xticks([]), plt.yticks([])
plt.subplot(133),plt.imshow(img_back)
plt.title('Result in JET'), plt.xticks([]), plt.yticks([])
plt.show()
結(jié)果如下:
結(jié)果表明高通濾波是邊緣檢測操作。
如果您仔細(xì)觀察結(jié)果,尤其是最后一張JET顏色的圖像,您會(huì)看到一些偽像(我用紅色箭頭標(biāo)記的一個(gè)實(shí)例)。它在那里顯示出一些波紋狀結(jié)構(gòu),稱為?振鈴效應(yīng)?。這是由我們用于遮罩的矩形窗口引起的。此蒙版轉(zhuǎn)換為正弦形狀,從而導(dǎo)致此問題。因此,矩形窗口不用于過濾。更好的選擇是高斯窗口。
OpenCV中的傅立葉變換
OpenCV 為此提供了功能?cv.dft()?和?cv.idft()?。它返回與以前相同的結(jié)果,但是有兩個(gè)通道。第一個(gè)通道將具有結(jié)果的實(shí)部,第二個(gè)通道將具有結(jié)果的虛部。輸入的圖像應(yīng)首先轉(zhuǎn)換為np.float32?。
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread('messi5.jpg',0)
dft = cv.dft(np.float32(img),flags = cv.DFT_COMPLEX_OUTPUT)
dft_shift = np.fft.fftshift(dft)
magnitude_spectrum = 20*np.log(cv.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(magnitude_spectrum, cmap = 'gray')
plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])
plt.show()
注意?還可以使用?cv.cartToPolar()?一次返回大小和相位
因此,現(xiàn)在我們必須進(jìn)行逆DFT。在上一部分中,我們創(chuàng)建了一個(gè)HPF,這次我們將看到如何去除圖像中的高頻內(nèi)容,即我們將LPF應(yīng)用于圖像。實(shí)際上會(huì)使圖像模糊。為此,我們首先創(chuàng)建一個(gè)在低頻時(shí)具有高值(1)的蒙版,即,我們傳遞LF含量,并在HF區(qū)域傳遞0。
rows, cols = img.shape
crow,ccol = rows/2 , cols/2
# create a mask first, center square is 1, remaining all zeros
mask = np.zeros((rows,cols,2),np.uint8)
mask[crow-30:crow+30, ccol-30:ccol+30] = 1
# apply mask and inverse DFT
fshift = dft_shift*mask
f_ishift = np.fft.ifftshift(fshift)
img_back = cv.idft(f_ishift)
img_back = cv.magnitude(img_back[:,:,0],img_back[:,:,1])
plt.subplot(121),plt.imshow(img, cmap = 'gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(img_back, cmap = 'gray')
plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])
plt.show()
查看結(jié)果:
注意?像往常一樣,OpenCV函數(shù)?cv.dft()?和?cv.idft()?比Numpy對(duì)應(yīng)函數(shù)要快。但是Numpy功能更加人性化。
DFT的性能優(yōu)化
對(duì)于某些陣列大小,DFT計(jì)算的性能更好。當(dāng)陣列大小為2的冪時(shí),它是最快的。大小為2、3和5的乘積的數(shù)組也得到了有效處理。因此,如果您擔(dān)心代碼的性能,可以在找到DFT之前將數(shù)組的大小修改為任何最佳大小(通過填充零)。對(duì)于OpenCV,您必須手動(dòng)填充零。但是對(duì)于Numpy,您可以指定FFT計(jì)算的新大小,它將自動(dòng)為您填充零。
那么我們?nèi)绾握业竭@個(gè)最佳尺寸呢?OpenCV 為此提供了一個(gè)函數(shù)?cv.getOptimalDFTSize()?。它適用于?cv.dft()?和?np.fft.fft2()?。讓我們使用IPython magic命令timeit檢查它們的性能。
In [16]: img = cv.imread('messi5.jpg',0)
In [17]: rows,cols = img.shape
In [18]: print("{} {}".format(rows,cols))
342 548
In [19]: nrows = cv.getOptimalDFTSize(rows)
In [20]: ncols = cv.getOptimalDFTSize(cols)
In [21]: print("{} {}".format(nrows,ncols))
360 576
參見,將大小(342,548)修改為(360,576)?,F(xiàn)在讓我們用零填充(對(duì)于OpenCV),并找到其DFT計(jì)算性能。您可以通過創(chuàng)建一個(gè)新的大零數(shù)組并將數(shù)據(jù)復(fù)制到其中來完成此操作,或者使用?cv.copyMakeBorder()?。
nimg = np.zeros((nrows,ncols))
nimg[:rows,:cols] = img
要么:
right = ncols - cols
bottom = nrows - rows
bordertype = cv.BORDER_CONSTANT #just to avoid line breakup in PDF file
nimg = cv.copyMakeBorder(img,0,bottom,0,right,bordertype, value = 0)
現(xiàn)在,我們計(jì)算Numpy函數(shù)的DFT性能比較:
In [22]: %timeit fft1 = np.fft.fft2(img)
10 loops, best of 3: 40.9 ms per loop
In [23]: %timeit fft2 = np.fft.fft2(img,[nrows,ncols])
100 loops, best of 3: 10.4 ms per loop
它顯示了4倍的加速。現(xiàn)在,我們將嘗試使用OpenCV函數(shù)。
In [24]: %timeit dft1= cv.dft(np.float32(img),flags=cv.DFT_COMPLEX_OUTPUT)
100 loops, best of 3: 13.5 ms per loop
In [27]: %timeit dft2= cv.dft(np.float32(nimg),flags=cv.DFT_COMPLEX_OUTPUT)
100 loops, best of 3: 3.11 ms per loop
它還顯示了4倍的加速??梢钥吹絆penCV函數(shù)比Numpy函數(shù)快3倍左右。
apachecn.github.io/opencv-doc-zh/#/