Thanks to visit codestin.com
Credit goes to github.com

Skip to content

slic(mask=..., enforce_connectivity=True, min_size_factor=...) can assign the same label to two non-connected supervoxels #8295

Description

@cullen-peters

Description:

Expected behavior: every label returned when enforce_connectivity=True should refer to a single connected component.

Actual behavior: a small (below the minimum size) component can be assigned the same label id as a different component in the volume which it is not connected to.

Way to reproduce:

import numpy as np
from scipy import ndimage as ndi
from scipy.spatial.distance import cdist
from skimage.segmentation import slic

CONNECTIVITY_6 = ndi.generate_binary_structure(3, 1)

def connected_pieces(label_mask):
    labeled, n_pieces = ndi.label(label_mask, structure=CONNECTIVITY_6)
    return [np.argwhere(labeled == i) for i in range(1, n_pieces + 1)]

# Volume + mask with several small excluded ("below threshold") pockets.
shape = (24, 24, 24)
rng = np.random.default_rng(27)
volume = rng.integers(0, 255, size=shape + (3,)).astype(np.float64)
volume = ndi.uniform_filter(volume, size=(3, 3, 3, 1))

mask_rng = np.random.default_rng(27 + 1000)
mask = np.ones(shape, dtype=bool)
for _ in range(6):
    z, y, x = (mask_rng.integers(0, shape[i] - 2) for i in range(3))
    mask[z:z+2, y:y+2, x:x+2] = False

start_label = 1
segments = slic(
    volume, mask=mask, n_segments=80, compactness=5,
    enforce_connectivity=True, min_size_factor=0.3, max_size_factor=3,
    start_label=start_label, channel_axis=-1,
)

bg_label = start_label - 1
for lbl in np.unique(segments):
    if lbl == bg_label:
        continue
    pieces = connected_pieces(segments == lbl)
    if len(pieces) > 1:
        dist = min(
            cdist(pieces[i], pieces[j]).min()
            for i in range(len(pieces))
            for j in range(i + 1, len(pieces))
        )
        sizes = [len(p) for p in pieces]
        print(f"label {lbl}: {len(pieces)} disconnected pieces, sizes={sizes}, "
              f"min distance between pieces={dist:.2f}")

Output:

label 28: 2 disconnected pieces, sizes=[2, 358], min distance between pieces=2.00

This means that two non-connected components were both assigned the label 28.

Version information:

3.11.16 (main, Aug 12 2026, 23:03:19) [Clang 21.0.0 (clang-2100.1.1.101)]
macOS-26.6.2-arm64-arm-64bit
scikit-image version: 0.26.0
numpy version: 2.4.6

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions