1

I am trying to applying these two filters in the frequency domain. First, the low-pass filter, followed by the Laplace of Gaussian filter. Although my image is being filtered correctly, the output is wrapping around. Also, the output image is shifted ( it looks as if the image has been duplicated).

Here's the input and output: Before and After filter

Here's my code:

# Padding the image
image = Pad(image)

# The mask for low-pass filter
rows, cols = image.shape
center = (rows, cols)
crow, ccol = rows/2, cols/2
Low_mask = np.zeros((rows, cols), dtype=np.float32)
Low_mask[crow-cutoff:crow+cutoff, ccol-cutoff:ccol+cutoff] = 1

# Shifting the mask (low-pass)
Low_mask_dft = np.fft.fft2(Low_mask)
Low_mask_dft_shift  = np.fft.fftshift(Low_mask_dft)

# Shifting the image
image_dft = np.fft.fft2(image)
image_dft_shift = np.fft.fftshift(image_dft)

# Performing the convolution
image_fdomain = np.multiply(image_dft_shift, Low_mask_dft_shift)

# Shifting the mask (LOG)
LOGmask = GaussKernel(center)
LOGmask_dft = np.fft.fft2(LOGmask)
LOGmask_dft_shift = np.fft.fftshift(LOGmask_dft)

# Performing the convolution
frequency_image = np.multiply(image_fdomain, LOGmask_dft_shift)

# Now, return the image back to it's original form
result = np.fft.ifftshift(frequency_image)
result = np.fft.ifft2(result)
result = np.absolute(result)

return result
Royi
  • 4,640
  • 6
  • 46
  • 64
ARandAI95
  • 11
  • 1
  • 2
  • Possible duplicate of [Analytical Fourier transform vs FFT of functions in Matlab](https://stackoverflow.com/questions/49317834/analytical-fourier-transform-vs-fft-of-functions-in-matlab) – Cris Luengo May 31 '18 at 00:42
  • The linked question is not identical, but it explains your problem: the FFT expects the origin of the image (and the kernel) in the top-left corner. Since you have it in the middle, it is shifted. This leads to the effects you are seeing. Use `ifftshift` on your kernel before `fft`. – Cris Luengo May 31 '18 at 00:45
  • Also, you don’t need to apply `fftshift` in the frequency domain unless you want to show it. – Cris Luengo May 31 '18 at 00:45
  • So, I took your advice and I used the ifftshift on the kernel before before applying the fft. However, I still obtained similar results. So, I removed the LOG filter from the operation and I generated a smooth image without wrap around. I'm guessing that the problem stems from using the LOG filter. Do you have any thoughts? – ARandAI95 Jun 02 '18 at 02:06

1 Answers1

0

What you need to do is decide the boundary condition you're using.
The natural one for the Frequency Domain (For Discrete Data) is Circular / Cyclic Convolution which means circular boundary condition.

Once you set that and prepare data accordingly, everything works as required.

I created small MATLAB Script (You will be able to easily replicate it in Python) to show how it should be done.

The main thing is:

numRows = size(mI, 1);
numCols = size(mI, 2);

% Convolution in Spatial Domain
% Padding for Cyclic Convolution
mOGaussianRef = conv2(PadArrayCircular(mI, kernelRadius), mGaussianKernel, 'valid');
mOLogRef = conv2(PadArrayCircular(mI, kernelRadius), mLog, 'valid');

% Convolution in Frequency Domain
% Padding and centering of the Kernel
mGaussianKernel(numRows, numCols) = 0;
mGaussianKernel = circshift(mGaussianKernel, [-kernelRadius, -kernelRadius]);

mLog(numRows, numCols) = 0;
mLog = circshift(mLog, [-kernelRadius, -kernelRadius]);

mOGaussian  = ifft2(fft2(mI) .* fft2(mGaussianKernel), 'symmetric');
mOLog       = ifft2(fft2(mI) .* fft2(mLog), 'symmetric');

convErr = norm(mOGaussianRef(:) - mOGaussian(:), 'inf');
disp(['Gaussian Kernel - Cyclic Convolution Error (Infinity Norm) - ', num2str(convErr)]);

convErr = norm(mOLogRef(:) - mOLog(:), 'inf');
disp(['LoG Kernel - Convolution Error (Infinity Norm) - ', num2str(convErr)]);

Which results in:

Gaussian Kernel - Cyclic Convolution Error (Infinity Norm) - 3.4571e-06
LoG Kernel - Convolution Error (Infinity Norm) - 5.2154e-08

Namely it does what it should do.

The full code in my Stack Overflow Q50614085 Github Repository.

If you want to see how it should be done for other Boundary Conditions (Or Linear Convolution), have a look at FreqDomainConv.m.

Royi
  • 4,640
  • 6
  • 46
  • 64