I am performing the 2D FFT on a particular image and I get its spectral components. Now this image has been superimposed with another image to create periodic noise.
The original image as well as the periodic noise version is shown below:
Original Image
Periodic Noise Image
To filter this out, I used manual boxes that masked the components in the magnitude spectrum that are quite large relative to the other components as shown below.
After this is done, I perform an inverse FFT, but I do not get the original image back.
Does anyone know what I'm doing wrong?
Here is the code that masks the values and then proceeds to do an inverse 2D FFT on the masked spectral image:
pat1 = imread('Pattern1.png'); spec_orig = fft2(double(pat1)); spec_orig2 = abs(spec_orig); spec_img = fftshift(spec_orig2); for j = 115:125 for n = 96:106 spec_img(n,j) = 0; end for n = 216:226 spec_img(n,j) = 0; end for n = 274:284 spec_img(n,j) = 0; end for n = 298:308 spec_img(n,j) = 0; end for n = 12:22 spec_img(n,j) = 0; end for n = 37:47 spec_img(n,j) = 0; end end %Getting Back the Image for Pattern1 figure;subplot(2,1,1); spec_img = log(1 + spec_img); imshow(spec_img,[]); subplot(2,1,2); ptnfx = ifft2(spec_img); imshow(ptnfx);
Filtering in the frequency domain is a tricky business to get right. Your code has a few errors that are preventing you from reconstructing the original image:
You are applying the filtering on the magnitude component only. You have to do this on the original image spectrum, not just the magnitude component. The phase is essential for proper reconstruction. BTW, to coin a signal processing term, what you are implementing is a notch filter or a band-stop filter, which removes certain select frequencies.
You centered the spectrum via fftshift
but after you filtered you forgot to undo the shift. You must invoke ifftshift
on your resulting filtered image to undo the centering.
You're finding the inverse FFT of the log-transformed image. Remember that performing a log transform of the spectrum is only for display purposes. You do not use this when filtering or finding the inverse. Doing this will give you unintended consequences as the majority of the spectrum has been changed due to a non-linear operation. You have to do it on the original image spectrum itself.
A minor note, but make sure you call real
after you filter the result after you take the inverse FFT. There are most likely some residual imaginary components that are due to computational floating-point errors and so calling real
will only extract the real components of the signal.
With these corrections, this is the code I have. I've read your image directly from StackOverflow to be reproducible:
pat1 = imread('http://i.stack.imgur.com/oIumJ.png'); %// Change spec_orig = fft2(double(pat1)); spec_img = fftshift(spec_orig); for j = 115:125 for n = 96:106 spec_img(n,j) = 0; end for n = 216:226 spec_img(n,j) = 0; end for n = 274:284 spec_img(n,j) = 0; end for n = 298:308 spec_img(n,j) = 0; end for n = 12:22 spec_img(n,j) = 0; end for n = 37:47 spec_img(n,j) = 0; end end %// Change ptnfx = real(ifft2(ifftshift(spec_img))); imshow(ptnfx,[]);
I get this image:
A pretty good reconstruction of the original image I'll add. You'll still see a bit of streaking and that is highly dependent on the notch filter shape and size. Perhaps make the size bigger and even more so, make the shape of the notch filter circular instead of square. This has a tendency to preserve more of the original image as hard edges introduced by the corners of the squares have unintended ringing effects.
You have to use "ifftshift" when you convert back your image to spatial domain.