我有一个3D numpy数组,大小为50x50x4。我也有50x50飞机上几个点的位置。对于每个点,我需要提取一个11x11x4区域,以该点为中心。如果该区域与边界重叠,则该区域必须环绕。请问最有效的方法是什么?
我目前正在使用for循环迭代每个点,将3D矩阵子集化,并将其存储在pre-init数组中。是否有内置的numpy功能可以做到这一点?谢谢。
很抱歉回复缓慢,非常感谢大家的投入。
答案 0 :(得分:1)
一种方法是在最后一个轴上使用np.pad
和wrapping
功能。然后,我们将使用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)
答案 1 :(得分:0)
根据您必须执行此操作的次数,一种简单有效的方法是填充原始数组:
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, :]