14-傅里叶变换的代码实现

一、numpy实现傅里叶变换和逆傅里叶变换

1.numpy实现傅里叶变换
numpy.fft.fft2
实现傅里叶变换,返回一个复数数组(complex ndarray),也就是频谱图像
numpy.fft.fftshift
将零频率分量移到频谱中心(将左上角的低频区域,移到中心位置)

 20*np.log(np.abs(fshift))
设置频谱的范围。可以理解为,之前通过傅里叶变换得到复数的数组,是不能通过图像的方法展示出来的,需要转换为灰度图像(映射到[0,255]区间)

需要注意的是
1> 傅里叶得到低频、高频信息,针对低频、高频处理能够实现不同的目的
2> 傅里叶过程是可逆的,图像经过傅里叶变换、逆傅里叶变换后,能够恢复到原始图像
3> 在频域对图像进行处理,在频域的处理会反映在逆变换图像上

# 将绘制的图显示在窗口
%matplotlib qt5

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

img = cv2.imread(r"image\lena.bmp",cv2.IMREAD_GRAYSCALE)

# 傅里叶变换
f = np.fft.fft2(img)
# 移动中心位置
fshift = np.fft.fftshift(f)
# 调整值范围
result = 20*np.log(np.abs(fshift))

plt.subplot(1,2,1)
plt.imshow(img,cmap=plt.cm.gray)
plt.title("original")
plt.axis("off")

plt.subplot(1,2,2)
plt.imshow(result,cmap=plt.cm.gray)
plt.title("result")
plt.axis("off")

plt.show()

傅里叶变换的频谱图像:

 

2.numpy实现逆傅里叶变换
numpy.fft.ifft2
实现逆傅里叶变换,返回一个复数数组(complex ndarray)
numpy.fft.ifftshift
fftshift函数的逆函数,将中心位置的低频,重新移到左上角
iimg = np.abs(逆傅里叶变化结果)
设置值的范围,映射到[0,255]区间

# 将绘制的图显示在窗口
%matplotlib qt5

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

img = cv2.imread(r"image\boat.bmp",cv2.IMREAD_GRAYSCALE)

# 傅里叶变换
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)
# 逆傅里叶变换
ishift = np.fft.ifftshift(fshift)
iimg = np.fft.ifft2(ishift)
iimg = np.abs(iimg)

plt.subplot(1,2,1)
plt.imshow(img,cmap=plt.cm.gray)
plt.title("original")
plt.axis("off")

plt.subplot(1,2,2)
plt.imshow(iimg,cmap=plt.cm.gray)
plt.title("iimg")
plt.axis("off")

plt.show()

将一副图像,进行傅里叶变换和逆傅里叶变换后,进行对比(一样的)

实例:通过numpy实现高通滤波,保留图像的边缘信息

获取图像的形状
rows,cols = img.shape
获取图像的中心点
crow,ccol = int(rows/2),int(cols/2)
将频谱图像的中心区域(低频区域)设置为0(黑色)
fshift[crow-30:crow+30,ccol-30:ccol+30] = 0

# 将绘制的图显示在窗口
%matplotlib qt5

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

img = cv2.imread(r"image\boat.bmp",cv2.IMREAD_GRAYSCALE)

# 傅里叶变换
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)

# 高通滤波
rows,cols = img.shape
crow,ccol = int(rows/2),int(cols/2)
fshift[crow-30:crow+30,ccol-30:ccol+30] = 0

# 逆傅里叶变换
ishift = np.fft.ifftshift(fshift)
iimg = np.fft.ifft2(ishift)
iimg = np.abs(iimg)

plt.subplot(1,2,1)
plt.imshow(img,cmap=plt.cm.gray)
plt.title("original")
plt.axis("off")

plt.subplot(1,2,2)
plt.imshow(iimg,cmap=plt.cm.gray)
plt.title("iimg")
plt.axis("off")

plt.show()

使用numpy实现高通滤波的实验结果:

 二、opencv实现傅里叶变换和逆傅里叶变换

1.opencv实现傅里叶变换

返回结果 = cv2.dft(原始图像,转换标识)
1> 返回结果:是双通道的,第一个通道是结果的实数部分,第二个通道是结果的虚数部分
2> 原始图像:输入图像要首先转换成np.float32(img)格式
3> 转换标识:flags = cv2.DFT_COMPLEX_OUTPUT,输出一个复数阵列

numpy.fft.fftshift
将零频率分量移到频谱中心(将左上角的低频区域,移到中心位置)

调整频谱的范围,将上面频谱图像的复数数组,转换为可以显示的灰度图像(映射到[0,255]区间)
返回值 = 20*np.log(cv2.magnitude(参数1,参数2))
1> 参数1:浮点型X坐标值,也就是实部
2> 参数2:浮点型Y坐标值,也就是虚部

# 将绘制的图显示在窗口
%matplotlib qt5

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

img = cv2.imread(r"image\lena.bmp",cv2.IMREAD_GRAYSCALE)

