Convolve2d just by using Numpy Convolve2d just by using Numpy numpy numpy

Convolve2d just by using Numpy


You could generate the subarrays using as_strided:

import numpy as npa = np.array([[ 0,  1,  2,  3,  4],       [ 5,  6,  7,  8,  9],       [10, 11, 12, 13, 14],       [15, 16, 17, 18, 19],       [20, 21, 22, 23, 24]])sub_shape = (3,3)view_shape = tuple(np.subtract(a.shape, sub_shape) + 1) + sub_shapestrides = a.strides + a.stridessub_matrices = np.lib.stride_tricks.as_strided(a,view_shape,strides)

To get rid of your second "ugly" sum, alter your einsum so that the output array only has j and k. This implies your second summation.

conv_filter = np.array([[0,-1,0],[-1,5,-1],[0,-1,0]])m = np.einsum('ij,ijkl->kl',conv_filter,sub_matrices)# [[ 6  7  8]#  [11 12 13]#  [16 17 18]]


Cleaned up using as_strided and @Crispin 's einsum trick from above. Enforces the filter size into the expanded shape. Should even allow non-square inputs if the indices are compatible.

def conv2d(a, f):    s = f.shape + tuple(np.subtract(a.shape, f.shape) + 1)    strd = numpy.lib.stride_tricks.as_strided    subM = strd(a, shape = s, strides = a.strides * 2)    return np.einsum('ij,ijkl->kl', f, subM)


You can also use fft (one of the faster methods to perform convolutions)

from numpy.fft import fft2, ifft2import numpy as npdef fft_convolve2d(x,y):    """ 2D convolution, using FFT"""    fr = fft2(x)    fr2 = fft2(np.flipud(np.fliplr(y)))    m,n = fr.shape    cc = np.real(ifft2(fr*fr2))    cc = np.roll(cc, -m/2+1,axis=0)    cc = np.roll(cc, -n/2+1,axis=1)    return cc

cheers,Dan