开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第24天,点击查看活动详情
前言
我们已经学习了如何在实际应用中使用 numpy.fft 模块的 2D-FFT。在本节中,我们将介绍 scipy.fftpack 模块的 fft2() 函数用于实现高斯模糊 LPF。
实现高斯模糊
在本节,我们将使用人物灰度图像作为输入,并使用 FFT 从图像中创建 2D 频率响应数组:
import numpy as np
import numpy.fft as fp
from skimage.color import rgb2gray
from skimage.io import imread
import matplotlib.pyplot as plt
from scipy import signal
from matplotlib.ticker import LinearLocator, FormatStrFormatter
im = rgb2gray(imread('1.png'))
freq = fp.fft2(im)
通过计算两个 1D 高斯核的外积,在空间域中创建高斯 2D 核用作 LPF:
kernel = np.outer(signal.gaussian(im.shape[0], 1), signal.gaussian(im.shape[1], 1))
使用 DFT 获得高斯核的频率响应:
freq_kernel = fp.fft2(fp.ifftshift(kernel))
使用卷积定理通过逐元素乘法在频域中将 LPF 与输入图像卷积:
convolved = freq*freq_kernel # by the Convolution theorem
使用 IFFT 获得输出图像,需要注意的是,要正确显示输出图像,需要缩放输出图像:
im_blur = fp.ifft2(convolved).real
im_blur = 255 * im_blur / np.max(im_blur)
绘制图像、高斯核和在频域中卷积后获得图像的功率谱,可以使用 matplotlib.colormap 绘制色,以了解不同坐标下的频率响应值:
plt.figure(figsize=(20,20))
plt.subplot(221), plt.imshow(kernel, cmap='coolwarm'), plt.colorbar()
plt.title('Gaussian Blur Kernel', size=10)
plt.subplot(222)
plt.imshow( (20*np.log10( 0.01 + fp.fftshift(freq_kernel))).real.astype(int), cmap='inferno')
plt.colorbar()
plt.title('Gaussian Blur Kernel (Freq. Spec.)', size=10)
plt.subplot(223), plt.imshow(im, cmap='gray'), plt.axis('off'), plt.title('Input Image', size=10)
plt.subplot(224), plt.imshow(im_blur, cmap='gray'), plt.axis('off'), plt.title('Output Blurred Image', size=10)
plt.tight_layout()
plt.show()
要绘制输入/输出图像和 3D 核的功率谱,我们定义函数 plot_3d(),使用 mpl_toolkits.mplot3d 模块的 plot_surface() 函数获取 3D 功率谱图,给定相应的 Y 和Z值作为 2D 阵列传递:
def plot_3d(X, Y, Z, cmap=plt.cm.seismic):
fig = plt.figure(figsize=(20,20))
ax = fig.gca(projection='3d')
# Plot the surface.
surf = ax.plot_surface(X, Y, Z, cmap=cmap, linewidth=5, antialiased=False)
#ax.plot_wireframe(X, Y, Z, rstride=10, cstride=10)
#ax.set_zscale("log", nonposx='clip')
#ax.zaxis.set_scale('log')
ax.zaxis.set_major_locator(LinearLocator(10))
ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f'))
ax.set_xlabel('F1', size=15)
ax.set_ylabel('F2', size=15)
ax.set_zlabel('Freq Response', size=15)
#ax.set_zlim((-40,10))
# Add a color bar which maps values to colors.
fig.colorbar(surf) #, shrink=0.15, aspect=10)
#plt.title('Frequency Response of the Gaussian Kernel')
plt.show()
在 3D 空间中绘制高斯核的频率响应,并使用 plot_3d() 函数:
Y = np.arange(freq.shape[0]) #-freq.shape[0]//2,freq.shape[0]-freq.shape[0]//2)
X = np.arange(freq.shape[1]) #-freq.shape[1]//2,freq.shape[1]-freq.shape[1]//2)
X, Y = np.meshgrid(X, Y)
Z = (20*np.log10( 0.01 + fp.fftshift(freq_kernel))).real
plot_3d(X,Y,Z)
下图显示了 3D 空间中高斯 LPF 核的功率谱:
绘制 3D 空间中输入图像的功率谱:
Z = (20*np.log10( 0.01 + fp.fftshift(freq))).real
plot_3d(X,Y,Z)
最后,绘制输出图像的功率谱(通过将高斯核与输入图像卷积获得):
Z = (20*np.log10( 0.01 + fp.fftshift(convolved))).real
plot_3d(X,Y,Z)
从输出图像的频率响应中可以看出,高频组件被衰减,从而导致细节的平滑/丢失,并导致输出图像模糊。