在标签贴图中围绕线段获取边界框的最快方法

时间:2014-07-15 20:31:44

标签: python performance algorithm numpy

3D标签图是矩阵,其中每个像素(体素)具有整数标签。这些值预计是连续的,这意味着标签k的段不会被分段。

鉴于此类标签贴图(细分),在Python中获取每个细分周围最小边界框坐标的最快方法是什么?

我尝试了以下内容:

  • 使用multiindex迭代器(来自numpy.nditer)遍历矩阵并构造反向索引字典。这意味着对于每个标签,您将获得标签所在的每个体素的3个坐标。
  • 对于每个标签,获取每个坐标的最大值和最小值。

好处是你可以在一次O(N)传球中获得所有位置信息。不好的是,我不需要这些详细信息。我只需要四肢,所以可能有一种更快的方法来实现这一点,使用一些比这么多列表追加更快的numpy函数。有什么建议吗?

在我的机器上通过矩阵大约需要8秒钟,所以摆脱它会很棒。为了了解数据,标签贴图中有几百个标签。标签贴图的大小可以是700x300x30或300x300x200或类似的东西。

编辑:现在每个标签只存储更新的最大和最小坐标。这消除了维护和存储所有这些大型列表(追加)的需要。

1 个答案:

答案 0 :(得分:3)

如果我正确理解你的问题,你就有了一组体素,你希望每个轴都有一个组的极值。

让我们定义:

  • 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').max * np.ones((3, labmax + 1), dtype='int32')
b_last = np.iinfo('int32').max * np.ones((3, labmax + 1), dtype='int32')

# run through all 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_firstb_last都将是最大int32值。

我在计算机上尝试了这个,对于(300,300,200)阵列,需要大约1秒才能找到值。