具有大内核大小的频域滤波

信息处理 matlab fft 卷积 IFFT 快速卷积
2022-02-22 21:48:04

我使用 FFT 在频域中进行滤波,但是当我使用大内核时,我在边界上发生了偏移,我认为这是由于循环卷积的性质,我需要做更多的零填充。

但是如何计算所需的填充大小?在matlab中应该是2的幂吗?

这是我的matlab代码:

tic
I= rgb2gray(imread('im.jpg'));
h = fspecial('gaussian',555);
F = fft2(double(I));
H = fft2(double(h), size(I,1), size(I,2));
F_fH = H.*F;
ffi = ifft2(F_fH);
toc

figure, imshow(ffi,[])

更新:

这是解决方案:

%The zero-padding is just a way to make cyclical convolutions
%(which is what FFT-based convolutions are) act like linear convolutions.
%the convolution theorem yields the desired linear convolution result only 
%if x(n) and h(n) are padded with zeros prior to the DFT such that their 
%respective lengths are Nx+Nh-1, essentially zeroing out all circular artifacts.

tic
%Frequency Domain Filtering 
I= rgb2gray(imread('im.jpg'));

ker_sz= 55;
h = fspecial('gaussian',ker_sz);
F = fft2(double(I), size(I,1)+ker_sz-1, size(I,2)+ker_sz-1);
H = fft2(double(h), size(I,1)+ker_sz-1, size(I,2)+ker_sz-1);
F_fH = F.*H;
ffi = ifft2(F_fH);
ffi= ffi((ker_sz-1)/2+1:(ker_sz-1)/2+size(I,1), (ker_sz-1)/2+1:(ker_sz-1)/2+size(I,2));
toc
%Display results
figure, imshow(ffi,[])
2个回答

您没有为高斯滤波器指定 sigma。我通常使用类似的东西

fspecial('gaussian',6*sigma,sigma);

因为高斯核大约是 6 x sigma 宽。(请参见此处的图表,但请注意它们针对方差进行绘图https://en.wikipedia.org/wiki/Gaussian_function

因此,您的填充应该是 3 x sigma。但是用零填充会在图像中创建一个可能不存在的边缘。您可以通过复制外部像素而不是用零填充来获得更好的结果:

padarray(I,[3*sigma,3*sigma],'symmetric');

此外,您可能想要在执行过滤器ifftshift之前执行一个fft2(注意i

如果您真的想要大部分内核,您可以将其提高到 8 x sigma(和 4 x sigma)。高斯核有无限的支持,所以总会有一些循环卷积效应——你不能填充到无穷大——但是用 3 或 4 sigma 填充它会很小。

顺便说一句,MATLAB 建议使用imgaussfilt http://au.mathworks.com/help/images/ref/imgaussfilt.html

根据滤波器内核的生成方式,您可能希望在 fft2() 之前尝试对滤波器内核进行 fftshift 以使峰值居中在 0,0 附近。