_label.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. from scipy import ndimage
  2. from ._ccomp import label_cython as clabel
  3. def _label_bool(image, background=None, return_num=False, connectivity=None):
  4. """Faster implementation of clabel for boolean input.
  5. See context: https://github.com/scikit-image/scikit-image/issues/4833
  6. """
  7. from ..morphology._util import _resolve_neighborhood
  8. if background == 1:
  9. image = ~image
  10. if connectivity is None:
  11. connectivity = image.ndim
  12. if not 1 <= connectivity <= image.ndim:
  13. raise ValueError(
  14. f'Connectivity for {image.ndim}D image should '
  15. f'be in [1, ..., {image.ndim}]. Got {connectivity}.'
  16. )
  17. footprint = _resolve_neighborhood(None, connectivity, image.ndim)
  18. result = ndimage.label(image, structure=footprint)
  19. if return_num:
  20. return result
  21. else:
  22. return result[0]
  23. def label(label_image, background=None, return_num=False, connectivity=None):
  24. r"""Label connected regions of an integer array.
  25. Two pixels are connected when they are neighbors and have the same value.
  26. In 2D, they can be neighbors either in a 1- or 2-connected sense.
  27. The value refers to the maximum number of orthogonal hops to consider a
  28. pixel/voxel a neighbor::
  29. 1-connectivity 2-connectivity diagonal connection close-up
  30. [ ] [ ] [ ] [ ] [ ]
  31. | \ | / | <- hop 2
  32. [ ]--[x]--[ ] [ ]--[x]--[ ] [x]--[ ]
  33. | / | \ hop 1
  34. [ ] [ ] [ ] [ ]
  35. Parameters
  36. ----------
  37. label_image : ndarray of dtype int
  38. Image to label.
  39. background : int, optional
  40. Consider all pixels with this value as background pixels, and label
  41. them as 0. By default, 0-valued pixels are considered as background
  42. pixels.
  43. return_num : bool, optional
  44. Whether to return the number of assigned labels.
  45. connectivity : int, optional
  46. Maximum number of orthogonal hops to consider a pixel/voxel
  47. as a neighbor.
  48. Accepted values are ranging from 1 to input.ndim. If ``None``, a full
  49. connectivity of ``input.ndim`` is used.
  50. Returns
  51. -------
  52. labels : ndarray of dtype int
  53. Labeled array, where all connected regions are assigned the
  54. same integer value.
  55. num : int, optional
  56. Number of labels, which equals the maximum label index and is only
  57. returned if return_num is `True`.
  58. See Also
  59. --------
  60. skimage.measure.regionprops
  61. skimage.measure.regionprops_table
  62. References
  63. ----------
  64. .. [1] Christophe Fiorio and Jens Gustedt, "Two linear time Union-Find
  65. strategies for image processing", Theoretical Computer Science
  66. 154 (1996), pp. 165-181.
  67. .. [2] Kensheng Wu, Ekow Otoo and Arie Shoshani, "Optimizing connected
  68. component labeling algorithms", Paper LBNL-56864, 2005,
  69. Lawrence Berkeley National Laboratory (University of California),
  70. http://repositories.cdlib.org/lbnl/LBNL-56864
  71. Examples
  72. --------
  73. >>> import numpy as np
  74. >>> x = np.eye(3).astype(int)
  75. >>> print(x)
  76. [[1 0 0]
  77. [0 1 0]
  78. [0 0 1]]
  79. >>> print(label(x, connectivity=1))
  80. [[1 0 0]
  81. [0 2 0]
  82. [0 0 3]]
  83. >>> print(label(x, connectivity=2))
  84. [[1 0 0]
  85. [0 1 0]
  86. [0 0 1]]
  87. >>> print(label(x, background=-1))
  88. [[1 2 2]
  89. [2 1 2]
  90. [2 2 1]]
  91. >>> x = np.array([[1, 0, 0],
  92. ... [1, 1, 5],
  93. ... [0, 0, 0]])
  94. >>> print(label(x))
  95. [[1 0 0]
  96. [1 1 2]
  97. [0 0 0]]
  98. """
  99. if label_image.dtype == bool:
  100. return _label_bool(
  101. label_image,
  102. background=background,
  103. return_num=return_num,
  104. connectivity=connectivity,
  105. )
  106. else:
  107. return clabel(label_image, background, return_num, connectivity)