Connected Components 3D
Connected Components 3D (cc3d) is a Python library for performing connected component labeling on discrete and continuous multilabel 3D and 2D images. It efficiently handles 26, 18, and 6 connected variants for 3D images, and 4 or 8 connected variants for 2D images, including support for periodic boundaries. The library is currently at version 3.26.1 and is actively maintained, offering significant performance improvements over general-purpose libraries for multi-label and large volumetric datasets.
Common errors
-
numpy.ufunc size changed, may indicate binary incompatibility. Expected 216 from C header, got 192 from PyObject
cause Mismatch between the NumPy version `connected-components-3d` was compiled against and the currently installed NumPy version, often due to an upgrade or environment change.fixRun `pip install --upgrade numpy` and then reinstall `connected-components-3d` using `pip install connected-components-3d --no-binary :all:` to force recompilation against the current NumPy. This requires a C++ compiler. -
ModuleNotFoundError: No module named 'cc3d'
cause The `connected-components-3d` package was not installed correctly, or the Python environment where it was installed is not active.fixEnsure the package is installed in your current environment by running `pip install connected-components-3d`. If the issue persists, verify your active Python environment or reinstall. -
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
cause Attempting to use a NumPy array directly in a boolean context (e.g., `if array:`) instead of applying a boolean operation like `np.any()` or `np.all()`. This is a general NumPy error but can occur if output of cc3d is not handled properly.fixWhen checking for conditions on the output `labels_out` array, use explicit boolean checks, e.g., `if np.any(labels_out > 0):` or `if (labels_out == some_label).any():`.
Warnings
- breaking Older versions of connected-components-3d (pre-1.16 numpy compatibility) may exhibit 'numpy.ufunc size changed, may indicate binary incompatibility' errors, especially when the installed numpy version differs from the one it was compiled against.
- gotcha When working with continuously valued raw data images (e.g., grayscale), ensure proper use of the `delta` argument to define the threshold for connecting values. Incorrect `delta` values can lead to over- or under-segmentation.
- gotcha For images that cross periodic boundaries (e.g., global climate data), ensure `periodic_boundary=True` is set in `cc3d.connected_components`. Older workarounds for this scenario can be less efficient and lead to incorrect labeling.
- gotcha The `connectivity` parameter defines the neighborhood for component labeling. Using the wrong connectivity (e.g., 6-connected vs. 26-connected for 3D) can significantly alter labeling results, especially for complex shapes or sparse data.
Install
-
pip install connected-components-3d -
pip install numpy pip install connected-components-3d --no-binary :all:
Imports
- connected_components
from connected_components_3d import connected_components
import cc3d ... labels_out = cc3d.connected_components(data)
Quickstart
import cc3d
import numpy as np
# Create a sample 3D binary image
labels_in = np.zeros((10, 10, 10), dtype=np.int32)
labels_in[2:5, 2:5, 2:5] = 1
labels_in[6:8, 6:8, 6:8] = 1
labels_in[4,4,4] = 0 # Introduce a gap for demonstration
print(f"Input shape: {labels_in.shape}, dtype: {labels_in.dtype}")
# Perform connected component labeling with 26-connectivity (default)
# Also return the number of connected components (N)
labels_out, N = cc3d.connected_components(labels_in, return_N=True, connectivity=26)
print(f"\nOutput labeled image (slice 5):\n{labels_out[:,:,5]}")
print(f"Number of connected components found: {N}")
# Example of extracting a single component
# for segid in range(1, N + 1):
# extracted_component = (labels_out == segid).astype(labels_in.dtype)
# print(f"Component {segid} volume: {np.sum(extracted_component)}")