vibespatial.raster.label

Connected component labeling, sieve filtering, and morphology.

CPU baseline uses scipy.ndimage. GPU path uses custom NVRTC union-find kernels (kernels/ccl.py) and morphology stencil kernels (kernels/morphology.py).

ADR-0040: CCCL Connected Component Labeling

Attributes

Functions

label_connected_components(...)

Label connected components in a raster.

label_gpu(→ vibespatial.raster.buffers.OwnedRasterArray)

GPU connected component labeling using iterative union-find.

make_structuring_element(→ numpy.ndarray)

Build a binary structuring element (SE) for morphological operations.

morphology_gpu(...)

GPU binary morphology using NVRTC 3x3 stencil kernels.

raster_morphology(...)

Apply binary morphological operation to a raster.

raster_morphology_blackhat(...)

Black top-hat transform: morphological closing minus original.

raster_morphology_tophat(...)

White top-hat transform: original minus morphological opening.

sieve_filter(→ vibespatial.raster.buffers.OwnedRasterArray)

Remove small connected components from a labeled raster.

Module Contents

vibespatial.raster.label.label_connected_components(raster: vibespatial.raster.buffers.OwnedRasterArray, *, connectivity: int = 4, use_gpu: bool | None = None) vibespatial.raster.buffers.OwnedRasterArray

Label connected components in a raster.

Each group of connected nonzero (and non-nodata) pixels receives a unique integer label. Background (zero or nodata) pixels get label 0.

For multiband rasters, each band is labeled independently: the foreground of each band is labeled as a separate 2-D connected component analysis. The output has the same band count as the input.

Parameters

rasterOwnedRasterArray

Input raster. Nonzero values are foreground.

connectivityint

4 or 8 neighbor connectivity.

use_gpubool or None

Force GPU (True), force CPU (False), or auto-dispatch (None). Auto uses GPU when available and pixel count exceeds threshold.

Returns

OwnedRasterArray

Integer-labeled raster where each connected component has a unique label.

vibespatial.raster.label.label_gpu(raster: vibespatial.raster.buffers.OwnedRasterArray, *, connectivity: int = 4) vibespatial.raster.buffers.OwnedRasterArray

GPU connected component labeling using iterative union-find.

Multiband rasters are labeled per-band independently via dispatch_per_band_gpu.

Uses NVRTC kernels: init_labels -> local_merge -> pointer_jump (iterate) -> relabel to compact sequential labels 1..N.

Optimizations over naive union-find: - Path-splitting find_root with atomicCAS (reduces tree height in-place) - Lock-free union via atomicCAS (avoids atomicMin serialization on roots) - Asymmetric neighbor scan (each edge processed once, not twice) - Pointer jump runs to full convergence (no fixed iteration cap) - Compact relabel via direct LUT (O(1) per pixel, no binary search) - All relabel computation on device (no D->H->D ping-pong) - Occupancy-based launch configs (no hardcoded block sizes) - Grid-stride loops in 1D kernels for wave-quantization robustness - Single d_changed buffer reused (no per-iteration allocation)

Parameters

rasterOwnedRasterArray

Input raster. Nonzero values are foreground.

connectivityint

4 or 8 neighbor connectivity.

Returns

OwnedRasterArray

HOST-resident integer-labeled raster (int32, nodata=0).

vibespatial.raster.label.make_structuring_element(shape: str, size: int | tuple[int, int]) numpy.ndarray

Build a binary structuring element (SE) for morphological operations.

Parameters

shapestr

One of 'rect', 'cross', 'disk'.

sizeint or (int, int)

For 'rect' and 'cross': side length (int) or (height, width). For 'disk': radius as int (the SE will be (2*r+1, 2*r+1)). Sizes must be odd.

Returns

np.ndarray

2-D uint8 array with 1s for active SE positions.

Raises

ValueError

If shape is unknown or size is even.

vibespatial.raster.label.morphology_gpu(raster: vibespatial.raster.buffers.OwnedRasterArray, operation: str, *, connectivity: int = 4, iterations: int = 1) vibespatial.raster.buffers.OwnedRasterArray

