為何很多地方要用傅里葉變換?
很多在時域看似不可能做到的數學操作,在頻域相反很容易,這就是需要傅里葉變換的地方。
尤其是從某條曲線中去除一些特定的頻率成分,這在工程上稱為濾波,是信號處理最重要的概念之一,只有在頻域才能輕松的做到。
幅值譜:頻率和幅值的關系。中心為頻率最小點。因此幅值譜中心部分代表的是低頻信息,即空間域的平緩的部分。越往外代表的是高頻信息,空間域的邊緣啊噪聲等
頻率:以正弦波為例,就是周期的倒數
幅值:周期內最大值
幅值高(幅值譜越亮的部分)代表像素越多。一幅圖像經過傅里葉變換之后一定是中心較亮,四周較暗(低頻像素多,高頻像素少),因為一般一幅圖像中高頻信息(邊緣等)是很少的,多的是背景。
"""
二維坐標系中向量點的圖示由於正交基(即坐標系)的建立, 可以寫成向量坐標(如(2,1))數值格式;同理已知坐標系和向量坐標可以變換推出圖示意的樣子。(這個類比很棒了)
傅里葉變換也是一樣:將連續的周期性函數寫成無數個正交的正(余)弦函數的和,其中引入了振幅(f, 周期函數的最大值),相位(q,即0時刻周期函數曲線的進入點),頻率(w,反應周期性大小)。
同坐標變換一樣,已知了這些相互正交的周期函數(即空間中一組完備的正交基),可以由傅里葉變換后的坐標結果(即f,w, q)反變換得到之前的圖示結果---即原始的那條周期性曲線。
變聲,美顏都可以用傅里葉變換及反變換得到。
比如美顏,一張人物圖片傅里葉變換后就是一張類似衍射圖的東西,然后低頻代表人物輪廓,高頻代表人物細節如皺紋等,我們只需要抹掉高頻,然后反變換回圖片空間即得到磨皮的結果。
變聲也是:發現嘈雜的聲音傅里葉變換后,發現有具有低頻的部分,以及僅高頻的部分,還有一些噪音。大腦自動發現了男聲處在低頻部分,女聲在高頻部分。
只要將一個變換后的聲音的低頻抹掉,再反變換回去就得到了女聲,同樣的根據某個人的變換后的頻率相位圖反變換就得到變聲。
世界上所有的信號都具有波粒二象性,耳朵接收聲波,眼睛接受光波,正是因為大腦能進行快速傅里葉變換處理信號,所以人類才這么高級方便。
"""
高通濾波,低通濾波是按頻率划分的。對於正弦曲線,振幅變化快就是高頻,變化慢就是低頻。那么對於圖像,像素值變化快就是高頻(噪聲啦,邊緣啦、邊緣及噪聲在局部像素值變化較大),像素值變化慢就是低頻。所以一幅圖像低頻較多,高頻較少。那么保留高頻就是高通濾波器(邊緣提取),保留低頻就是低通錄波器(圖像平滑)。
傅里葉變換將圖像轉換成幅值譜(magnitude_spectrum):按頻率從小到大由中心向四周擴散,幅值譜越亮說明像素越多,反之則越少。
上代碼:
1 import cv2 2 import numpy as np 3 import matplotlib.pyplot as plt 4 img=cv2.imread('../images/example_01.jpg',0) 5 # 高通濾波 numpy 用的多 6 # 正變換 7 f=np.fft.fft2(img) 8 fshift=np.fft.fftshift(f) 9 magnitude_spectrum=20*np.log(np.abs(fshift)) 10 11 12 plt.subplot(121),plt.imshow(img,cmap='gray'),plt.title('Input Image'),plt.xticks([]),plt.yticks([]) 13 plt.subplot(122),plt.imshow(magnitude_spectrum,cmap='gray'),plt.title('magnitude_spectrum') 14 plt.show()
上效果:
那么像提取圖像的邊緣就是去掉低頻保留高頻:先通過傅里葉正變換得到幅值譜,去掉低頻像素,然后再通過傅里葉逆變換得到圖像邊緣。上代碼:
1 import cv2 2 import numpy as np 3 import matplotlib.pyplot as plt 4 # img=cv2.imread('../images/can.jpg',0) 5 # img=cv2.imread('../images/qin.jpg',0) 6 img=cv2.imread('../images/example_01.jpg',0) 7 # 高通濾波 numpy 用的多 8 # 正變換 9 f=np.fft.fft2(img) 10 fshift=np.fft.fftshift(f) 11 magnitude_spectrum=20*np.log(np.abs(fshift)) 12 13 14 rows,cols=img.shape 15 crow,ccol=int(rows/2),int(cols/2) 16 print('img.shape',img.shape) 17 # 低頻過濾 18 fshift[(crow-30):(crow+30),(ccol-30):(ccol+30)]=0 19 #逆變換 20 f_ishift=np.fft.ifftshift(fshift) 21 img_back=np.abs(np.fft.ifft2(f_ishift)) 22 23 24 plt.subplot(121),plt.imshow(img,cmap='gray'),plt.title('Input Image'),plt.xticks([]),plt.yticks([]) 25 plt.subplot(122),plt.imshow(img_back,cmap='gray'),plt.title('img_back'),plt.xticks([]),plt.yticks([]) 26 plt.show()
上效果:
那么均值濾波,高斯濾波,sobel,scharr,拉普拉斯濾波器是低通濾波器還高通濾波器呢?我們通過幅值譜來判
斷,上代碼:
1 import cv2 2 import numpy as np 3 from matplotlib import pyplot as plt 4 5 6 # simple averaging filter without scaling parameter 7 # 低通 8 mean_filter = np.ones((3,3)) 9 10 11 # creating a guassian filter 12 # 低通 13 x = cv2.getGaussianKernel(5,10) 14 gaussian = x*x.T 15 16 17 # different edge detecting filters 18 # scharr in x-direction 19 # 高通 20 scharr = np.array([[-3, 0, 3], 21 [-10,0,10], 22 [-3, 0, 3]]) 23 # sobel in x direction 24 # 高通 25 sobel_x= np.array([[-1, 0, 1], 26 [-2, 0, 2], 27 [-1, 0, 1]]) 28 # sobel in y direction 29 # 高通 30 sobel_y= np.array([[-1,-2,-1], 31 [0, 0, 0], 32 [1, 2, 1]]) 33 # laplacian 34 # 高通 35 laplacian=np.array([[0, 1, 0], 36 [1,-4, 1], 37 [0, 1, 0]]) 38 39 40 filters = [mean_filter, gaussian, laplacian, sobel_x, sobel_y, scharr] 41 filter_name = ['mean_filter', 'gaussian','laplacian', 'sobel_x', \ 42 'sobel_y', 'scharr_x'] 43 fft_filters = [np.fft.fft2(x) for x in filters] 44 fft_shift = [np.fft.fftshift(y) for y in fft_filters] 45 mag_spectrum = [np.log(np.abs(z)+1) for z in fft_shift] 46 47 48 for i in range(6): 49 plt.subplot(2,3,i+1),plt.imshow(mag_spectrum[i],cmap = 'gray') 50 plt.title(filter_name[i]), plt.xticks([]), plt.yticks([]) 51 plt.show()
上效果:
前面討論過,幅值譜中間為低頻,四周為高頻且越亮像素越多,就是被濾波器保存下來了。不難發現,均值與高斯濾波器幅值譜中間亮,為低通濾波器(平滑),拉普拉斯、sobel、scharr四周較亮為高通濾波器(邊緣提取),邊緣提取又分垂直邊緣與水平邊緣~這個從圖上看就一目了然啦。