0

i wrote a function which performs 2d-convolution in the fourier domain. However, when i compare the output of my function to the output of the scipy.ndimage.convolve function without transfering the image and the kernel into the fourier domain the result is completely different. For a test convolution i chose a kernel which i expected would blur my test image, instead my test image just got significantly darker and the edges are highlighted. Using the scipy.ndimage.convolve function, yields the exected result. Does someone know what i do wrong in my function?

def fourier_conv(img:np.ndarray, kernel:np.ndarray) -> np.ndarray:
    #perform 2d discrete fourier transform on image and kernel
    #convolute image and kernel (maybe kernel padding necessary so image and kernel have same size)
    #perform inverse DTF to bring image back to spatial domain
    
    img_2ddft = np.fft.fft2(img)
    kernel_2ddft = np.fft.fft2(kernel)
    
    conv_img_fd = ndimage.convolve(img_2ddft, kernel_2ddft, mode='constant', cval=0, origin=0)

    conv_img = abs(np.fft.ifft2(conv_img_fd))
    return conv_img

Thanks for your help!

Laurids
  • 23
  • 3
  • Besides the issue discussed below, you need to pad and adjust the origin of the kernel, see here: https://stackoverflow.com/q/54877892/7328782 – Cris Luengo Apr 25 '23 at 19:08
  • Padding is automatically performed by the ndimage.convolve method. – Laurids Apr 25 '23 at 23:01
  • Yes, but you shouldn’t be using that method. You need to multiply the two spectra together, as the answer below states. – Cris Luengo Apr 25 '23 at 23:16
  • I tried a different version where i use np.multiply, that worked better but the images still werent the same. They looked the same but the values are still different... – Laurids Apr 26 '23 at 10:24
  • Why would you use `np.multiply`, when you have the simple operator `*`? The answer at the link I shared earlier contains complete code. Just follow that. You can use `np.fft` instead of `scipy.fftpack`, they do the same thing. Pay attention to the details in that answer, for example you need to take the real part of the result, not the absolute value. And don’t expect numerically identical results, they should be very close though, except near the boundary of the image, where different conditions are applied in the FFT vs the spatial convolution. – Cris Luengo Apr 26 '23 at 13:05

1 Answers1

1

This is expected: one of the reasons a Fourier transform is so useful in certain contexts is that it eliminates the need for a convolution. A full continuous convolution is equivalent to a multiplication is frequency space. Obviously an FFT will be slightly different, but it should be fairly close. You'd have to research exactly how you multiply your transformed input by your transformed kernel in 2D.

David
  • 1,688
  • 1
  • 11
  • 21