OpenCV 中相应的函数是 cv2.dft() 和 cv2.idft()。和前面输出的结果一样,但是是双通道的。第一个通道是结果的实数部分,第二个通道是结果的虚数部分。输入图像要首先转换成 np.float32 格式。我们来看看如何操作。
在前面的部分我们实现了一个 HPF(高通滤波),后面做 LPF(低通滤波)将高频部分去除。其实就是对图像进行模糊操作。首先我们需要构建一个掩模,与低频区域对应的地方设置为 1, 与高频区域对应的地方设置为 0。
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('image/lufei.jpeg',0)
dft = cv2.dft(np.float32(img),flags = cv2.DFT_COMPLEX_OUTPUT)
dft_shift = np.fft.fftshift(dft)
magnitude_spectrum = 20*np.log(cv2.magnitude(dft_shift[:,:,0],dft_shift[:,:,1]))
rows,cols = img.shape
crow,ccol = rows/2,cols/2
mask = np.zeros((rows,cols,2),np.uint8)
mask[crow-30:crow+30,ccol-30:ccol+30] = 1
fshift = dft_shift*mask
f_ishift = np.fft.ifftshift(fshift)
img_back = cv2.idft(f_ishift)
img_back = cv2.magnitude(img_back[:,:,0], img_back[:,:,1])
plt.subplot(121),plt.imshow(img,cmap = 'gray')
plt.title('Input Image'),plt.xticks([]),plt.yticks([])
plt.subplot(122),plt.imshow(img_back,cmap = 'gray')
plt.title('Magnitude Spectrum'),plt.xticks([]),plt.yticks([])
plt.show()
结果图:
OpenCV 中的函数 cv2.dft() 和 cv2.idft() 要比 Numpy 快。但是Numpy 函数更加用户友好。
当数组的大小为某些值时 DFT 的性能会更好,当数组的大小是 2 的指数时 DFT 效率最高。当数组的大小是 2, 3, 5 的倍数时效率也会很高。所以如果你想提高代码的运行效率时,你可以修改输入图像的大小(补 0)。对于OpenCV 你必须自己手动补 0,但是 Numpy,你只需要指定 FFT 运算的大小,它会自动补 0。那我们怎样确定最佳大小呢?OpenCV 提供了一个函数:cv2.getOptimalDFTSize(),可以同时被 cv2.dft() 和 np.fft.fft2() 使用。
为什么拉普拉斯算子是高通滤波器?为什么 Sobel 是 HPF?等等。对于第一个问题的答案我们以傅里叶变换的形式给出。我们一起来对不同的算子进行傅里叶变换并分析它们
import cv2
import numpy as np
from matplotlib import pyplot as plt
mean_filter = np.ones((3,3))
x = cv2.getGaussianKernel(5,10)
gaussian = x*x.T
scharr = np.array([[-3,0,3],[-10,0,10],[-3,0,3]])
sobel_x = np.array([[-1,0,1],[-2,0,2],[-1,0,1]])
sobel_y = np.array([[-1,-2,-1],[0,0,0],[1,2,1]])
laplacian = np.array([[0,1,0],[1,-4,1],[0,1,0]])
filters = [mean_filter,gaussian,laplacian,sobel_x,sobel_y,scharr]
filter_name = ['mean_filter','gaussian','laplacian','sobel_x','sobel_y','scharr_x']
fft_filters = [np.fft.fft2(x) for x in filters]
fft_shift = [np.fft.fftshift(y) for y in fft_filters]
mag_spectrum = [np.log(np.abs(z)+1) for z in fft_shift]
for i in xrange(6):
plt.subplot(2,3,i+1),plt.imshow(mag_spectrum[i],cmap = 'gray')
plt.title(filter_name[i]),plt.xticks([]),plt.yticks([])
plt.show()
结果图:
从图像中我们就可以看出每一个算子允许通过那些信号。从这些信息中我
们就可以知道那些是 HPF 那是 LPF.