2

The documentation of OpenCV demonstrates how you can perform an discrete fourier transform, apply an LPF mask and then perform an inverse DFT. The following code does this:

import numpy as np
import cv2
from matplotlib import pyplot as plt

img = cv2.imread('messi5.jpg',0)

dft = cv2.dft(np.float32(img),flags = cv2.DFT_COMPLEX_OUTPUT)
dft_shift = np.fft.fftshift(dft)

magnitude_spectrum = 20*np.log(cv2.magnitude(dft_shift[:,:,0],dft_shift[:,:,1]))

plt.subplot(121),plt.imshow(img, cmap = 'gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(magnitude_spectrum, cmap = 'gray')
plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])
plt.show()

rows, cols = img.shape
crow,ccol = rows/2 , cols/2

# create a mask first, center square is 1, remaining all zeros
mask = np.zeros((rows,cols,2),np.uint8)
mask[crow-30:crow+30, ccol-30:ccol+30] = 1

# apply mask and inverse DFT
fshift = dft_shift*mask
f_ishift = np.fft.ifftshift(fshift)
img_back = cv2.idft(f_ishift)
img_back = cv2.magnitude(img_back[:,:,0],img_back[:,:,1])

plt.subplot(121),plt.imshow(img, cmap = 'gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(img_back, cmap = 'gray')
plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])
plt.show()

I have two questions:

  1. Is this the same as performing a sinc filter?
  2. Also, how do I perform the same on an RGB image (instead of grayscale)? I tried performing this operation on the individual channels and stacking them back together but I guess that's not the way to go about it.

Thank you in advance.

  • 1
    Yes, applying the filter to each channel independently is the right way to do it. This is true for any linear filter such as the one you're applying, but not true for non-linear filters (such as the median filter or morphological filters). – Cris Luengo Jan 28 '20 at 15:05
  • So in regard to question 1, is this performing the same job as a sinc filter? – Sukanya Dasgupta Jan 28 '20 at 16:46
  • 1
    Yes, multiplication with a square filter in the frequency domain is the same thing as a convolution with a sinc filter in the spatial domain. – Cris Luengo Jan 28 '20 at 16:46
  • 2
    However, instead of the magnitude of the inverse FFT, use the real part. The imaginary part must be very close to 0, so you can discard it. If it's not, there's an issue with your code. – Cris Luengo Jan 28 '20 at 16:48
  • Thanks a lot! Yes, I did change it to just the real part :) As a follow up question, how do I modify this to work as a Lanczos filter (which I believe just picks the central lobe of the sinc function)? – Sukanya Dasgupta Jan 28 '20 at 16:51
  • 1
    The Lanczos filter is two differently-sized sinc functions multiplied together, then taking the region corresponding to the central lobe of the larger of the two. This is a way of truncating the sinc function so it's easier to compute in the spatial domain. You should apply the filter as a convolution in the spatial domain, don't try to use the FFT for that. It can be done, but it's not going to be easy nor efficient. – Cris Luengo Jan 28 '20 at 16:55
  • Thanks again! What would be the best way to compute such a 2D kernel for the spatial domain? – Sukanya Dasgupta Jan 28 '20 at 17:00
  • It's a 1D kernel. Apply it to each row of the image, and then on each column of the result of the first step. You create the 1D kernel by sampling the given equation. Pick a parameter `a` (an integer value, typically 2) and sample at integer intervals from `-a` to `+a`. – Cris Luengo Jan 28 '20 at 17:08

0 Answers0