加快图像标记

我有一堆 1000 张图像,其中包含超过 12 万个对象。在第三方软件中运行连接组件算法后,我得到了一张彩色图像,其中每个连接的对象都有一个标签、一个颜色和一个 ID 值。

我需要提取构成每个对象的体素坐标列表。

我已经编写了一个 Python 代码来提取这些信息,但它非常慢,因为它每分钟处理大约 30 个标签。因此,在最佳情况下,处理整个扫描需要 2 天以上的时间。

将堆栈转换为 3D Numpy 数组(img_stack_numpy)后,这里是代码的主要部分:

# Store the labels and its associated voxels in a dictionary
labels,counts = np.unique(img_stack_np,return_counts=True)
labels_list = list(labels)
dict_labels_and_voxels = {}

for label in labels_list:
    
    if label==0:  # We don't want to store the label 0 (background)
        continue
    
    index = np.where(img_stack_np == label)
    dict_labels_and_voxels[label] = [index]
    

我怎样才能提高它的速度?

iamhero3333 回答:加快图像标记

当前代码的主要问题在于 np.where(img_stack_np == label) 行。实际上,它为 700 * 700 * 1000 = 490,000,000 的 120,000 个值迭代 img_stack_nplabel_list 值,导致要检查 490,000 * 120,000 = 58,800,000 值。

您不需要为每个标签迭代 img_stack_np。您需要的是按值(即标签)对“体素”进行分类。您可以使用自定义排序来做到这一点:

  • 首先,将每个体素的位置存储在一个带有标签的数组中;
  • 然后,进行键值排序,其中标签是键,体素位置是值;
  • 然后,遍历已排序的项目以按标签对它们进行分组(或为简单起见使用效率较低的 np.unique);
  • 最后将每个组的位置存储在最终的字典中。

为了简单起见并限制内存使用,也可以使用基于索引的排序来代替键值排序。这可以通过 argsort 完成。这是一个示例代码:

s1,s2,s3 = img_stack_np.shape

# Classification by label.
# Remove the "kind='stable'" argument if you do not care about the ordering 
# of the voxel positions for a given label in the resulting dict (much faster).
index = np.argsort(img_stack_np,axis=None,kind='stable')
labels = img_stack_np.reshape(img_stack_np.size)[index]

# Generate the associated position
i1 = np.arange(s1).repeat(s2*s3)[index]
i2 = np.tile(np.arange(s2),s1).repeat(s3)[index]
i3 = np.tile(np.arange(s3),s1*s2)[index]

groupLabels,groupSizes = np.unique(img_stack_np,return_counts=True)
groupOffsets = np.concatenate(([0],counts.cumsum()))

dict_labels_and_voxels = {}

for i,label in enumerate(groupLabels):
    if label==0:
        continue
    start,end = groupOffsets[i],groupOffsets[i] + groupSizes[i]
    index = (i1[start:end],i2[start:end],i3[start:end])
    dict_labels_and_voxels[label] = [index]

这是在我的机器上使用 100x100x1000 基于整数的随机输入和 12000 个标签的结果:

Reference algorithm:                   363.29 s
Proposed algorithm (strict ordering):    3.91 s
Proposed algorithm (relaxed ordering):   2.02 s

因此,在这种情况下,建议的实施速度 快 180 倍
对于您指定的输入,它应该快几千倍

附加说明:

img_stack_np 中使用 float32 值会占用大量内存:700 * 700 * 1000 * 4 ~= 2 GB。如果可以,请使用 float16 甚至 in8/int16 类型。存储每个体素的位置也需要大量内存:从 3 GB(带有 int16)到 12 GB(带有 int64)。考虑使用更紧凑的数据表示或更小的数据集。如需进一步改进,请查看此 this post 以替换相当慢的 np.unique 调用。

本文链接:https://www.f2er.com/575572.html

大家都在问