当前代码的主要问题在于 np.where(img_stack_np == label)
行。实际上,它为 700 * 700 * 1000 = 490,000,000
的 120,000 个值迭代 img_stack_np
的 label_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