图像处理(十):傅里叶变换

图像处理笔记总目录


一、在opencv中实现图像的傅里叶变换

傅里叶变换的物理意义是将图像的灰度分布函数变换为图像的频率分布函数;
傅里叶逆变换是将图像的频率分布函数变换为灰度分布函数。

正变换:dft = cv2.dft(src, dst=None)

参数:

  • src: 输入图像,要转换成np.float32格式
  • dst:参数是可选的, 决定输出数组的大小。默认输出数组的大小和输入图像大小一样。如果输出结果比输入图像大,输入图像就需要在进行变换前补 0。如果输出结果比输入图像小的话,输入图像就会被切割。

返回:

  • dft: 傅里叶变换后的结果,有两个通道,第一个通道是结果的实数部分,第二个通道是结果的虚数部分。我们需要在此基础上计算傅里叶变换的频谱和相位。

逆变换:img = cv.idft(dft)

参数:

  • dft: 图像的频域表示

返回:

  • img: 图像的空域表示

实现:

import numpy as np 
import cv2
from matplotlib import pyplot as plt

# 1 读取图像
img = cv2.imread('../image/deer.jpeg',0)

# 2 傅里叶变换
# 2.1 正变换
dft = cv2.dft(np.float32(img),flags = cv2.DFT_COMPLEX_OUTPUT) 
# 2.2 频谱中心化
dft_shift = np.fft.fftshift(dft)
# 2.3 计算频谱和相位谱
mag, angle = cv2.cartToPolar(dft_shift[:,:,0], dft_shift[:,:,1], angleInDegrees=True)
mag=20*np.log(mag)

# 3 傅里叶逆变换
# 3.1 反变换
img_back = cv2.idft(dft)
# 3.2 计算灰度值
img_back = cv2.magnitude(img_back[:,:,0],img_back[:,:,1])

# 4 图像显示
plt.figure(figsize=(10,8))
plt.subplot(221),plt.imshow(img, cmap = 'gray') 
plt.title('输入图像'), plt.xticks([]), plt.yticks([]) 
plt.subplot(222),plt.imshow(mag, cmap = 'gray')
plt.title('频谱'), plt.xticks([]), plt.yticks([]) 
plt.subplot(223),plt.imshow(angle, cmap = 'gray')
plt.title('相位谱'), plt.xticks([]), plt.yticks([])
plt.subplot(224),plt.imshow(img_back, cmap = 'gray')
plt.title('逆变换结果'), plt.xticks([]), plt.yticks([])
plt.show()

在这里插入图片描述

二、高通和低通滤波器

我们知道,图像在经过傅里叶变换后,经频谱中心化后,从中间到外面,频率上依次是从低频到高频的。那么我们假设把中间规定一小部分去掉,是不是相对于把低频信号去掉了呢?这也就是相当于进行了高通滤波。

这个滤波模板如下图所示:

在这里插入图片描述
其中黑色部分为0,白色部分为1,我们将这个模板与图像的傅里叶变换相与就实现了高通滤波。如下所示:

import numpy as np 
import cv2
from matplotlib import pyplot as plt

# 1 读取图像
img = cv2.imread('../image/deer.jpeg',0)

# 2 设计高通滤波器(傅里叶变换结果中有两个通道,所以高通滤波中也有两个通道)
rows,cols = img.shape
mask = np.ones((rows,cols,2),np.uint8)
mask[int(rows/2)-30:int(rows/2)+30,int(cols/2)-30:int(cols/2)+30,:] = 0

# 3 傅里叶变换
# 3.1 正变换
dft = cv2.dft(np.float32(img),flags = cv2.DFT_COMPLEX_OUTPUT) 
# 3.2 频谱中心化
dft_shift = np.fft.fftshift(dft)
# 3.3 滤波
dft_shift = dft_shift * mask
# 3.4 频谱去中心化
dft_shift = np.fft.fftshift(dft_shift)

# 4 傅里叶逆变换
# 4.1 反变换
img_back = cv2.idft(dft_shift)
# 4.2 计算灰度值
img_back = cv2.magnitude(img_back[:,:,0],img_back[:,:,1])
plt.subplot(121),plt.imshow(img, cmap = 'gray') 
plt.title('输入图像'), plt.xticks([]), plt.yticks([]) 
plt.subplot(122),plt.imshow(img_back, cmap = 'gray')
plt.title('高通滤波结果'), plt.xticks([]), plt.yticks([])
plt.show()

在这里插入图片描述

从结果中可以看出,高通滤波器有利于提取图像的轮廓,图像的轮廓或者边缘或者一些噪声处,灰度变化剧烈,那么在把它们经过傅里叶变换后。就会变成高频信号(高频是捕捉细节的),所以在把图像低频信号滤掉以后剩下的自然就是轮廓了。

现在我们看下低通滤波的效果,构造一个低通滤波器很简单,只要把上述模板中的1改为0,0改为1即可。把设计高通滤波器部分的代码改成如下所示:

rows,cols = img.shape
mask = np.zeros((rows,cols,2),np.uint8)
mask[int(rows/2)-30:int(rows/2)+30,int(cols/2)-30:int(cols/2)+30,:] = 1

低通滤波的效果如下图所示:
在这里插入图片描述
从结果中可看到低通滤波后图像轮廓变模糊了,图像的大部分信息基本上都保持了。图像的主要信息都集中在低频上,所以结果会如上图所示。

三、带通和带阻滤波器

我们把高通和低通的一部分结合在模板中就形成了带通滤波器,它允许一定频率范围信号通过, 但减弱(或减少)频率低于下限截止频率和高于上限截止频率的信号的通过,如下图所示:
在这里插入图片描述
还是以理想的带通滤波器演示如下,将构建的滤波的代码修改如下:

rows,cols = img.shape
mask1 = np.ones((rows,cols,2),np.uint8)
mask1[int(rows/2)-8:int(rows/2)+8,int(cols/2)-8:int(cols/2)+8] = 0
mask2 = np.zeros((rows,cols,2),np.uint8)
mask2[int(rows/2)-80:int(rows/2)+80,int(cols/2)-80:int(cols/2)+80] = 1
mask = mask1*mask2

在这里插入图片描述
这就是带通的效果,它既能保留一部分低频,也能保留一部分高频。至于保留多少,根据需求选择就可以了。

带阻滤波器减弱(或减少)一定频率范围信号, 但允许频率低于下限截止频率和高于上限截止频率的信号的通过,如下示:
在这里插入图片描述

在代码中将设计滤波器部分改为如下所示:

mask = np.ones((rows,cols,2),np.uint8)
mask[int(rows/2)+80:int(rows/2)+150,int(cols/2)-150:int(cols/2)+150] = 0
mask[int(rows/2)-150:int(rows/2)-80,int(cols/2)-150:int(cols/2)+150] = 0
mask[int(rows/2)-150:int(rows/2)+150,int(cols/2)+80:int(cols/2)+150] = 0
mask[int(rows/2)-150:int(rows/2)+150,int(cols/2)-150:int(cols/2)-80] = 0
plt.imshow(mask[:,:,1],cmap=plt.cm.gray)

在这里插入图片描述
从结果中可看到带阻滤波器保持了原图像的大部分信息,图像的主要信息都集中在低频上,而边缘轮廓信息都在高频位置。带阻滤波器滤除了中频信息,保留了低频和高频信息,所以对图像的信息破坏是比较小的。

猜你喜欢

转载自blog.csdn.net/weixin_45707277/article/details/122887731