【问题标题】:Crop area from 3d array从 3d 阵列裁剪区域
【发布时间】:2026-02-01 06:45:01
【问题描述】:

我有一个形状为(400, 512, 512) 的 3D numpy 数组,并且我有边界框,例如:

[376, 250, 206]
[380, 256, 211] 

现在,我想从数组中裁剪边界框区域并进行可视化。通常在二维数组/图像中,我们可以使用最小最大值进行裁剪,例如:

img[y:y + h, x:x + w]

但我不认为在 3D 数组中是这样的,因为 z 轴也参与其中。谁能建议任何示例如何使用最小最大边界框坐标从 3D numpy 数组中裁剪区域?最后,我将在提取的边界框区域中拟合一个圆柱体。

编辑:我想要主大 3D 数组的边界框内的所有索引及其强度值。 我可以这样做:

big_3d_array[z1:z2, x1:x2, y1:y2]
where,    
z1 = 376, z2 = 380, x1 = 250, x2 = 256, y1=206, y2= 211

现在这种方法的问题是我只能得到强度值,不能得到指数。此外,我不确定是否使用这种方法获取边界框内的所有坐标。因为在 3d 空间边界框应该有 8 个角点。这里我只有边界框的最小值。

【问题讨论】:

  • img[y:y+h, x:x+w, :]
  • 为什么取消选择答案?
  • 感谢@MadPhysicist。第一次读的时候。看起来不错。你的答案是正确的。但我看起来是这样的:link 使用该 bbox 的最小最大坐标从 bbox 内的 3d 数组中获取所有点。可能是您的答案可以解决问题。我可能误会了。
  • 那你真的需要把问题说清楚。 bbox 是在数组索引中还是在数据的 x-y-z 坐标中?请提供一个有意义的例子来说明你想要什么
  • 为什么链接在 3D 中不适合您?您在问题中所做的根本没有遵循链接的建议。要么该解决方案有效,要么我的解决方案有效,但除非您展示您想要什么以及您做了什么,否则很难说。

标签: python numpy


【解决方案1】:

假设边界框数组由每个维度的三列组成,行是开始和结束坐标,按顺序:

c = np.array([[376, 250, 206]
              [380, 256, 211]])

让我们来看看basic index 3D:

a = np.random.randint(10, size=(400, 512, 512))

你这样写一个索引:

a[376:380, 250:256, 206:211]

这个索引代表对a.__getitem__(实际上是type(a).__getitem__(a, ...)的函数调用。参数是切片对象的元组。元组由括号中的逗号指定,当使用:字符时创建切片:

a.__getitem__((slice(376, 380), slice(250, 256), slice(206, 211)))

使用此信息,您可以通过几种不同的方式索引数组:

a[c[0, 0]:c[1, 0], c[0, 1]:c[1, 1], c[0, 2]:c[1, 2]]
a[tuple(slice(*x) for x in c.T)]

第二种方式通常更具可扩展性。

Numpy 提供了另一种索引数组的方法,除了切片,称为advanced or fancy indexing。在此方法中,您提供坐标数组 broadcast 一起形成您想要的输出形状。例如:

ix = np.arange(*c[:, 0]).reshape(-1, 1, 1)
iy = np.arange(*c[:, 1]).reshape(-1, 1)
iz = np.arange(*c[:, 2])
a[ix, iy, iz]

有一个名为 np.ogrid 的辅助对象,它可以让您更无缝地创建索引数组:

np.ogrid[tuple(slice(*x) for x in c.T)]

在所有情况下,如果您的边界框包含在上限上,则需要在将其用于索引之前对其进行递增:

c[1, :] += 1

【讨论】: