傅里叶变换 高通滤波 低通滤波
为何很多地方要用傅里叶变换?
很多在时域看似不可能做到的数学操作,在频域相反很容易,这就是需要傅里叶变换的地方。
尤其是从某条曲线中去除一些特定的频率成分,这在工程上称为滤波,是信号处理最重要的概念之一,只有在频域才能轻松的做到。
幅值谱:频率和幅值的关系。中心为频率最小点。因此幅值谱中心部分代表的是低频信息,即空间域的平缓的部分。越往外代表的是高频信息,空间域的边缘啊噪声等
频率:以正弦波为例,就是周期的倒数
幅值:周期内最大值
幅值高(幅值谱越亮的部分)代表像素越多。一幅图像经过傅里叶变换之后一定是中心较亮,四周较暗(低频像素多,高频像素少),因为一般一幅图像中高频信息(边缘等)是很少的,多的是背景。
"""
二维坐标系中向量点的图示由于正交基(即坐标系)的建立, 可以写成向量坐标(如(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四周较亮为高通滤波器(边缘提取),边缘提取又分垂直边缘与水平边缘~这个从图上看就一目了然啦。