3D标签图是矩阵,其中每个像素(体素)都有一个整数标签。这些值应该是连续的,这意味着标记为k
的分段不会被分段。
给出这样的标签图(分段),在Python中获取围绕每个分段的最小边界框的坐标的最快方法是什么?
我尝试了以下操作:
numpy.nditer
)遍历矩阵并构造一个反向索引字典。这意味着对于每个标签,您将获得该标签所在的每个体素的3个坐标。 好处是,您可以在一O(N)次通过中获得所有位置信息。不好的是,我不需要此详细信息。我只需要四肢,所以可能会使用一些numpy函数来执行此操作,该方法比许多附加列表要快。有什么建议吗?
一次通过矩阵在我的计算机上花费了大约8秒钟,因此摆脱它非常好。为了对数据有所了解,标签图中有数百个标签。标签图的大小可以是700x300x30或300x300x200或类似的尺寸。
编辑:现在,每个标签的每个坐标仅存储更新的最大值和最小值。这样就无需维护和存储所有这些大列表(追加)。
如果我正确理解了您的问题,则有几组体素,并且您希望在每个轴上都有一组的极限。
让我们定义:
arr
:3D整数标签数组
labels
:标签列表(整数0..labmax)
代码:
import numpy as np
# number of highest label:
labmax = np.max(labels)
# maximum and minimum positions along each axis (initialized to very low and high values)
b_first = np.iinfo('int32').min * np.ones((3, labmax + 1), dtype='int32')
b_last = np.iinfo('int32').max * np.ones((3, labmax + 1), dtype='int32')
# run through all of the dimensions making 2D slices and marking all existing labels to b
for dim in range(3):
# create a generic slice object to make the slices
sl = [slice(None), slice(None), slice(None)]
bf = b_first[dim]
bl = b_last[dim]
# go through all slices in this dimension
for k in range(arr.shape[dim]):
# create the slice object
sl[dim] = k
# update the last "seen" vector
bl[arr[sl].flatten()] = k
# if we have smaller values in "last" than in "first", update
bf[:] = np.clip(bf, None, bl)
此操作后,我们有六个向量给出每个轴的最小和最大索引。例如,沿标签13
的第二轴的边界值为b_first[1][13]
和b_last[1][13]
。如果缺少某些标签,则所有对应的b_first
和b_last
将是最大int32
值。
我在计算机上尝试过,对于(300,300,200)数组,大约需要1秒钟才能找到值。