OpenCV-Python -- Fourier Transform
學習目標
- 使用OpenCV計算傅立葉變換
- 使用Numpy中的傅立葉變換(FFT)
- 傅立葉變換的應用
- 學習函式如下:
cv2.dft()
,cv2.idft()
理論
傅立葉變換用來分析不同濾波器的頻率特性。對於影像而言,2D離散傅立葉變換(DFT)用於尋找頻率域。傅立葉變換的快速演算法,FFT,常用於計算DFT。
對於正弦訊號,
x
(
t
)
=
A
s
i
n
(
2
π
f
t
)
x(t) = Asin(2\pi ft)
x(t)=Asin(2πft),我們稱f
為頻率訊號,如果頻率域確定,那麼我們可以看到f
的具體形狀(spike)。如果一個訊號是離散取樣的,我們得到相同的頻率域,週期的範圍,
[
−
π
,
π
]
,
o
r
[
0
,
2
π
]
(
o
r
f
o
r
N
−
P
o
i
n
t
的
D
F
T
,
[
0
,
N
]
)
[-\pi ,\pi],or[0, 2\pi](or for N-Point的DFT,[0,N])
[−π,π],or[0,2π](orforN−Point的DFT,[0,N])。可以將影像看成從兩個方向取樣的訊號。那麼從X和Y方向取樣可以得到影像的表達。
更為直觀的說,對於正弦訊號,如果短時間內振幅變化很快,那麼可以稱為高頻訊號。如果變化很慢,則稱之為低頻訊號。如果將該思想擴充套件到影像中,那麼影像的什麼區域振幅較大,通常是邊界點或者噪聲。所以,我們可以說,邊界和噪聲是影像中的高頻訊號。反之則為低頻區域。
Numpy中的傅立葉變換
首先我們學習如何利用Numpy計算傅立葉變換。Numpy有相應的FFT包。np.fft.fft2()
提供了頻率變換,它是複陣列。第一個輸入引數是灰度影像。第二個引數是可選的,決定了輸出陣列的大小。如果輸出陣列大於輸入影像,那麼輸入影像會被填充零,然後計算FFT
。如果小於輸入影像,那麼輸入影像會被裁剪。如果沒有傳入引數,輸出陣列大小與輸入相同。
計算得到結果,零頻域部分(DC component)在左上角。如果需要將其移入中心,那麼需要偏移N/2。可以使用函式計算:np.fft.fftshift()
. 得到頻率變換後,也可以得到振幅譜。
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.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()
執行結果如下:
從圖中可以看出,白色區域在中心,表示低頻區域更多。得到頻域變換後,可以在頻率域進行一些操作,比如高通濾波和重建影像,或者計算DFT的逆操作。通過設計一個60x60大小的矩形視窗可以濾除低頻部分。然後應用逆操作,np.fft.ifftshift()
,那麼DC區域會變換到左上角。並計算FFT的逆操作,np.ifft2()
。得到的結果是複數,取絕對值:
rows, cols = img.shape
crow,ccol = rows/2 , cols/2
fshift[crow-30:crow+30, ccol-30:ccol+30] = 0
f_ishift = np.fft.ifftshift(fshift)
img_back = np.fft.ifft2(f_ishift)
img_back = np.abs(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()
執行結果如下:
從結果可以看出,高通濾波器是邊界檢測器。在影像梯度的章節我們也看到類似的效果。同樣可以得到,影像大部分是低頻區域。
OpenCV中傅立葉變換
OpenCV提供的函式:cv2.dft()
,cv2.idft()
. 返回結果與上面的一樣,但是通道為2. 第一個通道是結果的實部,第二個通道是結果的虛部。輸入影像必須轉為np.float32,下面是程式碼示例:
import numpy as np
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('messi5.jpg',0)
dft = cv2.dft(np.float32(img),flags = cv2.DFT_COMPLEX_OUTPUT)
dft_shift = np.fft.fftshift(dft)
magnitude_spectrum = 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(magnitude_spectrum, cmap = 'gray')
plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])
plt.show()
執行結果如下:
cv2.cartToPolar()可以同時返回幅度和相位
現在需要進行DFT
的逆操作。在上面的敘述中,我們建立了HPF,現在我們學習去除影像的高頻部分,即對影像使用LPF。實際上會模糊影像。那麼,我們對於低頻部分置為1,高頻為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 = cv2.idft(f_ishift)
img_back = cv2.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()
執行結果如下:
優化DFT
某些大小的陣列進行DFT
會非常快,比如陣列大小時
2
n
2^n
2n. 如果需要提速,可以對陣列進行零填充,然後進行DFT
。對於OpenCV,需要人工填充零,而Numpy中,需要指定FFT的大小引數即可,然後會自動填充零。
所以,最佳的陣列大小是?OpenCV提供了函式:cv2.getOptimalDFTSize()
。該函式可以應用於cv2.dft()
,cv2.idft()
,下面來驗證:
為什麼Laplacian是高通濾波器?
import cv2
import numpy as np
from matplotlib import pyplot as plt
# simple averaging filter without scaling parameter
mean_filter = np.ones((3, 3))
# creating a guassian filter
x = cv2.getGaussianKernel(5, 10)
gaussian = x * x.T
# different edge detecting filters scharr in x-direction
scharr = np.array([[-3, 0, 3],
[-10, 0, 10],
[-3, 0, 3]])
# sobel in x direction
sobel_x = np.array([[-1, 0, 1],
[-2, 0, 2],
[-1, 0, 1]])
# sobel in y direction
sobel_y = np.array([[-1, -2, -1],
[0, 0, 0],
[1, 2, 1]])
# laplacian
laplacian = np.array([[0, 1, 0],
[1, -4, 1],
[0, 1, 0]])
filters = [mean_filter, gaussian, laplacian, sobel_x, sobel_y, scharr]
filter_name = ['mean_filter', 'gaussian', 'laplacian', 'sobel_x', 'sobel_y', 'scharr_x']
fft_filters = [np.fft.fft2(x) for x in filters]
fft_shift = [np.fft.fftshift(y) for y in fft_filters]
mag_spectrum = [np.log(np.abs(z) + 1) for z in fft_shift]
for i in range(6):
plt.subplot(2, 3, i + 1), plt.imshow(mag_spectrum[i], cmap='gray')
plt.title(filter_name[i]), plt.xticks([]), plt.yticks([])
plt.show()
執行結果:
相關文章
- 【OI向】快速傅立葉變換(Fast Fourier Transform)ASTORM
- 影象處理1--傅立葉變換(Fourier Transform )ORM
- 使用 scipy.fft 進行Fourier Transform:Python 訊號處理FFTORMPython
- 各種Fourier變換
- 『OpenCV-Python』滑鼠事件OpenCVPython事件
- 最新openCV-Python安裝教程(opencv-python版本4.4.0, Python版本: 3.9)OpenCVPython
- Census TransformORM
- canvas transform()CanvasORM
- opencv-python學習之旅OpenCVPython
- transform Vs UdfORM
- OpenCV-Python 視訊讀取OpenCVPython
- Android Transform + ASM 初探AndroidORMASM
- CSS transform-originCSSORM
- 深入理解TransformORM
- CSS transform 屬性CSSORM
- 4、Flutter Widget - Transform;FlutterORM
- Python - opencv-python 獲取影片尺寸PythonOpenCV
- Games101-2 transformGAMORM
- Laravel Transform 轉換器LaravelORM
- canvas transform引數解析CanvasORM
- OpenCV-Python 人臉眼睛嘴識別OpenCVPython
- 『OpenCV-Python』色彩空間及色彩轉換OpenCVPython
- 使用 OpenCV-Python 識別答題卡判卷OpenCVPython
- 什麼是Transform轉換ORM
- css使用transform垂直對齊CSSORM
- Css3中的TransformCSSS3ORM
- animation、transition、transform的區別ORM
- CSS3 transform-styleCSSS3ORM
- transition、transform、animate的區別?ORM
- opencv-python簡易文件(一)圖片基本操作OpenCVPython
- [elixir! #0083] Stream.transform 的用法ORM
- css3 transform與animation妙用CSSS3ORM
- 照片牆(transform/transition/z-index)ORMIndex
- css 3D transform變換CSS3DORM
- CSS動畫:animation、transition、transform、translateCSS動畫ORM
- CSS3 之 transform & transition & animationCSSS3ORM
- SVG transform變換深入理解SVGORM
- OpenCV-Python實戰(16)——人臉追蹤詳解OpenCVPython