# 傅里叶变换
dft = cv2.dft(np.float32(img),flags = cv2.DFT_COMPLEX_OUTPUT)
# 移动中心位置
dftShift = np.fft.fftshift(dft)
# 调整频谱的范围
result = 20*np.log(cv2.magnitude(dftShift[:,:,0],dftShift[:,:,1]))

plt.subplot(1,2,1)
plt.imshow(img,cmap=plt.cm.gray)
plt.title("original")
plt.axis("off")

plt.subplot(1,2,2)
plt.imshow(result,cmap=plt.cm.gray)
plt.title("result")
plt.axis("off")

plt.show()

傅里叶变换的频谱图像:

2.opencv实现逆傅里叶变换
返回结果 = cv2.idft(原始数据)
1> 返回结果:取决于原始数据的类型和大小
2> 原始数据:实数或者复数均可

numpy.fft.ifftshift
fftshift函数的逆函数,将中心位置的低频,重新移到左上角

调整频谱的范围,映射到[0,255]区间
返回值 = cv2.magnitude(参数1,参数2)
1> 参数1:浮点型X坐标值,也就是实部
2> 参数2:浮点型Y坐标值,也就是虚部

 

# 将绘制的图显示在窗口
%matplotlib qt5

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

img = cv2.imread(r"image\lena.bmp",cv2.IMREAD_GRAYSCALE)

# 傅里叶变换
dft = cv2.dft(np.float32(img),flags = cv2.DFT_COMPLEX_OUTPUT)
dftShift = np.fft.fftshift(dft)

# 逆傅里叶变换
ishift = np.fft.ifftshift(dftShift)
iimg = cv2.idft(ishift)
iimg = cv2.magnitude(iimg[:,:,0],iimg[:,:,1])

plt.subplot(1,2,1)
plt.imshow(img,cmap=plt.cm.gray)
plt.title("original")
plt.axis("off")

plt.subplot(1,2,2)
plt.imshow(iimg,cmap=plt.cm.gray)
plt.title("inverse")
plt.axis("off")

plt.show()

将一副图像,进行傅里叶变换和逆傅里叶变换后,进行对比(一样的)

 实例:通过opencv实现低通滤波,模糊一副图像

 获取图像的形状
rows,cols = img.shape
获取图像的中心点
crow,ccol = int(rows/2),int(cols/2)
生成一个原图像大小的全零矩阵(黑色)
mask = np.zeros((rows,cols,2),np.uint8),这里的(rows,cols,2)是因为dftShift频谱图像的形状是(rows,cols,2),双通道的
将全零矩阵(黑色)的中心区域设置为1(白色),也就是mask矩阵
mask[crow-30:crow+30,ccol-30:ccol+30] = 1
频谱图像 = 原频谱图像 * mask矩阵
fShift = dftShift*mask

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

img = cv2.imread(r"image\lena.bmp",cv2.IMREAD_GRAYSCALE)

# 傅里叶变换
dft = cv2.dft(np.float32(img),flags=cv2.DFT_COMPLEX_OUTPUT)
dftShift = np.fft.fftshift(dft)

# 低通滤波
rows,cols = img.shape
crow,ccol = int(rows/2),int(cols/2)
mask = np.zeros((rows,cols,2),np.uint8)
mask[crow-50:crow+50,ccol-50:ccol+50] = 1
fShift = dftShift*mask

# 逆傅里叶变换
ishift = np.fft.ifftshift(fShift)
iimg = cv2.idft(ishift)
iimg = cv2.magnitude(iimg[:,:,0],iimg[:,:,1])

plt.subplot(1,2,1)
plt.imshow(img,cmap=plt.cm.gray)
plt.title("original")
plt.axis("off")

plt.subplot(1,2,2)
plt.imshow(iimg,cmap=plt.cm.gray)
plt.title("inverse")
plt.axis("off")

plt.show()

使用opencv实现高通滤波的实验结果:

 

拓展:什么什么是低频、高频

低频:
1> 低频对应图像内变化缓慢的灰度分量。例如,在一副大草原的图像中,低频对应着广袤的颜色趋于一致的草原
2> 衰减高频而通过低频,低通滤波器,将模糊一副图像
高频:
1> 高频对应图像内变化越来越快的灰度分量,是由灰度的尖锐过度造成的。例如,在一副大草原图像中,其中狮子的边缘等信息
2> 衰减低频而通过高频,高通滤波器,将增强尖锐的细节,但是会导致图像的对比图降低

 

什么是滤波

1> 接受(通过)或拒绝一定频率的分量
2> 通过低频的滤波器称为低通滤波器
3> 通过高频的滤波器称为高通滤波器

 

频域滤波

修改傅里叶变换的低频或者高频信息,以达到特殊目的,然后计算IDFT(逆傅里叶变换)返回到图像域。特殊目的通常是图像增强、图像去噪、边缘检测、特征提取、压缩、加密等

 

 

posted @ 2021-09-27 16:24  马铃薯1  阅读(1378)  评论(0编辑  收藏  举报