fastlabelops
Fast CPU primitives for integer instance masks. Requires Python 3.12+.
fastlabelops provides five small operations commonly needed around instance segmentation and
labeled images:
label_counts— count elements for each observed labelrelabel_sequential— compact arbitrary IDs to sequential labelsremove_small_objects— remove labeled objects at or below a size thresholdoverlap_counts— count only observed label-pair overlaps between two masksregionprops— compute a small set of common per-label properties in 2D
The package is deliberately low-level: NumPy arrays in, NumPy arrays out, one compiled C++ extension, no scikit-image dependency at runtime.
Installation
pip install fastlabelops
import numpy as np
from fastlabelops import (
label_counts,
overlap_counts,
regionprops,
relabel_sequential,
remove_small_objects,
)
labels = np.array(
[
[0, 17, 17],
[91, 0, 5002],
],
dtype=np.uint32,
)
ids, counts = label_counts(labels)
relabeled, n = relabel_sequential(labels)
filtered = remove_small_objects(labels, max_size=1)
props = regionprops(labels)
a_ids, b_ids, overlap = overlap_counts(labels, relabeled)
Label 0 is background throughout. Inputs already contain instance IDs; none of these functions
perform connected-component labeling.
label_counts
ids, counts = label_counts(labels, include_background=False)
Counts elements for each observed label ID. IDs are returned in ascending order and counts are
uint64. Background label 0 is excluded by default.
- supports
uint32anduint64 - arbitrary NumPy dimensionality
- accepts non-contiguous inputs
- memory scales with the number of observed labels, not
max(label) - with
include_background=True, the background row is emitted only when its count is nonzero
relabel_sequential
relabeled, n = relabel_sequential(labels, offset=0, in_place=False)
- supports
uint32anduint64 - arbitrary NumPy dimensionality
- deterministic first-occurrence relabeling
in_place=Truemutates a writable C-contiguous arrayoffset=Nstarts foreground labels atN + 1- memory scales with the number of observed labels, not
max(label)
remove_small_objects
filtered = remove_small_objects(labels, max_size=64, in_place=False)
Removes every nonzero label whose total size is less than or equal to max_size elements. Surviving
objects keep their original IDs. Disconnected regions carrying the same nonzero label are treated as
one instance.
- supports
uint32anduint64 - arbitrary NumPy dimensionality
in_place=Truemutates a writable C-contiguous arraymax_size=0is a no-op
overlap_counts
a_ids, b_ids, counts = overlap_counts(labels_a, labels_b, include_background=False)
Returns only label pairs that actually occur. By default, positions where either input is background
are ignored. Use include_background=True when full foreground/background contingency counts are
needed.
- same-shape inputs of arbitrary dimensionality
- supports
uint32anduint64, including mixed dtypes - deterministic first-occurrence pair ordering
- memory scales with observed label pairs, not a dense
(max_a + 1) x (max_b + 1)matrix
regionprops
props = regionprops(labels)
Currently 2D only and intentionally limited to:
label
area
bbox
centroid
area_bbox
Rows are sorted by ascending label. Bounding boxes use
(min_row, min_col, max_row_exclusive, max_col_exclusive). Arbitrary/gappy uint32 and
uint64 IDs are handled directly without relabeling first.
Performance
fastlabelops is CPU-only. On supported x86 CPUs, uint32 workloads automatically use AVX2 run
scanning where it helps; lightweight input sampling selects between SIMD and fallback paths.
Representative speedups versus common reference implementations on 2048²–4096² instance masks:
| Operation | vs scikit-image | vs NumPy | vs fastremap |
|---|---|---|---|
label_counts |
— | 9–16× | 4–7× |
relabel_sequential |
6–9× | — | 1.1–1.3× |
remove_small_objects |
4.5–5× | — | — |
overlap_counts |
38–55× | 26–33× | — |
regionprops |
95–97× | — | — |
overlap_counts and regionprops show the largest gains because the reference implementations
size internal structures by max(label) + 1, which is prohibitively expensive for gappy or
sparse IDs. fastlabelops sizes by observed labels, so sparse IDs cost the same as compact ones.
In the benchmarked sparse uint64 cases, scikit-image's remove_small_objects and regionprops
raised MemoryError when max(label) exceeded available memory.
Run the comparison benchmarks (requires scikit-image, scipy, and fastremap):
uv sync --dev
uv run examples/benchmark_label_counts.py
uv run examples/benchmark_relabel.py
uv run examples/benchmark_remove_small_objects.py
uv run examples/benchmark_overlap.py
uv run examples/benchmark_regionprops.py
The dependency-free benchmark matrix is also available:
uv run examples/benchmark_matrix.py
Development
uv sync --dev
uv run pytest
uv run ruff check src tests examples
uv run ruff format --check src tests examples
uv run mypy src tests examples
uv run pre-commit install
See examples/usage_example.py for a runnable example.
Metadata
Release files for fastlabelops 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| fastlabelops-0.1.1.tar.gz | 32.4 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| fastlabelops-0.1.1-cp312-cp312-macosx_11_0_arm64.whl | CPython 3.12 | CPython 3.12 | macOS 11.0+ ARM64 | Details |
Total release size: 79.4 kB
Release files / fastlabelops-0.1.1.tar.gz
| Download URL | fastlabelops-0.1.1.tar.gz |
|---|---|
| Size | 32.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
dedcd6c27b03c6868c56cec8a5e4c021d3d8391385e10fd2874691d47efd3e05
|
|
BLAKE2b-256 checksum How to use checksums |
a57b144af2be9450e6b7772bd073040123cd490bfb617ec1dab72e4cb1672806
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.23 {"installer":{"name":"uv","version":"0.11.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / fastlabelops-0.1.1-cp312-cp312-macosx_11_0_arm64.whl
| Download URL | fastlabelops-0.1.1-cp312-cp312-macosx_11_0_arm64.whl |
|---|---|
| Size | 47.0 kB |
| Tags | CPython 3.12 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
1aa862e05ff331ce48d40fe91326c4afc0c3b055011065a88b0ca87a4e1a47b8
|
|
BLAKE2b-256 checksum How to use checksums |
08bd8d9f14544508e09365b5d263752a3c3845cb2eb60b4f87a01fa2855b794d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.23 {"installer":{"name":"uv","version":"0.11.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for fastlabelops 0.1.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.