通过Numpy和OpenCV两种方法都可实现傅里叶变换。本节介绍OpenCV方法。
OpenCV提供了函数cv2.dft()
和cv2.idft()
来实现傅里叶变换和逆傅里叶变换。
实现傅里叶变换
函数cv2.dft()
的语法格式为:
返回结果 = cv2.dft(原始图像, 转换标识)
- 对于参数“原始图像”,要首先使用
np.float32()
函数将图像转换成np.float32格式 - “转换标识”的值通常为
cv2.DFT_COMPLEX_OUTPUT
,用来输出一个复数阵列
cv2.dft返回的值是双通道的,第1个通道是结果的实数部分,第2个通道是结果的虚数部分。
经过cv2.dft()
的变换后,得到了原始图像的频谱信息。此时,零频率分量并不在中心位置,为了处理方便,需要将其移到中心位置。可以用numpy.fft.fftshift()
实现。
dftshift = np.fft.fftshift(dft)
经过这些处理之后,频谱图像还是一个由实部和虚部构成的值,要将其显示出来,还要进一步处理。
函数cv2.magnitude()
可以计算频谱信息的幅度。语法:
返回值 = cv2.magnitude(参数1, 参数2)
- 参数1:浮点型x坐标值,也就是实部
- 参数2:浮点数y的坐标值,也就是虚部
得到频谱信息的幅度后,通常还要对幅度值做进一步的转换,以便将频谱信息以图像的形式表达出来。
简单说,就是将幅度值映射到灰度图像的灰度空间[0,255]内,使其以灰度图像的形式展示。使用公式:
result = 20 * np.log(cv2.magnitude(实部, 虚部))
例1:用OpenCV函数对图像进行傅里叶变换,并展示其频谱信息。
import numpy as np
import cv2
import matplotlib.pyplot as plt
img = cv2.imread(r'E:\Blog\OpenCV\Process\fisher.png',0)
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(121),plt.imshow(img,cmap='gray')
plt.title('ORIGINAL'),plt.axis('off')
plt.subplot(122),plt.imshow(result,cmap='gray')
plt.title('RESULT'),plt.axis('off')
plt.show()
运行结果:
实现逆傅里叶变换
在OpenCV中,使用函数cv2.idft()
实现逆傅里叶变换,该函数是傅里叶函数cv2.dft()
的逆函数:
返回结果 = cv2.idft(原始数据)
得到返回结果之后,还需要将频谱从中心移回到原来的位置:
结果 = numpy.fft.ifftshift()
需要注意,在进行逆傅里叶变换后,得到的值仍旧是复数,需要使用函数cv2.magnitude()
计算其幅值。
例:用OpenCV函数对图像进行傅里叶变换、逆傅里叶变换,并展示原始图像及经过逆傅里叶变化后得到的图像。
import numpy as np
import cv2
import matplotlib.pyplot as plt
img = cv2.imread(r'E:\Blog\OpenCV\Process\fisher.png',0)
dft = cv2.dft(np.float32(img),flags=cv2.DFT_COMPLEX_OUTPUT)
dftShift = np.fft.fftshift(dft) #将频谱移到中心
idftShift = np.fft.ifftshift(dftShift) #将频谱移回原来的位置
imag = cv2.idft(idftShift)
imag = cv2.magnitude(imag[:,:,0],imag[:,:,1])
plt.subplot(121),plt.imshow(img,cmap='gray')
plt.title('ORIGINAL'),plt.axis('off')
plt.subplot(122),plt.imshow(imag,cmap='gray')
plt.title('RESULT'),plt.axis('off')
plt.show()
运行结果:
低通滤波示例
在一幅图像内,低频信号对应图像内变化缓慢的灰度分量。例如,在一幅大草原的图像中,低频信号对应着颜色趋于一致的广袤草原。低通滤波器让高频信号衰减而让低频信号通过。经滤波后,图像会变得模糊。
构造一个中心位置60X60的低通滤波器:
rows, cols = img.shape
crow, ccol = int(rows/2), int(cols/2)
mask = np.zeros((rows,cols,2),np.uint8)
mask[crow-30:crow+30, ccol-30:ccol+30] = 1
然后,将其与频谱图像进行运算,实现低通滤波:
fShift = dftShift * mask
例:使用函数cv2.dft()
对图像进行傅里叶变换,得到其频谱图像。然后,在频域内将其高频分量的值处理为0,实现低通滤波。最后,对图像进行逆傅里叶变换,得到恢复的原始图像。观察傅里叶变换前后图像的差异。
import numpy as np
import cv2
import matplotlib.pyplot as plt
img = cv2.imread(r'E:\Blog\OpenCV\Process\fisher.png',0)
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-30:crow+30,ccol-30:ccol+30] = 1
fshift = dftShift * mask
idftShift = np.fft.ifftshift(fshift) #将频谱移回原来的位置
imag = cv2.idft(idftShift)
imag = cv2.magnitude(imag[:,:,0],imag[:,:,1])
plt.subplot(121),plt.imshow(img,cmap='gray')
plt.title('ORIGINAL'),plt.axis('off')
plt.subplot(122),plt.imshow(imag,cmap='gray')
plt.title('RESULT'),plt.axis('off')
plt.show()
运行结果: