Source code for mathematicskit.topology.utils.raster

r"""Betti numbers of a binary image, as a ground truth for planar shapes.

A planar region's :math:`\beta_0` is its number of connected components
and :math:`\beta_1` the number of bounded components of its complement
(its holes). Counting both with :func:`scipy.ndimage.label` -- the
foreground with 8-connectivity and the background with 4-connectivity,
so that a diagonal pixel step joins the region and not the hole -- gives
the homology of a union of discs without building any complex, which is
how the nerve theorem is checked.
"""

from __future__ import annotations

import numpy as np
from scipy import ndimage

__all__ = ["planar_betti_numbers"]


[docs] def planar_betti_numbers(mask) -> tuple[int, int]: r"""The Betti numbers :math:`(\beta_0, \beta_1)` of the region drawn in a 2D boolean image. Parameters ---------- mask : array_like of bool, shape (rows, cols) True on the region. Returns ------- tuple of int Components and holes. Examples -------- >>> ring = np.ones((5, 5), dtype=bool) >>> ring[2, 2] = False >>> planar_betti_numbers(ring) (1, 1) """ region = np.pad(np.asarray(mask, dtype=bool), 1) _, components = ndimage.label(region, structure=np.ones((3, 3))) _, background = ndimage.label(~region) return int(components), int(background) - 1