【问题标题】:Selecting multiple patches from a 3D numpy array从 3D numpy 数组中选择多个补丁
【发布时间】:2017-01-26 01:47:42
【问题描述】:

我有一个 3D numpy 数组,大小为 50x50x4。我还有 50x50 平面上几个点的位置。对于每个点,我需要提取一个以该点为中心的 11x11x4 区域。如果该区域与边界重叠,则该区域必须环绕。请问最有效的方法是什么?

我目前正在使用 for 循环遍历每个点,对 3D 矩阵进行子集化,并将其存储在预初始化数组中。是否有一个内置的 numpy 函数可以做到这一点?谢谢你。


抱歉回复慢,非常感谢大家的投入。

【问题讨论】:

    标签: python arrays numpy 3d


    【解决方案1】:

    一种方法是在最后一个轴上使用np.padwrapping 功能。然后,我们将使用np.lib.stride_tricks.as_strided 在这个填充版本上创建滑动窗口,作为填充数组的视图将不再占用内存。最后,我们将索引到滑动窗口以获得最终输出。

    # Based on http://stackoverflow.com/a/41850409/3293881
    def patchify(img, patch_shape): 
        X, Y, a = img.shape
        x, y = patch_shape
        shape = (X - x + 1, Y - y + 1, x, y, a)
        X_str, Y_str, a_str = img.strides
        strides = (X_str, Y_str, X_str, Y_str, a_str)
        return np.lib.stride_tricks.as_strided(img, shape=shape, strides=strides)
    
    def sliding_patches(a, BSZ):
        hBSZ = (BSZ-1)//2
        a_ext = np.dstack(np.pad(a[...,i], hBSZ, 'wrap') for i in range(a.shape[2]))
        return patchify(a_ext, (BSZ,BSZ))
    

    示例运行 -

    In [51]: a = np.random.randint(0,9,(4,5,2)) # Input array
    
    In [52]: a[...,0]
    Out[52]: 
    array([[2, 7, 5, 1, 0],
           [4, 1, 2, 0, 7],
           [1, 3, 0, 8, 4],
           [8, 0, 5, 2, 7]])
    
    In [53]: a[...,1]
    Out[53]: 
    array([[0, 3, 3, 8, 7],
           [3, 8, 2, 8, 2],
           [8, 4, 3, 8, 7],
           [6, 6, 8, 5, 5]])
    

    现在,让我们在a 中选择一个中心点,比如说(1,0) 并尝试在它周围找到blocksize (BSZ) = 3 的补丁-

    In [54]: out = sliding_patches(a, BSZ=3) # Create sliding windows
    
    In [55]: out[1,0,...,0]  # patch centered at (1,0) for slice-0
    Out[55]: 
    array([[0, 2, 7],
           [7, 4, 1],
           [4, 1, 3]])
    
    In [56]: out[1,0,...,1]  # patch centered at (1,0) for slice-1
    Out[56]: 
    array([[7, 0, 3],
           [2, 3, 8],
           [7, 8, 4]])
    

    因此,在(1,0) 周围获取补丁的最终输出将是:out[1,0,...,:],即out[1,0]

    无论如何,让我们对原始形状数组进行形状检查 -

    In [65]: a = np.random.randint(0,9,(50,50,4))
    
    In [66]: out = sliding_patches(a, BSZ=11)
    
    In [67]: out[1,0].shape
    Out[67]: (11, 11, 4)
    

    【讨论】:

      【解决方案2】:

      根据您必须执行多少次,一种简单有效的方法是填充原始数组:

      p = np.concatenate([a[-5:, ...], a, a[:5, ...]], axis=0)
      p = np.concatenate([p[:, -5:, :], p, p[:, :5, :]], axis=1)
      

      那么你可以简单地切片

      s = p[x0 : x0 + 11, x1 : x1 + 11, :]
      

      【讨论】:

        猜你喜欢
        • 2015-10-10
        • 2021-12-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-04-03
        • 1970-01-01
        • 2017-09-10
        • 2019-04-02
        相关资源
        最近更新 更多