scipy 将M*N矩阵的每个3x 3窗口求和为M/3*N/3矩阵,其中numpy

ki1q1bka  于 2022-11-10  发布在  其他
关注(0)|答案(2)|浏览(171)

我正在尝试实现一个函数,该函数将对给定矩阵的每个3x3窗口求和(或最终求平均值),并使用每个窗口的结果创建一个小9倍的矩阵。
我想不出一个有效而简洁的方法来处理numpy。
有什么想法吗?
谢谢你,谢谢你

vc6uscn9

vc6uscn91#

最简单的numpy only方法(它比卷积做的工作少得多,因此可能比基于过滤器的方法更快)是将原始数组的大小调整为具有额外维度的数组,然后通过对新维度求和将其还原为正常值:

>>> 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的倍数时有效。

khbbv19g

khbbv19g2#

为了达到你的要求,我会在图像上应用一个[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))

当你试图理解发生了什么的时候,记住stride代表我们需要在内存中偏移的字节数,以遍历到每个维度中的下一个单元格。因此,如果你处理的是int32数据类型,它将是4的乘积。

相关问题