首页 > 解决方案 > 沿着 3D NumPy 数组的后 2 个维度移动窗口以获得 3D 块

问题描述

我有一个像这样a的形状的 3D NumPy 数组:(2, 9, 9)

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

       [[4, 2, 0, 1, 6, 7, 1, 0, 8],
        [1, 5, 3, 6, 4, 2, 4, 8, 3],
        [7, 4, 9, 9, 1, 9, 7, 3, 1],
        [3, 6, 1, 2, 5, 4, 1, 3, 0],
        [3, 3, 6, 6, 9, 8, 4, 2, 8],
        [7, 9, 1, 3, 0, 2, 0, 7, 4],
        [6, 7, 9, 3, 0, 2, 1, 9, 2],
        [1, 0, 3, 4, 7, 8, 1, 6, 5],
        [4, 4, 7, 8, 3, 7, 0, 4, 7]]])

我想2 × 3 × 3使用沿后两个维度的移动窗口(在本例中9 × 9)获得 3D 形状块。第一个维度的大小(我称之为“深度”)是任意的。第一个块的示例是:

>>> array([
       [[np.nan, np.nan, np.nan],
        [np.nan, 4, 5],
        [np.nan, 9, 2]],

        [[np.nan, np.nan, np.nan],
        [np.nan, 4, 2],
        [np.nan, 1, 5]]])

第二个是:

>>> array([
       [[np.nan, np.nan, np.nan],
        [4, 5, 1],
        [9, 2, 2]],

        [[np.nan, np.nan, np.nan],
        [4, 2, 0],
        [1, 5, 3]]])

等等...

我稍后需要对这些块应用更复杂的函数,而不是简单的平均值或类似的函数,所以我会很感激它们的新数组(我想这是相当内存密集型的,有没有不同的方法?可能矢量化?但它不是必要的)

我尝试在 #44305987 中申请np.lib.stride_tricks.as_strided我的案例,并在#15722324使用花哨的索引,但没有达到预期的结果。

谢谢!

标签: pythonarraysnumpyconvolution

解决方案


你可以用skimage.util.view_as_windows这个。由于您似乎需要2这些窗口视图的最小元素大小,您可以将数组分配给更大的数组np.nan,并获取结果数组的跨步视图:

from skimage.util import view_as_windows

i,j,k= a.shape
a_exp = np.full((i,j+2,k+2), np.nan)
a_exp[:,1:j+1,1:k+1] = a

或者你也可以这样做np.pad

a_exp = np.pad(a.astype('float'), 
               pad_width=((0,0),(1,1),(1,1)), 
               constant_values=np.nan)

并查看跨步:

out = view_as_windows(a_exp, (a.shape[0],3,3))

out
array([[[[[[nan, nan, nan],
           [nan,  4.,  5.],
           [nan,  9.,  2.]],

          [[nan, nan, nan],
           [nan,  4.,  2.],
           [nan,  1.,  5.]]],


         [[[nan, nan, nan],
           [ 4.,  5.,  1.],
           [ 9.,  2.,  2.]],

          [[nan, nan, nan],
           [ 4.,  2.,  0.],
           [ 1.,  5.,  3.]]],
         ...

推荐阅读