目录
1 概念
我们引入一个概念
- 时域分析,我们9:00工作,12:00吃饭,以时间为节点进行分析,这个叫时域分析
- 频域分析,我们一周上五天班,一周吃7次午饭,吃午饭的频率要比上班的频率高,以时间发生的频率进行分析,这个叫频域分析
任何的周期函数都可以通过若干正弦波堆叠出来
我们观察上面这张图,在频率方向上频率值越大,正弦波的频率就越高(周期越短,峰值越低),我们就可以以频率值为x,峰值为y画出频域图像,时间方向就是正常时间对应的值
我们再引入四个概念
- 低频:灰度值变化缓慢的地方
- 高频:灰度值变化剧烈的地方,例如边界
- 低通滤波器:只保留低频,会使图像变得模糊
- 高通滤波器:只保留高频,会使图像细节(边界)增强
下面是傅里叶变换的方法
- cv2.dft()是傅里叶变换,变换之后图像无法展示出来,所以我们要再使用cv2.idft()转换回来
- 傅里叶变换后低频区域会再左上角,为了处理方便我们要使用shift将低频区域转换到中心
- 第三点是返回结果有实部和虚部,需要使用cv2.idft转换成像素值才能展示出来
计算上就比较复杂了,我们专注于代码上的实现,我贴一下公式,如果有想法可以去了解一下
cv2.dft() 从时域图像转换为频域图像
cv2.idft() 从频域图像转换为时域图像
2 代码实现
用到新的的API如下
- cv2.dft() 由时域图转为频域图
- cv2.idft() 由频域图转为时域图
- np.float32() 将图像转为float32格式
- np.fft.fftshift() 将低频区域从左上角移动到中心
- np.fft.fftshift() 将低频区域从中心移动到左上角
- cv2.magnitude() 处理频域图像的实部与虚部
2.1 全部滤波
导入包后我们读入灰度图,然后转换为np.float32格式
之后使用cv2.dft进行傅里叶变换
这个flags就是用来控制输入与输出的,现在我们要输出傅里叶变换,所以选择OUTPUT这个参数
把低频值转换到中间
我们此时查看一下dft_shift的变量类型与形状
发现是numpy.ndarray类型,456*823,这个是图片的大小,两通道(实部与虚部)
使用cv2.magnitude()计算频域图上的幅值,也就是频域图上的坐标y
我们可以明显观察到频谱图的幅值是没有办法在时域图中展示的(超过了255),所以我们下面要用np.log将其转化为时域图
- *20的原因是np.log直接返回的值太小,在这里规定将返回的值乘20
之后就可以将图像展示出来了
在中间最亮的点频率是最低的,越往外发散频率越高
2.2 低通滤波
低通滤波就是把低频区域进行滤波,我们使用掩膜排除掉高频区域(四周),只过滤低频区域(中间)
一直到转移中心点之前都是一样的
我们获取图像的行与列,之后获取行与列的中心位置
然后我们创建只保留中心的掩膜,中心区域为1作为图像的系统可以保留图像频率值,其余区域置为0,最终乘积也会是0,我们当前的区域的中心区域60*60
之后我们将频域图与掩膜相乘进行过滤
现在我们得到了新的频谱图,我们要将其返回成我们现在可以看的图,上面的fftshift步骤把低频区域从左上角移动到了中心,现在我们要变成可以看的图就需要把低频区域从中心移动回左上角
之后我们使用idft将图片变回时域图
此时返回的结果还是实部与虚部结合的图像,所以还不能看,下面我们在计算峰值
- 由于已经转换为可见图像了,所以我们就不需要20*np.log()的操作了
下面就可以把图像显示出来了
由于进行的是低通滤波,屏蔽高频区域,我们明显看出图像模糊了
2.3 高通滤波
我们只需要将掩膜换掉即可
使用全1数组,把中心掏成0就可以了
我们可以发现图像的细节(边界)得到了增强