Search code examples
pythonscipyconvolutionndimage

Why is my manual convolution different to scipy.ndimage.convolve


I apologise in advance, I may just not understand convolution.

I'm struggling to reconcile the results using scipy.ndimage.convolve with what I get attempting to do it by hand.

For the example in the documentation:

import numpy as np
a = np.array([[1, 2, 0, 0],
              [5, 3, 0, 4],
              [0, 0, 0, 7],
              [9, 3, 0, 0]])
k = np.array([[1,1,1],[1,1,0],[1,0,0]])
from scipy import ndimage
ndimage.convolve(a, k, mode='constant', cval=0.0)
array([[11, 10,  7,  4],
       [10,  3, 11, 11],
       [15, 12, 14,  7],
       [12,  3,  7,  0]])

However I would expect the result to be:

     ([[1,  8,  5,  0],
       [8, 11,  5,  4],
       [8, 17, 10, 11],
       [9, 12, 10,  7]])

For example for the top left value:

1×0 (extended beyond the input)
1×0 (extended beyond the input)
1×0 (extended beyond the input)
1×0 (extended beyond the input)
1×1
0×2
1×0 (extended beyond the input)
0×5
0×3
___
=1

I don't see how it can be 11

What am I misunderstanding about convolution, arrays, or what scipy is doing here?


Solution

  • The operation you're performing by hand is cross correlation, not convolution. The process of convolution is similar but "flips" the kernel. You can show that your expected result can be obtained by first flipping your kernel which then gets unflipped during covolution:

    > ndimage.convolve(a, np.flip(k), mode='constant', cval=0.0)
    array([[ 1,  8,  5,  0],
           [ 8, 11,  5,  4],
           [ 8, 17, 10, 11],
           [ 9, 12, 10,  7]])
    

    A bit more information here: https://cs.stackexchange.com/questions/11591/2d-convolution-flipping-the-kernel