Masks Utils¶
supervision.detection.utils.masks.mask_to_roi(mask: npt.NDArray[np.bool_]) -> tuple[int, int, int, int] | None
¶
Return exclusive (x1, y1, x2, y2) bounds for true mask pixels.
Use this helper when you need NumPy slice semantics. Unlike
:func:~supervision.detection.utils.converters.mask_to_xyxy, this
function uses exclusive upper bounds (+1) and returns None for
empty masks instead of zeros. The inclusive mask_to_xyxy convention
stays in place for compatibility with CompactMask and box-based adapters.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
|
NDArray[bool_]
|
2D boolean array of shape |
required |
Returns:
| Type | Description |
|---|---|
tuple[int, int, int, int] | None
|
Exclusive |
tuple[int, int, int, int] | None
|
has no true pixels. |
Examples:
>>> import numpy as np
>>> from supervision.detection.utils.masks import mask_to_roi
>>> mask = np.zeros((10, 10), dtype=bool)
>>> mask[2:5, 3:6] = True
>>> mask_to_roi(mask)
(3, 2, 6, 5)
Source code in src/supervision/detection/utils/masks.py
supervision.detection.utils.masks.move_masks(masks: npt.NDArray[np.bool_], offset: npt.NDArray[np.integer], resolution_wh: tuple[int, int]) -> npt.NDArray[np.bool_]
¶
Offset the masks in an array by the specified (x, y) amount.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
|
NDArray[bool_]
|
A 3D array of binary masks corresponding to the
predictions. Shape: |
required |
|
NDArray[integer]
|
An array of shape |
required |
|
tuple[int, int]
|
The width and height of the desired mask resolution. |
required |
Returns:
| Type | Description |
|---|---|
NDArray[bool_]
|
Repositioned masks, optionally padded to the specified shape. |
Examples:
>>> import numpy as np
>>> import supervision as sv
>>> mask = np.array([[[False, False, False, False],
... [False, True, True, False],
... [False, True, True, False],
... [False, False, False, False]]], dtype=bool)
>>> offset = np.array([1, 1])
>>> sv.move_masks(mask, offset, resolution_wh=(4, 4))
array([[[False, False, False, False],
[False, False, False, False],
[False, False, True, True],
[False, False, True, True]]])
>>> offset = np.array([-2, 2])
>>> sv.move_masks(mask, offset, resolution_wh=(4, 4))
array([[[False, False, False, False],
[False, False, False, False],
[False, False, False, False],
[ True, False, False, False]]])
Source code in src/supervision/detection/utils/masks.py
supervision.detection.utils.masks.contains_holes(mask: npt.NDArray[np.bool_]) -> bool
¶
Checks if the binary mask contains holes (background pixels fully enclosed by foreground pixels).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
|
NDArray[bool_]
|
2D binary mask where |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if holes are detected, False otherwise. |
Examples:
>>> import numpy as np
>>> import supervision as sv
>>> mask = np.array([
... [0, 0, 0, 0, 0],
... [0, 1, 1, 1, 0],
... [0, 1, 0, 1, 0],
... [0, 1, 1, 1, 0],
... [0, 0, 0, 0, 0]
... ]).astype(bool)
>>> sv.contains_holes(mask=mask)
True
>>> mask = np.array([
... [0, 0, 0, 0, 0],
... [0, 1, 1, 1, 0],
... [0, 1, 1, 1, 0],
... [0, 1, 1, 1, 0],
... [0, 0, 0, 0, 0]
... ]).astype(bool)
>>> sv.contains_holes(mask=mask)
False

