前言
在前一篇的博文中,我们详细讲解了傅里叶变换的原理以及使用Numpy库实现傅里叶变换。但是其实OpenCV有直接实现傅里叶变换的函数。
在OpenCV中,我们通过cv2.dft()来实现傅里叶变换,使用cv2.idft()来实现逆傅里叶变换。两个函数的定义如下:
cv2.dft(原始图像,转换标识)
这里的原始图像必须是np.float32格式。所以,我们首先需要使用cv2.float32()函数将图像转换。而转换标识的值通常为cv2.DFT_COMPLEX_OUTPUT,用来输出一个复数阵列。
经过cv2.dft()函数的变换后,我们会得到原始图像的频谱信息。此时零分量与Numpy库实现一样都不在中心位置。这里我们还是需要使用numpy.fft.fftshift()函数将其移动到中间位置。
需要特别注意的是,函数cv2.dft()返回值是双通道的,第1个通道是结果的实数部分,第2个通道是结果的虚数部分。使用numpy.fft.fftshift()函数处理后,频谱图像还只是一个由实部和虚部构成的值,要显示出来,要使用到另一个函数cv2.magnitude()。
该函数的定义如下:
cv2.magnitude(参数1,参数2)
参数1:浮点型x坐标值,也就是实部
参数2:浮点型y坐标值,也就是虚部,它必须和参数1具有相同的大小(size)
得到频谱图像的幅度之后,还需要将幅度映射到灰度空间[0,255]内,使其以灰度图像显示出来。与前篇博文一样,使用20*np.log(cv2.magnitude())。
实现傅里叶变换
下面,我们来通过上述OpenCV函数来实现傅里叶变换,并显示其频谱信息。
import cv2 import numpy as np import matplotlib.pyplot as plt img = cv2.imread("4.jpg", 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.axis('off') plt.subplot(122) plt.imshow(result, cmap="gray") plt.axis('off') plt.show()
运行之后,显示效果与前篇博文一样。
实现逆傅里叶变换
还是与上篇博文一样,这里我们过滤图像的频谱信息,这里我们过滤低频信息。
import cv2 import numpy as np import matplotlib.pyplot as plt img = cv2.imread("4.jpg", 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])) rows,cols=img.shape rows_half,cols_half=int(rows/2),int(cols/2) mask=np.zeros((rows,cols,2),dtype=np.uint8) mask[rows_half-30:rows_half+30,cols_half-30:cols_half+30]=1 #逆傅里叶变换 fShift=dftShift*mask ishift=np.fft.ifftshift(fShift) iimg=cv2.idft(ishift) iimg=cv2.magnitude(iimg[:,:,0],iimg[:,:,1]) plt.subplot(121) plt.imshow(img, cmap="gray") plt.axis('off') plt.subplot(122) plt.imshow(iimg, cmap="gray") plt.axis('off') plt.show()
运行之后,效果如下:
可以看到过滤低频信息后,图像的边缘信息被消弱了。