Skip to content

dilate_labels

patchworks.dilate_labels(fn: Callable[[np.ndarray], np.ndarray], iterations: int = 1, *, use_gpu: bool = False) -> Callable[[np.ndarray], np.ndarray]

Wrap a segmentation callable to grow its labels after each tile.

Applies a single-pass grey dilation to whatever fn returns, before tile_process/stage_tile trim the overlap halo and merge across tile boundaries — so dilated labels still stitch correctly at tile edges. Labels only grow into background: a voxel that already belongs to an object keeps it, so touching objects do not eat into each other (a bare max filter would let the higher id overwrite its neighbour). Where two labels grow into the same background voxel, the higher id takes it.

Parameters:

Name Type Description Default
fn Callable[[ndarray], ndarray]

Any segmentation function with the tile_process/stage_tile contract (one tile in, integer label array out).

required
iterations int

Pixels to grow each label by (grey-dilation footprint size 2 * iterations + 1, single pass). Default 1. Values <= 0 disable dilation — fn is returned unwrapped.

1
use_gpu bool

Dilate via cupyx instead of scipy. Independent of whatever backend fn itself uses internally.

False

Returns:

Type Description
Callable[[ndarray], ndarray]

Picklable function ready for tile_process/stage_tile. If iterations <= 0, this is fn itself.

Source code in src/patchworks/_postprocess.py
def dilate_labels(
    fn: Callable[[np.ndarray], np.ndarray],
    iterations: int = 1,
    *,
    use_gpu: bool = False,
) -> Callable[[np.ndarray], np.ndarray]:
    """Wrap a segmentation callable to grow its labels after each tile.

    Applies a single-pass grey dilation to whatever ``fn`` returns, before
    ``tile_process``/``stage_tile`` trim the overlap halo and merge across
    tile boundaries — so dilated labels still stitch correctly at tile
    edges. Labels only grow into background: a voxel that already belongs
    to an object keeps it, so touching objects do not eat into each other
    (a bare max filter would let the higher id overwrite its neighbour).
    Where two labels grow into the same background voxel, the higher id
    takes it.

    Parameters
    ----------
    fn : Callable[[np.ndarray], np.ndarray]
        Any segmentation function with the ``tile_process``/``stage_tile``
        contract (one tile in, integer label array out).
    iterations : int, optional
        Pixels to grow each label by (grey-dilation footprint size
        ``2 * iterations + 1``, single pass). Default 1. Values ``<= 0``
        disable dilation — ``fn`` is returned unwrapped.
    use_gpu : bool, optional
        Dilate via cupyx instead of scipy. Independent of whatever backend
        ``fn`` itself uses internally.

    Returns
    -------
    Callable[[np.ndarray], np.ndarray]
        Picklable function ready for ``tile_process``/``stage_tile``. If
        ``iterations <= 0``, this is ``fn`` itself.
    """
    if iterations <= 0:
        return fn
    return partial(_run, fn=fn, iterations=iterations, use_gpu=use_gpu)