Source code in src/supervision/detection/utils/masks.py
supervision.detection.utils.masks.contains_multiple_segments(mask: npt.NDArray[np.bool_], connectivity: int = 4) -> bool
¶
Checks if the binary mask contains multiple unconnected foreground segments.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
|
NDArray[bool_]
|
2D binary mask where |
required |
|
int
|
Default: 4 is 4-way connectivity, which means that foreground pixels are the part of the same segment/component if their edges touch. Alternatively: 8 for 8-way connectivity, when foreground pixels are connected by their edges or corners touch. |
4
|
Returns:
| Type | Description |
|---|---|
bool
|
True when the mask contains multiple not connected components, False otherwise. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If connectivity(int) parameter value is not 4 or 8. |
Examples:
>>> import numpy as np
>>> import supervision as sv
>>> mask = np.array([
... [0, 0, 0, 0, 0, 0],
... [0, 1, 1, 0, 1, 1],
... [0, 1, 1, 0, 1, 1],
... [0, 0, 0, 0, 0, 0],
... [0, 1, 1, 1, 0, 0],
... [0, 1, 1, 1, 0, 0]
... ]).astype(bool)
>>> sv.contains_multiple_segments(mask=mask, connectivity=4)
True
>>> mask = np.array([
... [0, 0, 0, 0, 0, 0],
... [0, 1, 1, 1, 1, 1],
... [0, 1, 1, 1, 1, 1],
... [0, 1, 1, 1, 1, 1],
... [0, 1, 1, 1, 1, 1],
... [0, 0, 0, 0, 0, 0]
... ]).astype(bool)
>>> sv.contains_multiple_segments(mask=mask, connectivity=4)
False

Source code in src/supervision/detection/utils/masks.py
supervision.detection.utils.masks.filter_segments_by_distance(mask: npt.NDArray[np.bool_], absolute_distance: float | None = 100.0, relative_distance: float | None = None, connectivity: int = 8, mode: Literal['edge', 'centroid'] = 'edge') -> npt.NDArray[np.bool_]
¶
Keep the largest connected component and any other components within a distance threshold.
Distance can be absolute in pixels or relative to the image diagonal.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
|
NDArray[bool_]
|
Boolean mask HxW. |
required |
|
float | None
|
Max allowed distance in pixels to the main component.
Ignored if |
100.0
|
|
float | None
|
Fraction of the diagonal. If set, threshold = fraction * sqrt(H^2 + W^2). |
None
|
|
int
|
8
|
|
|
Literal['edge', 'centroid']
|
Defines how distance between components is measured. - "edge": Uses distance between nearest edges (via distance transform). - "centroid": Uses distance between component centroids. |
'edge'
|
Returns:
| Type | Description |
|---|---|
NDArray[bool_]
|
Boolean mask after filtering. |
Examples:
>>> import numpy as np
>>> import supervision as sv
>>> mask = np.array([
... [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
... [0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
... [0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
... [0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0],
... [0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0],
... [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
... [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
... [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
... [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0],
... [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0],
... [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
... [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
... ], dtype=bool)
>>> sv.filter_segments_by_distance(
... mask,
... absolute_distance=3,
... mode="edge",
... connectivity=8
... ).astype(int)
array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])
The nearby 2x2 block at columns 6-7 is kept because its edge distance is within 3 pixels. The distant block at columns 9-10 is removed.
Source code in src/supervision/detection/utils/masks.py
330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 | |
supervision.detection.utils.masks.calculate_masks_centroids(masks: npt.NDArray[np.bool_] | CompactMask) -> npt.NDArray[np.int_]
¶
Calculate the centroids of binary masks in a tensor.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
|
NDArray[bool_] | CompactMask
|
A 3D NumPy array of shape (num_masks, height, width).
Each 2D array in the tensor represents a binary mask.
Also accepts a :class: |
required |
Returns:
| Type | Description |
|---|---|
NDArray[int_]
|
A 2D NumPy array of shape (num_masks, 2), where each row contains the x and y coordinates (in that order) of the centroid of the corresponding mask. |
Examples:
>>> import numpy as np
>>> import supervision as sv
>>> masks = np.zeros((1, 10, 10), dtype=bool)
>>> masks[0, 2:6, 2:6] = True
>>> sv.calculate_masks_centroids(masks)
array([[4, 4]])