numpy中的二维卷积

发布于 2021-01-29 16:05:29

我试图使用for循环实现2D数组的大步卷积

arr = np.array([[2,3,7,4,6,2,9],
                [6,6,9,8,7,4,3],
                [3,4,8,3,8,9,7],
                [7,8,3,6,6,3,4],
                [4,2,1,8,3,4,6],
                [3,2,4,1,9,8,3],
                [0,1,3,9,2,1,4]])

arr2 = np.array([[3,4,4],
                 [1,0,2],
                 [-1,0,3]])

def stride_conv(arr1,arr2,s,p):
    beg = 0
    end = arr2.shape[0]
    final = []
    for i in range(0,arr1.shape[0]-1,s):
        k = []
        for j in range(0,arr1.shape[0]-1,s):
            k.append(np.sum(arr1[beg+i : end+i, beg+j:end+j] * (arr2)))
        final.append(k)

    return np.array(final)

stride_conv(arr,arr2,2,0)

结果是3 * 3数组:

array([[ 91, 100,  88],
       [ 69,  91, 117],
       [ 44,  72,  74]])

是否有numpy函数或scipy函数执行相同的操作?我的方法不是很好。如何将其向量化?

关注者
0
被浏览
142
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    忽略填充参数和尾随窗口,这些窗口的长度不足以针对第二个数组进行卷积,这是一种方法np.lib.stride_tricks.as_strided-

    def strided4D(arr,arr2,s):
        strided = np.lib.stride_tricks.as_strided
        s0,s1 = arr.strides
        m1,n1 = arr.shape
        m2,n2 = arr2.shape    
        out_shp = (1+(m1-m2)//s, m2, 1+(n1-n2)//s, n2)
        return strided(arr, shape=out_shp, strides=(s*s0,s*s1,s0,s1))
    
    def stride_conv_strided(arr,arr2,s):
        arr4D = strided4D(arr,arr2,s=s)
        return np.tensordot(arr4D, arr2, axes=((2,3),(0,1)))
    

    另外,我们可以使用内置的scikit-imageview_as_windows优雅
    地获取那些窗口,就像这样-

    from skimage.util.shape import view_as_windows
    
    def strided4D_v2(arr,arr2,s):
        return view_as_windows(arr, arr2.shape, step=s)
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看