【问题标题】:How to pad a numpy 3D array (or torch tensor) with values from surrounding 3D arrays如何使用来自周围 3D 数组的值填充 numpy 3D 数组(或 Torch 张量)
【发布时间】:2021-02-23 17:30:55
【问题描述】:

我有一个形状为 3,3,3 的 3D numpy 数组,我想从空间上围绕它的数组填充 2 层值,使其成为 5,5,5 数组。

到目前为止,我使用 torch cat 函数(其工作方式与 numpy concat 相同)填充 y 数组所做的工作如下:

x = torch.from_numpy(np.arange(1,28,1).reshape(3,3,3))
y = torch.from_numpy(np.arange(28,55,1).reshape(3,3,3))
z = torch.from_numpy(np.arange(55,82,1).reshape(3,3,3))

torch.cat((y,z[:,:2,:]), dim=1) #To concat z+ with 2 pads
torch.cat((x[:,1:,:],y), dim=1) #To concat z- with 2 pads

torch.cat((y,z[:,:,:2]), dim=2) #To concat x+ with 2 pads
torch.cat((x[:,1:,:],y), dim=1) #To concat x- with 2 pads

torch.cat((x,z[:2,:,:]), dim=2) #To concat y+ with 2 pads
torch.cat((x[1:,:,:],y), dim=1) #To concat y- with 2 pads

但它没有给我正确的价值观。我怎样才能做到这一点?

【问题讨论】:

  • 如果我遵循正确,您建议的操作会导致具有 81 个元素的非矩形形状(基本上是 5x5x5 立方体,但缺少边和角)。一个 5x5x5 的张量有 125 个元素。例如,您希望结果张量在索引 (0,0,0) 处具有什么值?如果您能提供一个很有帮助的示例输入/输出。
  • @jodag 我明白你的意思。边缘和角落区域将被留下。其实,我也不知道。问题是我需要创建一个函数,从所有触摸框/数组中获取所需的层数并将它们连接起来

标签: python arrays numpy multidimensional-array pytorch


【解决方案1】:

如果我理解正确,您想要的不是常规数组,因为每个维度都有不同的范围,具体取决于观察到的轴(即,它不能在几何上表示为立方体 - 您的图片不是 (n,n,n) 数组)。

不管怎样,在后面有点冗长的 sn-p 中,我们创建了一个 (5,5,5) 测试 3D 数组,从中可以对 (3,3,3) 数组进行采样。然后我们连续连接以获得原始数组,然后我们屏蔽不需要的单元格,因此输出就是您的图片显示的内容。请注意,在使用布尔 Numpy 数组时,您可以将逻辑操作替换为 +*

import numpy as np

# Define dummy 3D field
n = 5
xx, yy, zz = np.ogrid[0:n, 0:n, 0:n]
field = np.sin(xx) + np.cos(yy) + np.tan(zz)

# Indices of 3 innermost elements - to form (3,3,3) array
i1, i2 = n//2 - 1, n//2 + 1
# Inner 3D array
subfield = np.copy(field)[i1:i2+1, i1:i2+1, i1:i2+1]

# Indices of "inferior" pads
x1 = y1 = z1 = np.arange(i1 - 1, i1)
# Indices of "superior" pads
x2 = y2 = z2 = np.arange(i2 + 1, i2 + 2)

# Padding in axis 0 (x)
padded = np.concatenate((field[x1, i1:i2+1, i1:i2+1], subfield))
padded = np.concatenate((padded, field[x2, i1:i2+1, i1:i2+1]))
# Padding in axis 1 (y)
padded = np.concatenate((field[i1-1:i2+2, y1, i1:i2+1], padded), axis = 1)
padded = np.concatenate((padded, field[i1-1:i2+2, y2, i1:i2+1]), axis = 1)
# Padding in axis 2 (z)
padded = np.concatenate((field[i1-1:i2+2, i1-1:i2+2, z1], padded), axis = 2)
padded = np.concatenate((padded, field[i1-1:i2+2, i1-1:i2+2, z2]), axis = 2)

# Check padded array is equal to original 3D array
print(np.all(padded == field))

## We now mask unwanted cells
indices = np.indices(padded.shape)
idx1, idx2 = indices == 0, indices == n - 1

xi, xf = idx1[0], idx2[0]
yi, yf = idx1[1], idx2[1]
zi, zf = idx1[2], idx2[2]

# Logical operations to mask proper slices
xm = (xi + xf) * (yi + yf + zi + zf)            # masking in axis 0
ym = (yi + yf) * (xi + xf + zi + zf)            # masking in axis 1
zm = (zi + zf) * (yi + yf + xi + xf)            # masking in axis 2

mask = xm + ym + zm
# Masked (5,5,5) array
masked_padded = np.ma.masked_where(mask, padded)

顺便说一句,必须有更优雅的方法来实现相同的结果,但我没有那么多使用 Numpy 的高级索引:P

【讨论】:

    猜你喜欢
    • 2019-12-28
    • 2018-10-05
    • 1970-01-01
    • 2019-11-24
    • 1970-01-01
    • 2015-06-11
    • 2014-07-15
    • 1970-01-01
    • 2018-11-30
    相关资源
    最近更新 更多