Convolve2d just by using Numpy

前端 未结 3 718
孤独总比滥情好
孤独总比滥情好 2020-12-02 13:52

I am studying image-processing using Numpy and facing a problem with filtering with convolution.

I would like to convolve a gray-scale image. (convolve a 2d A

相关标签:
3条回答
  • 2020-12-02 14:01

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

    from numpy.fft import fft2, ifft2
    import numpy as np
    
    def 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
    
    • https://gist.github.com/thearn/5424195
    • you must pad the filter to be the same size as image ( place it in the middle of a zeros_like mat.)

    cheers, Dan

    0 讨论(0)
  • 2020-12-02 14:03

    You could generate the subarrays using as_strided [1]:

    import numpy as np
    
    a = 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_shape
    strides = a.strides + a.strides
    
    sub_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]]
    
    0 讨论(0)
  • 2020-12-02 14:24

    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)
    
    0 讨论(0)
提交回复
热议问题