1

I'm trying to convolve an image using a gaussian filter and I've learnt that using FFTs is the fastest way to do so. I've tried convolving the image with the gaussian filter but the results haven't turned out so well..

gaussian=[[0.003, 0.013, 0.022, 0.013, 0.003],\
          [0.013, 0.059, 0.097, 0.059, 0.013],\
          [0.022, 0.097, 0.159, 0.097, 0.022],\
          [0.013, 0.059, 0.097, 0.059, 0.013],\
          [0.003, 0.013, 0.022, 0.013, 0.003]]
gaussian1=np.array(gaussian)
# load in an image, convert to grayscale if needed
image = imageio.imread('input.jpg',as_gray=True)

# take the fourier transform of the image
fft2 = fftpack.fftshift(fftpack.fft2(image))
gaussian_np= fftpack.fftshift(fftpack.fft2(gaussian))

#temp array to save the results
temp_array=np.ones((fft2.shape[0],fft2.shape[1]))

for x in range(fft2.shape[0]-4): #range upto -4 because of 5x5 kernel
    for y in range(fft2.shape[1]-4):

        temp=fft2[x:5+x,y:5+y] #slices 5x5 grid from fft of image
        convolution=np.multiply(temp,gaussian_np)
        temp_array[x:5+x,y:5+y]=convolution
#convert results back
ifft2 = abs(fftpack.ifft2(fftpack.ifftshift(temp_array)))
sspatole
  • 115
  • 1
  • 1
  • 8
  • 1
    Note that for small kernels (and particularly for separable kernels, like Gaussian), an FFT-based convolution probably won't be more efficient. Depending on language, platform, etc, there is a generally a "tipping point" where the kernel size is large enough to warrant a frequency domain approach, but it's usually much larger than 5x5. – Paul R Feb 07 '19 at 08:41
  • @PaulR I'm trying to smoothen a large image, if I choose to stick with FFT, is there a way to create a gaussian large enough(of the size of the image)? – sspatole Feb 10 '19 at 01:51
  • 1
    You have to pad the kernel with zeroes prior to the FFT. Or you can just use an existing method, such as [scipy.signal.fftconvolve](https://stackoverflow.com/q/1100100/253056) – Paul R Feb 10 '19 at 08:23
  • You mean if I have a 2000x2000 image and a 5x5 gaussian kernel, I just pad the 5x5 kernel with zeroes to match with the image dimensions and it would do the trick? – sspatole Feb 10 '19 at 17:49
  • Yes, but it’s slightly more complicated than that - in order to avoid circular convolution you need to pad the image with 5-1=4 zeroes in each axis, and pad the kernel to the same dimensions. E.g. if the image is 2000x2000 then you need to pad both image and kernel to 2004x2004. – Paul R Feb 11 '19 at 07:16

0 Answers0