Can `imfilter` work in the frequency domain?

564 views Asked by At

According to this Quora answer, Gabor filter is a frequency domain filter. And, here is an implementation of Gabor filter which uses imfilter() to achieve the filtering, which means that

imfilter() works in the frequency domain.

Now, let us look at Source Code #1.

If I replace

I_ffted_shifted_filtered = I_ffted_shifted.*Kernel;

with

I_filtered = imfilter(I, Kernel);

as the following

function [out1, out2] = butterworth_lpf_imfilter(I, Dl, n)

    Kernel = butter_lp_kernel(I, Dl, n);

    I_filtered = imfilter(I, Kernel);

    out1 = ifftshow(ifft2(I_filtered));

    out2 = ifft2(ifftshift(I_filtered));
end

we don't obtain the expected output,

enter image description here

Why doesn't this work? What is the problem in my code?


Source Code #1

main.m

clear_all();
I = gray_imread('cameraman.png');
Dl = 10;
n = 1;
[J, K] = butterworth_lpf(I, Dl, n);    
imshowpair(I, J, 'montage');

butterworth_lpf.m

function [out1, out2] = butterworth_lpf(I, Dl, n)    
    Kernel = butter_lp_kernel(I, Dl, n);        
    I_ffted_shifted = fftshift(fft2(I));

    I_ffted_shifted_filtered = I_ffted_shifted.*Kernel;

    out1 = ifftshow(ifft2(I_ffted_shifted_filtered));        
    out2 = ifft2(ifftshift(I_ffted_shifted_filtered));
end

butter_lp_kernel.m

function k = butter_lp_kernel(I, Dl, n) 
    Height = size(I,1); 
    Width = size(I,2);                
    [u, v] = meshgrid( ...
                    -floor(Width/2) :floor(Width-1)/2, ...
                    -floor(Height/2): floor(Height-1)/2 ...
                 );         
    k = butter_lp_f(u, v, Dl, n);    

function f = butter_lp_f(u, v, Dl, n)
    uv = u.^2+v.^2;
    Duv = sqrt(uv);
    frac = Duv./Dl;
    denom = frac.^(2*n);
    f = 1./(1.+denom);

Output

enter image description here

1

There are 1 answers

2
Alex Taylor On BEST ANSWER

imfilter takes a spatial domain representation of an image A and a spatial domain kernel h, and returns a spatial domain image, B. Whatever domain or algorithm is used to compute B is an implementation detail. That said, imfilter uses spatial convolution to compute B.

As you can see in the comments above, a Gabor filter is not a "frequency domain filter". A Gabor filter is LTI and as such the filtering operation can be implemented in either domain. This should make sense, given that the "gaussian modulated with a sinusoid" waveforms that are frequently shown in the literature when discussing Gabor filter banks are in the spatial domain.

Example of spatial domain Gabor filter kernels

It happens that in the spatial domain, Gabor filter kernels can get large and are non-separable in the general case unless theta is a multiple of 90 degrees unless you want to use approximate techniques. So, it is common to use a frequency domain implementation of Gabor filtering for speed purposes. This is what imgaborfilt does in IPT.

If you have IPT, I recommend looking at the code in gabor and imgaborfilt for more information.

https://www.mathworks.com/help/images/ref/imgaborfilt.html

https://www.mathworks.com/help/images/ref/gabor.html

In the implementation you are using, they are using a frequency domain implementation. If you want to use imfilter, you would have to pass in the equivalent spatial domain representation of the Gabor filter. It does not make sense to pass a frequency domain representation of the Gabor filter to imfilter as you are currently doing. That is not a Gabor filtering operation.