参考伯乐在线的一篇文章,做图像的傅里叶变换。在PyCharm中安装cv2时出错,如下图:
根据提示建议在命令行中执行命令pip install cv2也依然是No matching distribution found for cv2.注意到pip可以更新,但这不是问题所在。然而,将相同的py文件添加在venv文件夹中没有在import时报错。venv是virtual environment的缩写。查到的资料是这样的:每个应用需要的运行环境经常不同(包的版本/python版本等),所以需要用virtualenv创建一套属于这个程序的“隔离”的Python运行环境。而且系统Python环境不会被修改,保持干净。可打包后移动目录,但无法跨平台。注意当前项目的python解释器是哪个,一定要设置成虚拟环境中的python。virtualenv 创建的虚拟环境与主机的 Python 环境完全无关, 你主机配置的库不能在 virtualenv 中直接使用。 你需要在虚拟环境中利用 pip install 再次安装配置后才能使用。
注意到解释器也根据工程有不同的版本,区别在安装了哪些模块。当在venv中换了一个解释器,cv2依然安装失败,但程序的结果正确。
#!/usr/bin/env.python
import cv2 as cv
import numpy as np
from matplotlib import pyplot as pltimg = cv.imread('Joseph_Fourier_250.jpg', 0)
f = np.fft.fft2(img) # 快速傅里叶变换算法得到频率分布
fshift = np.fft.fftshift(f) # 默认结果中心点位置是在左上角,转移到中间位置fimg = np.log(np.abs(fshift)) # fft 结果是复数,求绝对值结果才是振幅
fimg0=np.log(np.abs(f))# 展示结果
plt.subplot(131), plt.imshow(img, 'gray'), plt.title('Original Fourier')
plt.subplot(132), plt.imshow(fimg0, 'gray'), plt.title('Fourier Fourier') #中心位移之前的频谱
plt.subplot(133), plt.imshow(fimg, 'gray'), plt.title('Fourier Fourier-shift') #中心位移之后的频谱,但坐标轴没有变化,此时中心的频率应该为0
plt.show()
上面的代码中提到将频谱中心移动。具体操作通常在进行傅里叶变换之前用(-1)^(x+y)乘以输入的图像函数,这样就可以将傅里叶变换的原点F(0,0)移到(M/2,N/2)上。将频谱移频到圆心除了可以清晰地看出图像频率分布以外,还有一个好处,它可以分离出有周期性规律的干扰信号,比如正弦干扰,一副带有正弦干扰,移频到原点的频谱图上可以看出除了中心以外还存在以某一点为中心,对称分布的亮点集合,这个集合就是干扰噪音产生的,这时可以很直观的通过在该位置放置带阻滤波器消除干扰.
傅里叶变换的本质是将信号分解为一系列正弦曲线的叠加。正弦曲线有三个属性:频率;幅值;相位。我们看到傅里叶变换的每一项(对每对频率u,v,F(u,v)的值)是由f(x)函数所有值的和组成。f(x)的值与各种频率的正弦值和余弦值相乘。如果正好有相同的频率分量,相乘得一个值,即幅度。如果没有特定的频率分量,乘积就应该是0,其实傅里叶变换就是一个正交变换。
幅值描述了对比度,图像最亮处和最暗处的的差值。在频谱中由亮度表示,亮度越高表示对比度越大。
频率是空域上亮度改变的频率。傅里叶变换得到的频谱,频率从0到奈奎斯特频率(数字图像可被编码的最高频率,与分辨率、像素大小有关)。频率为0的分量就是直流DC分量,因为亮度不可能取负数,所以所有的图像的直流分量都不为0.
相位代表正弦曲线相对于原始状态是如何移动的(偏移量)。
I=imread('sin3.PNG');figure;
subplot(1,2,1),imshow(I),title('原图');
I=rgb2gray(I);%转换为灰度图I=im2double(I);%转换成double类型,图像灰度值从0~255变成0~1F=fft2(I);F=fftshift(F);%象限变换F=abs(F);
%F=real(F);有的程序是求摸,有的是求实部T=log(F+1);%保证取对数后还是正数subplot(1,2,2),imshow(T,[]),title('Fourier');%imshow(T)只会显示[0,1]的值,而imshow(T,[]) 会根据灰度图的数值范围来显示图像
频谱图中心点表示DC直流分量,频谱图以中心点中心对称。如下图,虽然只有一种频率分量,但却有三个亮点。截图来自参考链接1,链接1给的图是gif格式的,查了一下才知道gif其实也是一种无损压缩格式,GIF(Graphics Interchange Format)的原义是“图像互换格式”,只不过可以将多幅图像保存到同一个文件中的特点使它在逐幅图像读取到屏幕上时可以显示为动图。刚才的程序直接读取gif文件和后缀改为jpg的都报错,openCV不支持gif的解码(好像是因为gif中LZW算法专利的原因),可以用第三方库FreeImage读取,这里我用了截图软件才将频谱画出来,如下面的右半边,但是和刚才的分析和左边的实验结果不同,右边的图是一条直线,且频谱图的“背景色”是白色。当用如上的matlab画频谱图时,颜色与python画出的图正好相反。断点调试发现其中fimg变量出现大量的-inf,造成了“背景”全白,同时注意到控制台出现提示divid by zero,判断出是在取对数过程中造成了负无穷,根matlab一样在取对数之前+1进行修正,即得到了和matlab一样的结果。opencv也支持图像傅里叶变换,感兴趣可以戳这里。
既然“背景色”的问题已经解决了,还有一个问题是自己频谱的实验结果是一条线而Fouier Transform是三个点。参考链接在最后其实就是在解释这个问题,其实这就是“振铃效应”,也就是“吉伯斯现象”。仔细观察其实输入的黑白条纹图是渐变的,那么它是按照什么规律渐变的呢,答案就是正余弦函数,如果完全按照余弦函数渐变,它对应的频谱就是一个单频点,考虑到正负对称和直流分量就是三个点。这里我一开始每注意到渐变的因素,因为只要是间隔一样即只存在一个频率,还给正科解释错了。
但是,当黑白条纹没有做到像余弦函数一样平滑时频谱会怎么样呢,极端一点,我们考虑完全没有渐变的黑白条纹,黑条白条之间没有过渡,这对应一维的矩形。我们知道矩形需要无穷多个余弦函数才能拟合,而且需要很多的高频分量,在二维的黑白跳变的图像中,它的频谱就无穷多个“三点”的集合。如下图,从1到7,条纹越来越密集,频率也越来越大(分别是基准频率的3、5、7倍),对应的频谱中点的坐标值也越来越大,间隔越来越大。当把不同频率的条纹图叠加起来,它们的频谱也是对应频谱的叠加。可以观察到,随着高频分量的叠加,条纹亮度图中间的白条越来越突出,其他地方越来越成为黑色的背景,频谱图也越来越接近于一条直线。事实上,这就解释了最后一幅图的频谱图为什么是一条直线。
再分析上面两种频谱。左边的频谱看似有四条线,其实只是两条垂直的线,分别代表横向的亮度变化和纵向的亮度变化,但是都不经过中心点,是因为原图带来的相位偏移。结合右边的情况,频谱与亮度变化发生的具体位置是无关的。
看,只是最熟悉的傅里叶变换在实际运用在离散、二维情况下都出了这么多情况,就像正科的老师说的,越读书会越觉得什么都不会。纸上得来终觉浅啊,继续努力!
Reference:
1.http://cns-alumni.bu.edu/~slehar/fourier/fourier.html#filtering
2.https://blog.csdn.net/abcjennifer/article/details/7622228
3.http://blog.jobbole.com/94144/
4.https://blog.csdn.net/keith_bb/article/details/53389819