@@ -1478,6 +1478,81 @@ unspecified.
14781478labels = bic.segmentation.watershed(image, markers, mask = optional_mask)
14791479```
14801480
1481+ ### Connected-Components Labeling
1482+
1483+ ` bioimage-cpp ` provides pixel-grid connected-components labeling for 2D and
1484+ 3D arrays, mirroring ` skimage.measure.label ` . Two non-background pixels share
1485+ a component iff there is a path of ` connectivity ` -neighbour steps between
1486+ them along which the input value is constant.
1487+
1488+ Skimage:
1489+
1490+ ``` python
1491+ from skimage.measure import label
1492+
1493+ labels = label(image, background = 0 , connectivity = None )
1494+ ```
1495+
1496+ bioimage-cpp:
1497+
1498+ ``` python
1499+ import bioimage_cpp as bic
1500+
1501+ labels = bic.segmentation.label(image, background = 0 , connectivity = None )
1502+ ```
1503+
1504+ Vigra has a closely related entry point on binary / labeled inputs:
1505+
1506+ ``` python
1507+ import vigra.analysis as va
1508+
1509+ labels = va.labelMultiArrayWithBackground(
1510+ image, neighborhood = " direct" , background_value = 0 ,
1511+ )
1512+ ```
1513+
1514+ ` bic.segmentation.label ` covers both cases — it labels equal-value runs (as
1515+ ` skimage.measure.label ` does), and for binary masks it agrees with vigra's
1516+ ` labelMultiArrayWithBackground ` partition. ` neighborhood="direct" ` maps to
1517+ ` connectivity=1 ` , ` neighborhood="indirect" ` maps to ` connectivity=image.ndim ` .
1518+
1519+ Important migration notes:
1520+
1521+ - Supported input dtypes are ` bool ` , ` uint8 ` , ` uint16 ` , ` uint32 ` , ` uint64 ` ,
1522+ ` int32 ` , ` int64 ` . Floating-point inputs are rejected. Non-contiguous
1523+ arrays are copied to contiguous memory.
1524+ - ` connectivity ` is an integer in ` [1, image.ndim] ` . ` 1 ` is orthogonal
1525+ neighbours only (4-connectivity in 2D, 6-connectivity in 3D);
1526+ ` image.ndim ` enables full diagonal connectivity (8-connectivity in 2D,
1527+ 26-connectivity in 3D); ` 2 ` in 3D is 18-connectivity. ` connectivity=None `
1528+ defaults to ` image.ndim ` , matching ` skimage.measure.label ` .
1529+ - ` background ` is the pixel value treated as background. Background pixels
1530+ stay ` 0 ` in the output; other equal-valued pixels start at label ` 1 ` .
1531+ - The output dtype is always ` uint64 ` . ` skimage.measure.label ` returns
1532+ ` intp ` ; cast if you need bit-for-bit dtype parity.
1533+ - Output labels are dense, start at ` 1 ` , and are assigned in row-major
1534+ first-occurrence order — same convention as skimage.
1535+ - Passing a ` bool ` array enables an internal fast path that skips
1536+ per-pixel value-equality compares. Convert ` uint8 ` masks to ` bool ` first
1537+ if your data is binary.
1538+ - Only 2D and 3D inputs are supported in v1. ` skimage.measure.label `
1539+ accepts arbitrary ndim; loop over slices externally if you need 4D+.
1540+ - ` return_num=True ` from ` skimage.measure.label ` is not provided. Use
1541+ ` int(labels.max()) ` to get the component count.
1542+
1543+ Performance characteristics (single-threaded, against ` skimage 0.25 ` and
1544+ ` vigra 1.11 ` ):
1545+
1546+ - On integer inputs (` uint8 ` /` uint16 ` /…), bioimage-cpp clearly beats both
1547+ skimage and vigra across the tested grid (2D 512²–2048², 3D 64³–128³, all
1548+ connectivities, binary and multi-value). Typical margin is ** 1.5×–3×**
1549+ faster than skimage and ** 2×–8×** faster than vigra.
1550+ - On ` bool ` inputs, skimage ships a separately tuned 2D kernel that is very
1551+ fast at large sizes. bioimage-cpp matches it at small/medium sizes and on
1552+ all 3D cases; at 2D 2048² the skimage-bool path is currently ahead by
1553+ roughly 1.7×. Convert to ` uint8 ` to fall back onto the general path if
1554+ you need to win at every 2D size.
1555+
14811556## Vigra / fastfilters
14821557
14831558### Image Filters
0 commit comments