通过3d数组沿任意线切割一定宽度的盒子

时间:2017-07-26 11:19:50

标签: python-2.7 numpy multidimensional-array slice

我有一个大的(600,600,600)numpy数组,里面装满了我的数据。现在,我想通过框中的任意一行以给定宽度从中提取区域。

对于线条,我在单独的numpy数组中的每个点都有x,y和z坐标。因此,让我们说数据框中的行有35个点,然后x,y和z数组的长度也都是35。我可以使用像这样的索引来提取沿着线本身的点

extraction = data[z,y,x]

现在理想情况下,我想通过执行以下操作来提取一个方框

extraction = data[z-3:z+3,y-3:y+3,z-3:z+3]

但是因为x,y和z是数组,所以这是不可能的。我能想到的唯一方法是通过每个点的for循环,所以

extraction = np.array([])
for i in range(len(x)):
    extraction = np.append(extraction,data[z[i]-3:z[i]+3,y[i]-3:y[i]+3,z[i]-3:z[i]+3])

然后重新整形提取数组。然而,这非常缓慢,并且在这个for-loop I中的每个切片之间会有一些重叠,以防止。

有没有简单的方法可以在没有for循环的情况下直接执行此操作?

编辑: 让我通过我提出的另一个想法来重新解释这个问题,这个想法也很慢。我有一条线穿过datacube。我有一个x,y和z坐标列表(坐标是datacube数组中的索引)以及定义该行的所有点。 例如,这些列表如下所示:

 x_line: [345 345 345 345 342 342 342 342 342 342 342 342 342 342 342 342]
 y_line: [540 540 540 543 543 543 543 546 546 546 549 549 549 549 552 552]
 z_line: [84 84 84 87 87 87 87 87 90 90 90 90 90 93 93 93]

如您所见,这些坐标中的一些是相同的,因为线条在不同的坐标中定义,然后分箱到数据框的分辨率。 现在我想掩盖数据立方体中距离大于3个单元格的所有单元格。 对于沿线的单个点(x_line [i],y_line [i],z_line [i]),这是相对容易的。我为datacube中的坐标创建了一个meshgrid,然后创建了一个零的掩码数组,并使所有内容都令人满意条件为1:

data = np.random.rand(600,600,600)
x_box,y_box,z_box = np.meshgrid(n.arange(600),n.arange(600),n.arange(600))
mask = np.zeros(np.shape(data))

for i in range(len(x_line)):
    distance = np.sqrt((x_box-x_line[i])**2 + (y_box-y_line[i])**2 + (z_box-z_line[i])**2)
    mask[distance <= 3] = 1.

extraction = data[mask == 1.]

这样做的好处是掩模阵列消除了重复提取的问题。但是,网格和距离计算都很慢。因此,可以直接在整个线上计算距离,而不必在每个线点上进行for循环,这样它就可以直接屏蔽距离任意线点3个单元格内的所有单元格。 ?

1 个答案:

答案 0 :(得分:0)

这个怎么样?

# .shape = (N,)
x, y, z = ...

# offsets in [-3, 3), .shape = (6, 6, 6)
xo, yo, zo = np.indices((6, 6, 6)) - 3

# box indices, .shape = (6, 6, 6, N)
xb, yb, zb = x + xo[...,np.newaxis], y + yo[...,np.newaxis], z + zo[...,np.newaxis]

# .shape = (6, 6, 6, N)
extractions = data[xb, yb, zb]

这会提取一系列6x6x6多维数据集,每个多维数据集“居中”在xyz

中的坐标上

这将产生重复的坐标,并且在边界附近的情况下失败

如果您将xyz保留在一个数组中,这样可以减少冗长,并且可以删除重复数据:

# .shape = (N,3)
xyz = ...

# offsets in [-3, 3), .shape = (6, 6, 6, 3)
xyz_offset = np.moveaxis(np.indices((6, 6, 6)) - 3, 0, -1)

# box indices, .shape = (6, 6, 6, N, 3)
xyz_box = xyz + xyz_offset[...,np.newaxis,:]

if remove_duplicates:
    # shape (M, 3)
    xyz_box = xyz_box.reshape(-1, 3)
    xyz_box = np.unique(xyz_box, axis=0)

xb, yb, zb = xyz_box
extractions = data[xb, yb, zb]