3D图像 高效连通域标记算法 connected-components-3d

对于二值图像的连通域标记算法,常见的使用方法是opencv里的connectedComponents()以及connectedComponentsWithStats(),这个实现方法很快,使用也便捷,但无法适用于3D图像。skimage中的skimage.measure.label()以及skimage.measure.regionprops()可以得到2D和3D图像的连通域和相关的统计信息,但这个实现方法较慢,对于尺寸大的3D图像(比如512*512*512尺寸的医学影像)并非最优解。

这里简单介绍一个提速的2D/3D图像连通域标记的Python/C++开源包:connected-components-3d(link)。这个包的实现结合了two-pass算法,Array-Based Union-Find并查集来存储label信息,对于3D图像的处理更快,还能够直接处理非二值图像,下载方便,使用方法简单,强烈推荐~

下载和使用

Python版本直接pip install下载,C++版本可以去github(link)上下载源码。

pip install connected-components-3d

使用:

import cc3d
import numpy as np

labels_in = np.ones((512, 512, 512), dtype=np.int32)
labels_out = cc3d.connected_components(labels_in, connectivity=26) 

详情请直接去github上并支持原作者:)

2D的情况

我们先用较为简单直观的2D图像来做示例,再扩展到3D图像。这里举例的是8邻域的连通域。主要思路是Two Pass算法,这个算法包括两次扫描,大体过程是这样的:

  • 第一次扫描:依次扫描每个像素。每遇到一个前景像素,判断是否周围像素已有label。如果已有标记过label,就用这个label;如果没有,则标记上新的label。如果有两个label相邻,记录下相邻关系。
  • 第二次扫描:遇到有label的前景像素,根据之前记录的相邻关系进行重新label。

这个算法的实现中有可以提速的点:

  • 相邻关系的记录使用Union-Find并查集,也能适用于非二值图,可以用一个array来实现。

  • 在第一遍扫描的时候,对于前景像素的判断,需要对于其周围的8个像素都遍历取值,这个过程是比较慢的。我们是从上到下、从左到右扫描的,有些点的状态是已知的,经过对于拓扑关系的总结,我们可以只用8邻域中左上角的4个点来对当前前景点做出判断。这个判断关系可以用决策树来表示,并通过优化决策树结构(判断步骤最少),可以得到对于一个前景点标记的最终判断条件。

3D图像 高效连通域标记算法 connected-components-3d_第1张图片

值得一提的是,对于2D的情况,可以对于多个像素合成block,以block为单位来一次性判断和赋值多个像素点来提高速度(Blocked Based Decision Tree)。
PS. 这个方法在2D图像的情况下很快,但目前还未有很好的3D图像版本的实现。

3D图像 高效连通域标记算法 connected-components-3d_第2张图片

3D的情况

我们可以想象,把之前的2D图像扩展成3D,这里以26邻域连通域举例。我们的步骤是一样的,仍旧是Two Pass,但在第一次扫描时,判断每个前景像素点的时间更久了,因为周围有26个点需要取值来进行判断。我们用之前相同的优化逻辑,同样利用拓扑和优化决策树找到最优的判断条件。如果要看详细的具体判断条件可以直接看论文或者看代码。

3D图像 高效连通域标记算法 connected-components-3d_第3张图片

这个包的作者还添加了一些代码实现上的加速:

  • 算法的具体逻辑代码使用C++,2D或者3D图像都转换成1D array处理。Python版本接口使用Cython来进行数据结构转换。
  • 从Two Pass改成了Four Pass。在开始之前提到的Two Pass算法之前,多加了两遍遍历来得到一些已知的统计信息,以对后续的操作进行剪枝。
    • 最开始的额外第一遍遍历:预估之后的Two Pass算法会有多少个临时的label。因为我们要用一个array来当作并查集来存储所有label的相邻关系,大概知道会有多少label可以直接申请多大空间的array,节省空间以及减少caching的时间。预估的方法是遍历每一行,记录label之间可能出现多少次转换(relabel)。
    • 额外第二遍遍历:预估前景点的位置。比如说对于每一行,记录下前景点出现的index区间,这样在之后的遍历不需要遍历整行。因为大部分图片的前景点可能是比背景点的个数少得多,这样可以节省后续的很多时间。但可以根据数据的具体情况调整。
    • Two Pass算法的两次遍历
  • 多设置一些剪枝条件,以减少不必要的时间开销。比如,如果额外第一次遍历所得到的临时label个数为0,就可以直接返回,因为没有前景点。

Reference

  1. W. Silversmith. “cc3d: Connected Components on Multilabel 3D Images”. January 2021. (link)
  2. A. Rosenfeld and J. Pfaltz. “Sequential Operations in Digital Picture Processing”. Journal of the ACM. Vol. 13, Issue 4, Oct. 1966, Pg. 471-494. doi: 10.1145/321356.321357 (link)
  3. R. E. Tarjan. “Efficiency of a good but not linear set union algorithm”. Journal of the ACM, 22:215-225, 1975. (link)
  4. K. Wu, E. Otoo, K. Suzuki. “Two Strategies to Speed up Connected Component Labeling Algorithms”. Lawrence Berkeley National Laboratory. LBNL-29102, 2005. (link)
  5. S. Selkow. “The Tree-to-Tree Editing Problem”. Information Processing Letters. Vol. 6, No. 6. June 1977. doi: 10.1016/0020-0190(77)90064-3 (link)
  6. C. Grana, D. Borghesani, R. Cucchiara. “Optimized Block-based Connected Components Labeling with Decision Trees”. IEEE Transactions on Image Processing. Vol. 19, Iss. 6. June 2010. doi: 10.1109/TIP.2010.2044963 (link)
  7. P. Sutheebanjard. “Decision Tree for 3-D Connected Components Labeling”. Proc. 2012 International Symposium on Information Technology in Medicine and Education. doi: 10.1109/ITiME.2012.6291402 (link)
  8. C. Grana, D. Borghesani, R. Cucchiara. “Fast Block Based Connected Components Labeling”. Proc. 16th IEEE Intl. Conf. on Image Processing. 2009. doi: 10.1109/ICIP.2009.5413731 (link)
  9. L. He, Y. Chao and K. Suzuki, “A Linear-Time Two-Scan Labeling Algorithm”, IEEE International Conference on Image Processing, vol. 5, pp. 241-244, 2007.

你可能感兴趣的:(算法,算法,图像处理,图形学,计算机视觉)