在数组的每个索引周围切片部分



我需要以特定方式从 NumPy 数组中切片部分。假设我有一个(200,200, 4)形状的 NumPy 数组。然后对于(200, 200)中的每个索引,我想选择5x5x4周围的索引,将其展平,然后将其放入另一个数组中。所以最后,最终数组的形状将是(200, 200, 100).此外,我想删除位置(:, :, 12)的所有值。所以最后,我们会得到形状(200, 200, 99).

我想到了两种方法,但它们给出了不同的结果,我不确定我做错了什么。

方法一:

import numpy as np
arr_lst = [np.random.normal(size=(200, 200)) for _ in range(4)]
slice_arr = np.zeros([200, 200, 99])
start = 0
for i, arr in enumerate(arr_lst):
for idx, _ in np.ndenumerate(arr):

#Getting surrounding 25 pixels
pos_arr = arr[idx[0]-2:idx[0]+3, idx[1]-2:idx[1]+3]

#Reshaping, into size 100
pos_arr = pos_arr.reshape(-1)
#Near the boundaries slicing does not result in size 25
if pos_arr.shape[0] != 25:
pos_arr = np.full(25, np.nan)
if i == 0:
pos_arr = np.delete(pos_arr, 12)
end = start + 25 - 1
else:
end = start + 25
slice_arr[idx[0], idx[1], start:end] = pos_arr

start = end
print(slice_arr[10, 100])

方法2:

import numpy as np
arr_lst = [np.random.normal(size=(200, 200)) for _ in range(4)]      
stacked_arr = np.stack(arr_lst, axis=2)
slice_arr = np.zeros([200, 200, 100])
for i in range(200):
for j in range(200):
x = stacked_arr[i-2:i+3, j-2:j+3, 0:4]
if x.shape != (5, 5, 4):
x = np.array([np.nan for _ in range(100)])
else:
x = x.reshape(100)
slice_arr[i,j] = x
slice_arr = np.delete(slice_arr, 12, 2)
print(slice_arr[10, 100])

第一种方法以正确的顺序为我提供了所需的数组,但第二种方法感觉更自然、更快。我的另一个问题是我是否可以优化它?有没有一种快速的方法可以同时对每个索引进行切片并保持每个切片的形状相同?然后,删除我们想要的东西?

使用@hpaulj有用的注释,我设计了一个我认为适合我目的的解决方案。它类似于此处建议的内容:滚动 ndarray 的窗口,但具有 np.nan 值的额外边框。如果其他人觉得这很有用,我已经在这里发布了它,出于调试目的,我已经在填充数组中设置了值来协调元组:

from skimage.util.shape import view_as_windows
arr_lst = [np.empty(shape=(200, 200), dtype=tuple) for _ in range(4)]
arr_lst = [np.pad(x, pad_width=2, mode='constant', constant_values=np.nan) for x in arr_lst]
padded_arr = np.stack(arr_lst, axis=2)
for idx, _ in np.ndenumerate(padded_arr):
padded_arr[idx[0], idx[1], idx[2]] = idx
w = view_as_windows(padded_arr, (5, 5, 4)).reshape(200, 200, 100)

最新更新