在numpy张量中快速实现邻域

时间:2018-09-12 20:48:05

标签: python arrays numpy

我在numpy中有一个3张量A和一个索引(i,j,k)。我需要将一个{可能是numpy的)数组arr放在(i,j,k)的“邻居”的线性索引中(即元素(i+i1, j+j1, k+k1),其中i1, j1, k2 = -1, 0, 1) 。我需要对(i,j,k)的每个索引A进行此操作,所以我的问题是,有一种简便快捷的方法吗?

一个玩具示例:

n = 10
dim = (10, 10, 10)
i, j, k = (2, 3, 4)
res = []
pm = [-1, 0, 1]
for i1 in range(3):
    for j1 in range(3):
        for k1 in range(3):
            # ravel_multi_index transforms a multi-index (i,j,k) to the corresponding linear index of a tensor of shape "dim"
            res.append(np.ravel_multi_index((i + pm[i1], j + pm[j1], k + pm[k1]), dim))
#print...
[123, 124, 125, 133, 134, 135, 143, 144, 145, 223, 224, 225, 233, 234, 235, 243, 244, 245, 323, 324, 325, 333, 334, 335, 343, 344, 345]

有27个社区。

边界索引的邻域较少:例如,坐标(0,0,0)有8个邻域。

作为解决方案,我正在考虑将邻域进行某种“固定化”处理,但这很快变得很麻烦。

1 个答案:

答案 0 :(得分:0)

这应该做到。您只需生成一次vertices数组,然后让广播完成其余的工作。 vertices提供了添加到索引并获取其所有邻居所需的全部27种可能性。

ijk = np.array([2, 3, 4]) # an example point 
dim = (10, 10, 10) # dimensions 

pts = np.stack(([-1,0,1],)*3,0)
vertices = (np.array(np.meshgrid(*pts)).T).reshape(3**3,3) # a 27x3 array
# the vertices are the points to add to ijk to get all neighbors 

n = (vertices + ijk).T # neighbors 
n = n.T[((n[0]>=0)&(n[0]<dim[0])
         &(n[1]>=0)&(n[1]<dim[1])
          &(n[2]>=0)&(n[2]<dim[2]))] # out of bounds elements filtered

这将返回

>>> n
array([[1, 2, 3],
       [1, 3, 3],
       [1, 4, 3],
       [2, 2, 3],
       [2, 3, 3],
       [2, 4, 3],
       [3, 2, 3],
       [3, 3, 3],
       [3, 4, 3],
       [1, 2, 4],
       [1, 3, 4],
       [1, 4, 4],
       [2, 2, 4],
       [2, 3, 4],
       [2, 4, 4],
       [3, 2, 4],
       [3, 3, 4],
       [3, 4, 4],
       [1, 2, 5],
       [1, 3, 5],
       [1, 4, 5],
       [2, 2, 5],
       [2, 3, 5],
       [2, 4, 5],
       [3, 2, 5],
       [3, 3, 5],
       [3, 4, 5]])

您可以使用

将其强加到示例输出中
sorted([int(''.join(x)) for x in n.astype('str')])

哪个返回

 [123,
 124,
 125,
 133,
 134,
 135,
 143,
 144,
 145,
 223,
 224,
 225,
 233,
 234,
 235,
 243,
 244,
 245,
 323,
 324,
 325,
 333,
 334,
 335,
 343,
 344,
 345]