2
$\begingroup$

I use FFT to do filtering in frequency domain, but when I use big kernel I got shift on border, I think it's due to nature of cyclical convolution and I need to do more zero padding.

But how to calculate required padding size? should it be power of 2 in matlab?

Here is my matlab code:

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,[])

UPDATE:

Here is solution:

%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,[])
$\endgroup$
1
$\begingroup$

You dont have sigma specified for the gaussian filter. I typically use something like

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

as the gaussian kernel is roughly 6 x sigma wide. (see graph here but note they plot against variance https://en.wikipedia.org/wiki/Gaussian_function)

Because of that, your padding should be 3 x sigma. But padding with zeros creates an edge in the image that might not have been there. You may get better results by replicating the outer pixels instead of padding with zeros:

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

Also you might want to do an ifftshift before doing the fft2 of the filter (note the i)

You could up this to 8 x sigma (and 4 x sigma) if you really want most of the kernel. The gaussian kernel has infinite support so there will always be some circular convolution effect - you can't pad to infinity - but with 3 or 4 sigma padding it will be small.

btw MATLAB recommends using imgaussfilt http://au.mathworks.com/help/images/ref/imgaussfilt.html

$\endgroup$
0
$\begingroup$

Depending on how the filter kernel is generated, you might want to try an fftshift on the filter kernel before the fft2() to center the peak around 0,0.

$\endgroup$
  • $\begingroup$ Adding fftshift doesn't help, but add more strange distortions. $\endgroup$ – mrgloom Feb 17 '15 at 16:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.