简体   繁体   English

使用scipy.fftpack进行频域过滤,ifft2无法提供理想的结果

[英]Frequency domain filtering with scipy.fftpack, ifft2 does not give the desired result

I am trying to simply apply a Gaussian filter on a gray-scale input lena image in frequency domain with the following code and here is the wrong output I am getting: 我正在尝试使用以下代码在频域的灰度输入lena图像上简单地应用高斯滤波器,这是我得到的错误输出:

在此处输入图片说明

from scipy import signal
from skimage.io import imread
import scipy.fftpack as fp
import matplotlib.pyplot as plt

im = imread('lena.jpg') # read lena gray-scale image
# create a 2D-gaussian kernel with the same size of the image
kernel = np.outer(signal.gaussian(im.shape[0], 5), signal.gaussian(im.shape[1], 5))

freq = fp.fftshift(fp.fft2(im))
freq_kernel = fp.fftshift(fp.fft2(kernel))
convolved = freq*freq_kernel # simply multiply in the frequency domain
im_out = fp.ifft2(fp.ifftshift(convolved)).real # output blurred image

在此处输入图片说明

However, if I do the same but use signal.fftconvolve I get the desired blurred image output as shown below: 但是,如果我也这样做,但使用signal.fftconvolve得到所需的模糊图像输出,如下所示:

im_out = signal.fftconvolve(im, kernel, mode='same')  # output blurred image

在此处输入图片说明

My input image is 220x220, is there any padding issue? 我的输入图片是220x220,是否存在填充问题? if so, how to solve it and make the first code (without fftconvolve ) work? 如果是这样,如何解决它并使第一个代码(没有fftconvolve )起作用? any help will be highly appreciated. 任何帮助将不胜感激。

First of all, there is no need to shift the result of the FFT just to shift it back before doing the IFFT. 首先,不需要在执行IFFT之前就将FFT的结果移回去。 This just amounts to a lot of shifting they has no effect on the result. 这只是大量的转移,对结果没有影响。 Multiplying the two arrays happens in the same way whether you shift them both or not. 无论您是否同时移动两个数组,两个数组的乘积都以相同的方式发生。

The problem you noticed in your output is that the four quadrants are swapped. 您在输出中注意到的问题是四个象限已交换。 The reason this happens is because the filter is shifted by half its size, causing the same shift in the output. 发生这种情况的原因是因为滤波器的大小偏移了一半,导致输出发生了相同的偏移。

Why is it shifted? 为什么要转移? Well, because the FFT puts the origin in the top-left corner of the image. 好吧,因为FFT将原点放在图像的左上角。 This is not only true for the output of the FFT, but also for its input. 这不仅对于FFT的输出如此,对于其输入也是如此。 Thus, you need to generate a kernel whose origin is at the top-left corner. 因此,您需要生成一个原点位于左上角的内核。 How? 怎么样? Simply apply ifftshift to it before calling fft : 只需调用fft 之前对其应用ifftshift

freq = fp.fft2(im)
freq_kernel = fp.fft2(fp.ifftshift(kernel))
convolved = freq*freq_kernel
im_out = fp.ifft2(convolved).real

Note that ifftshift shifts the origin from the center to the top-left corner, whereas fftshift shifts it from the corner to the center. 请注意, ifftshift将原点从中心移到左上角,而fftshift将原点从角移到中心。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM