Skip to main content

fastmask-seg

Unique colors, pixel counts, per-color boolean masks, and bounding boxes from segmentation masks stored as images.

import cv2
import numpy as np
import fastmask_seg as fms

image = cv2.imread("instance_mask.png")  # (H, W, 3) uint8, one solid color per instance

result = fms.unique_color_masks(image)
result.colors        # (K, 3) uint8 colors present, in BGR order because OpenCV loads BGR
result.color_counts  # (K,) int64 pixel count per color
result.masks         # (K, H, W) bool, one mask per color

road = fms.get_color_mask(image, color=np.array([128, 64, 128], np.uint8))  # (H, W) bool
boxes = fms.masks_to_bboxes(result.masks)  # (K, 4) int64 rows of (rmin, rmax, cmin, cmax)

The library targets instance and semantic segmentation masks, where each class or instance is one solid color. Its fast paths rely on what those images look like: few distinct colors in long runs of identical pixels.

Install

pip install fastmask-seg            # NumPy only
pip install "fastmask-seg[numba]"   # adds compiled kernels for 3-channel images

Requires Python 3.12+ and NumPy 1.26+. The numba extra gives the same results as NumPy, with color analysis 1.3-2x faster and masks of named colors 2-4x faster (details).

API

fm = fms.FastMask(image)             # computes on first access and caches, so later queries reuse the analysis
fm.unique_colors                     # (K, C) uint8 colors in the image's channel layout, ordered by color ID
fm.unique_color_ids                  # (K,) sorted color IDs
fm.unique_color_counts               # (K,) int64 pixel counts
fm.label_image                       # (H, W) index of each pixel's color in unique_color_ids
fm.color_id_image                    # (H, W) color ID of each pixel
fm.get_color_masks(colors=palette)   # ColorMasks(masks, num_masks), one mask per requested color
fm.get_color_masks()                 # every color in the image
fm.get_color_mask(color=c)           # one (H, W) bool mask
fm.iter_color_masks()                # one (H, W) mask at a time, for many colors on large images

# Each FastMask member is also a function that takes an image or a FastMask:
fms.unique_colors(image)
fms.get_color_masks(image, colors=palette)
fms.unique_color_masks(image)        # UniqueColorMasks(colors, color_ids, color_counts, masks, num_masks)

fms.masks_to_bboxes(masks)           # (K, 4) boxes of a (K, H, W) bool stack
fms.mask_to_bbox(mask)               # (rmin, rmax, cmin, cmax) of one mask

fms.colors_to_color_ids(colors)      # (..., 3) or (..., 4) uint8 colors to uint32 IDs
fms.color_ids_to_colors(ids, fms.ColorFormat.COLOR)
fms.sort_colors(colors)              # colors in color ID order
  • Images are uint8 arrays of shape (H, W, 3) or (H, W, 4), as cv2.imread or np.asarray(PIL.Image.open(...)) give them, or 2-D arrays of any integer dtype: a grayscale image, or a label image such as an instance-ID or object-index pass. In a 2-D image each pixel value is its color ID.
  • Colors follow the image's channel order: BGR for OpenCV, RGB for Pillow. A color ID packs a color into one uint32 with channel 0 in the lowest byte.
  • Mask requests take colors= or color_ids=, and with neither they cover every color in the image. A color absent from the image gives an all-False mask.
  • Bounding boxes have exclusive ends, so mask[rmin:rmax, cmin:cmax] crops a mask to its pixels. An empty mask raises ValueError.
  • Functions and FastMask: a function given an image analyzes it from scratch on each call. Wrap the image in a FastMask to ask several questions about one image, and pass that object to the functions when you prefer their form.
  • Arguments are used as given. The docstrings state each required shape and dtype, and other inputs surface as NumPy errors or wrong results.

Processing many images

Allocate the mask buffer once and pass it as out=, so each image writes into memory the process already holds:

masks_buf = np.empty((64, H, W), dtype=bool)  # room for up to 64 colors per image

for path in paths:
    result = fms.unique_color_masks(cv2.imread(path), out=masks_buf)
    ...  # result.masks is masks_buf[:result.num_masks], overwritten by the next image

For a fixed class palette, pass the palette straight to get_color_masks(image, colors=palette, out=...); with the numba extra this is the fastest path. docs/performance.md covers the backends, the NumPy-path color_id_buffer, caching, and benchmarks.

Development

make dev     # uv sync --dev
make check   # ruff, isort, mypy --strict
make format  # isort + ruff format

License

MIT

Metadata

Release files for fastmask-seg 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for fastmask-seg 0.2.0
File Size Uploaded Provenance Actions
fastmask_seg-0.2.0.tar.gz 18.2 kB Without provenance Details for fastmask_seg-0.2.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for fastmask-seg 0.2.0
File Interpreter ABI Platform Actions
fastmask_seg-0.2.0-py3-none-any.whl Python 3 none any Details for fastmask_seg-0.2.0-py3-none-any.whl

Total release size: 38.0 kB

Release files / fastmask_seg-0.2.0.tar.gz

Download URL fastmask_seg-0.2.0.tar.gz
Size 18.2 kB
Tags Source
SHA-256 checksum
How to use checksums
2d8b5f8b33b40dd7d97f8571ff88db6e1cfd0496c24e1fd7f2a422627439fc2c
BLAKE2b-256 checksum
How to use checksums
9a55f0ad2e418acd687561be22336b723a3002f5f8ea13a6e07b537fa4d89a6a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.9.4

Release files / fastmask_seg-0.2.0-py3-none-any.whl

Download URL fastmask_seg-0.2.0-py3-none-any.whl
Size 19.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
93f959e5af1f593d21590875843a10107a6f37c59782179d48927f222445b6e3
BLAKE2b-256 checksum
How to use checksums
052720406f85092fea8982eaef2162c405a0a1dcb234a15e2c9b6eff006eca81
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.9.4

Security for fastmask-seg 0.2.0

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.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page