将M * N矩阵的每个3x3窗口与numpy的M / 3 * N / 3矩阵相加

时间:2013-11-17 11:11:54

标签: python image-processing numpy scipy

我正在尝试实现一个总和(或最终平均)的函数 给定矩阵的每个3x3窗口,并根据每个窗口的结果创建一个小9x的矩阵。

我无法通过numpy找到一种有效而简洁的方法。

有什么想法吗?

谢谢!

2 个答案:

答案 0 :(得分:7)

最简单的numpy方法,在卷积方面做得少得多,因此可能比基于文件管理器的方法更快,是将原始数组调整为具有额外维度的数组,然后通过对新数据求和来将其恢复正常尺寸:

>>> arr = np.arange(108).reshape(9, 12)
>>> rows, cols = arr.shape
>>> arr.reshape(rows//3, 3, cols//3, 3).sum(axis=(1, 3))
array([[117, 144, 171, 198],
       [441, 468, 495, 522],
       [765, 792, 819, 846]])

如果你想要均值,你只需将得到的数组除以元素数:

>>> arr.reshape(rows//3, 3, cols//3, 3).sum(axis=(1, 3)) / 9
array([[ 13.,  16.,  19.,  22.],
       [ 49.,  52.,  55.,  58.],
       [ 85.,  88.,  91.,  94.]])

此方法仅在您的数组的形状本身是3的倍数时才有效。

答案 1 :(得分:3)

为了达到您的要求,我会在图像上应用[3x3]盒式滤镜,而不是使用最近邻插值调整矩阵的大小。

# Pseudo code
kernel = np.array([[1/9, 1/9, 1/9],
                   [1/9, 1/9, 1/9],
                   [1/9, 1/9, 1/9]])
avg_data= ndimage.convolve(data, kernel)

smaller_data = scipy.misc.imresize(avg_data, org_size/3, interp='nearest', mode=None)

如果你想要更高效的东西 - 正如@Jaime指出的那样 - 你可以做这样的事情How can I efficiently process a numpy array in blocks similar to Matlab's blkproc (blockproc) function

from numpy.lib.stride_tricks import as_strided as ast

def block_view(A, block= (3, 3)):
    """Provide a 2D block view to 2D array. No error checking made.
    Therefore meaningful (as implemented) only for blocks strictly
    compatible with the shape of A."""
    # simple shape and strides computations may seem at first strange
    # unless one is able to recognize the 'tuple additions' involved ;-)
    shape= (A.shape[0]/ block[0], A.shape[1]/ block[1])+ block
    strides= (block[0]* A.strides[0], block[1]* A.strides[1])+ A.strides
    return ast(A, shape= shape, strides= strides)

if __name__ == '__main__':
    B = block_view(A).sum(axis=(2,3))

当您尝试了解发生了什么时,请记住步幅表示我们需要在内存中偏移以遍历每个维度中的下一个单元格的字节数。因此,如果您处理的是int32数据类型,那么它将是4的倍数。