GPU binary morphology using NVRTC 3x3 stencil kernels.

Parameters

rasterOwnedRasterArray

Input binary raster (nonzero = foreground).

operationstr

One of “erode”, “dilate”, “open”, “close”.

connectivityint

4 or 8 neighbor connectivity for the structuring element.

iterationsint

Number of times to apply the operation.

Returns

OwnedRasterArray

HOST-resident result raster.

vibespatial.raster.label.raster_morphology(raster: vibespatial.raster.buffers.OwnedRasterArray, operation: str, *, connectivity: int = 4, iterations: int = 1, structuring_element: numpy.ndarray | None = None, use_gpu: bool | None = None) vibespatial.raster.buffers.OwnedRasterArray

Apply binary morphological operation to a raster.

Parameters

rasterOwnedRasterArray

Input binary raster (nonzero = foreground).

operationstr

One of “erode”, “dilate”, “open”, “close”.

connectivityint

4 or 8 neighbor connectivity for the structuring element. Ignored when structuring_element is provided.

iterationsint

Number of times to apply the operation.

structuring_elementnp.ndarray or None

Custom structuring element (2-D uint8 array with odd dimensions). If None, falls back to the legacy 3x3 SE based on connectivity. Use make_structuring_element() to build presets.

use_gpubool or None

Force GPU (True), force CPU (False), or auto-dispatch (None).

Returns

OwnedRasterArray

Result raster.

vibespatial.raster.label.raster_morphology_blackhat(raster: vibespatial.raster.buffers.OwnedRasterArray, structuring_element: numpy.ndarray | None = None, *, connectivity: int = 4, use_gpu: bool | None = None) vibespatial.raster.buffers.OwnedRasterArray

Black top-hat transform: morphological closing minus original.

Extracts dark features (holes) smaller than the structuring element. Multiband rasters are processed per-band independently.

Parameters

rasterOwnedRasterArray

Input binary raster (nonzero = foreground).

structuring_elementnp.ndarray or None

Custom SE (2-D uint8, odd dimensions). Defaults to 3x3 from connectivity.

connectivityint

4 or 8 (used only if structuring_element is None).

use_gpubool or None

Force GPU (True), force CPU (False), or auto-dispatch (None).

Returns

OwnedRasterArray

Pixels that were added by closing (dark detail / holes filled).

vibespatial.raster.label.raster_morphology_tophat(raster: vibespatial.raster.buffers.OwnedRasterArray, structuring_element: numpy.ndarray | None = None, *, connectivity: int = 4, use_gpu: bool | None = None) vibespatial.raster.buffers.OwnedRasterArray

White top-hat transform: original minus morphological opening.

Extracts bright features smaller than the structuring element. Multiband rasters are processed per-band independently.

Parameters

rasterOwnedRasterArray

Input binary raster (nonzero = foreground).

structuring_elementnp.ndarray or None

Custom SE (2-D uint8, odd dimensions). Defaults to 3x3 from connectivity.

connectivityint

4 or 8 (used only if structuring_element is None).

use_gpubool or None

Force GPU (True), force CPU (False), or auto-dispatch (None).

Returns

OwnedRasterArray

Pixels that were removed by opening (bright detail).

vibespatial.raster.label.sieve_filter(labeled: vibespatial.raster.buffers.OwnedRasterArray, min_size: int, *, connectivity: int = 4, replace_value: int = 0, use_gpu: bool | None = None) vibespatial.raster.buffers.OwnedRasterArray

Remove small connected components from a labeled raster.

Parameters

labeledOwnedRasterArray

Integer-labeled raster (e.g., from label_connected_components).

min_sizeint

Minimum pixel count to keep a component.

connectivityint

4 or 8 neighbor connectivity (used for counting).

replace_valueint

Value to assign to removed components (default 0 = background).

use_gpubool or None

Force GPU (True), force CPU (False), or auto-dispatch (None). Auto uses GPU when available and pixel count exceeds threshold.

Returns

OwnedRasterArray

Sieved raster with small components replaced.

vibespatial.raster.label.logger