Search code examples
matlabimage-processingfilterfftlowpass-filter

Manual high/low-pass filter in MATLAB


I am struggling with finding the error in my code or reasoning; I have to manually create a high/lowpass filter to process an image in the frequency domain. I am not allowed to use butter(), filter() and other related functions.

The end result I am aiming for is something that is similar to what is shown here: link 1, link2.

To achieve this result I have created the following function:

function out = hlow2(x,n,mask,u)
% x - input image
% n - mask size
% mask - user-defined mask
% u - user choice: 1 -> high-pass, anything else -> low-pass
a=size(x);
mask=padarray(mask,[floor((a(1)-n)/2) floor((a(2)-n)/2)],'replicate');
mask=padarray(mask,[1 1],'replicate','pre');
% i am padding the mask array in order to make it fit the image and have my
% circle filter attached to the "middle" of the frequency graph.

maskl=logical(mask);
maskh=~mask;
maskl=double(maskl);
maskh=double(maskh);
% here, i created the high and low pass masks from the user-defined mask.

x=fft2(x);

if u==1
    HP=x.*maskh;
    out=ifft(HP);
else
    LP=x.*maskl;
    out=ifft(LP);
end
end

The mask I'm using is a white circle on a black bacground. I am using it in the following code:

mask=imread('circle.png');
mask=double(mask)/255;
mask=mask(:,:,1);

boat_a=imread('boat.png');
boat_a2=double(boat_a)/255;

c1=hlow2(boat_a2,255,mask,1);
c2=hlow2(boat_a2,255,mask,2);


figure()
imshow(c1)
figure()
imshow(c2)

The end result, however, is totally not what I'd expect! I checked the images' frequency graphs and they seem fine, with the circle filter placed where it should be, but the output images are completely wrong. For the high-pass filter, the output image is unchanged. For low-pass, it's completely black. I tried rewriting the function a few times and playing with the way i multiply the matrices but my result won't change.

I am sure I'm missing something, but I can't seem to find what. Please, please help me.


Solution

  • Use ifft2 and fftshift

    x=fft2(x);
    x=fftshift(x);
    if u==1
        P=x.*maskh;
    else
        P=x.*maskl;
    end
    P=fftshift(P);
    out=ifft2(P);
    

    Also I think this is an easier way to make a mask with a circle in the middle:

    [i,j]=size(im');
    [x, y] = meshgrid(1:i, 1:j);
    r=20;
    mask=((x-i/2).^2+(y-j/2).^2)<r^2;