Combine¶
For a full guide including backend selection, usage examples, and per-category postprocessing, see the Postprocessing Backends page.
sahi.postprocess.combine
¶
Postprocessing strategies for combining predictions from sliced inference.
Classes¶
PostprocessPredictions
¶
PostprocessPredictions(
match_threshold: float = 0.5,
match_metric: str = "IOU",
class_agnostic: bool = True,
)
Bases: ABC
Abstract base class for postprocessing object prediction lists.
Subclasses implement a specific strategy (NMS, NMM, greedy NMM, etc.) to reduce overlapping detections produced by sliced inference.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
|
float
|
Minimum overlap value (IoU or IoS) to consider two predictions as matching. |
0.5
|
|
str
|
Overlap metric, "IOU" or "IOS". |
'IOU'
|
|
bool
|
If True, apply postprocessing across all categories. If False, apply per category independently. |
True
|
Initialize the postprocessor with configuration parameters.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
|
float
|
Minimum overlap value (IoU or IoS) to consider two predictions as matching. |
0.5
|
|
str
|
Overlap metric, "IOU" or "IOS". |
'IOU'
|
|
bool
|
If True, apply postprocessing across all categories. If False, apply per category independently. |
True
|
Source code in sahi/postprocess/combine.py
NMSPostprocess
¶
NMSPostprocess(
match_threshold: float = 0.5,
match_metric: str = "IOU",
class_agnostic: bool = True,
)
Bases: PostprocessPredictions
Postprocessor using Non-Maximum Suppression (NMS).
Keeps the highest-scored prediction among overlapping boxes and discards the rest. Does not merge bounding boxes or masks.
Source code in sahi/postprocess/combine.py
NMMPostprocess
¶
NMMPostprocess(
match_threshold: float = 0.5,
match_metric: str = "IOU",
class_agnostic: bool = True,
)
Bases: PostprocessPredictions
Postprocessor using Non-Maximum Merging (NMM) with transitive merging.
Instead of discarding overlapping detections, merges their bounding boxes, masks, and scores. Uses non-greedy transitive merging: if A overlaps B and B overlaps C, all three are merged even if A does not directly overlap C.
Source code in sahi/postprocess/combine.py
GreedyNMMPostprocess
¶
GreedyNMMPostprocess(
match_threshold: float = 0.5,
match_metric: str = "IOU",
class_agnostic: bool = True,
)
Bases: NMMPostprocess
Postprocessor using Greedy Non-Maximum Merging (NMM).
Similar to NMM but uses a greedy strategy: each kept prediction only merges boxes that directly overlap with it (no transitive merging). This is faster than full NMM and produces tighter merged boxes.
Source code in sahi/postprocess/combine.py
LSNMSPostprocess
¶
LSNMSPostprocess(
match_threshold: float = 0.5,
match_metric: str = "IOU",
class_agnostic: bool = True,
)
Bases: PostprocessPredictions
Postprocessor using Locality-Sensitive NMS from the lsnms package.
Uses a spatial index for fast neighbor lookup, making it efficient for
large numbers of predictions. Only supports IoU metric (not IoS).
Requires the lsnms package (pip install lsnms>0.3.1).
Note
This postprocessor is experimental and not recommended for production use.
Source code in sahi/postprocess/combine.py
Functions:¶
nms
¶
nms(
predictions: ndarray,
match_metric: str = "IOU",
match_threshold: float = 0.5,
) -> list[int]
Non-maximum suppression for axis-aligned bounding boxes.
Dispatches to the resolved backend (numpy, numba, or torchvision).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
|
ndarray
|
Array of shape (N, 6) with columns [x1, y1, x2, y2, score, category_id]. |
required |
|
str
|
Overlap metric, "IOU" or "IOS". |
'IOU'
|
|
float
|
Minimum overlap to suppress a lower-scored box. |
0.5
|
Returns:
| Type | Description |
|---|---|
list[int]
|
List of indices of the kept predictions, sorted by score descending. |
Source code in sahi/postprocess/combine.py
batched_nms
¶
batched_nms(
predictions: ndarray,
match_metric: str = "IOU",
match_threshold: float = 0.5,
) -> list[int]
Apply non-maximum suppression independently per category.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
|
ndarray
|
Array of shape (N, 6) with columns [x1, y1, x2, y2, score, category_id]. |
required |
|
str
|
Overlap metric, "IOU" or "IOS". |
'IOU'
|
|
float
|
Minimum overlap to suppress a lower-scored box. |
0.5
|
Returns:
| Type | Description |
|---|---|
list[int]
|
List of indices of the kept predictions, sorted by score descending. |
Source code in sahi/postprocess/combine.py
greedy_nmm
¶
greedy_nmm(
predictions: ndarray,
match_metric: str = "IOU",
match_threshold: float = 0.5,
) -> dict[int, list[int]]
Greedy non-maximum merging for axis-aligned bounding boxes.
Instead of discarding overlapping boxes, merges them into the highest-scored box. Dispatches to the resolved backend.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
|
ndarray
|
Array of shape (N, 6) with columns [x1, y1, x2, y2, score, category_id]. |
required |
|
str
|
Overlap metric, "IOU" or "IOS". |
'IOU'
|
|
float
|
Minimum overlap to merge a lower-scored box. |
0.5
|
Returns:
| Type | Description |
|---|---|
dict[int, list[int]]
|
Dict mapping each kept index to a list of indices merged into it. |
Source code in sahi/postprocess/combine.py
batched_greedy_nmm
¶
batched_greedy_nmm(
predictions: ndarray,
match_metric: str = "IOU",
match_threshold: float = 0.5,
) -> dict[int, list[int]]
Apply greedy non-maximum merging independently per category.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
|
ndarray
|
Array of shape (N, 6) with columns [x1, y1, x2, y2, score, category_id]. |
required |
|
str
|
Overlap metric, "IOU" or "IOS". |
'IOU'
|
|
float
|
Minimum overlap to merge a lower-scored box. |
0.5
|
Returns:
| Type | Description |
|---|---|
dict[int, list[int]]
|
Dict mapping each kept index to a list of indices merged into it. |
Source code in sahi/postprocess/combine.py
nmm
¶
nmm(
predictions: ndarray,
match_metric: str = "IOU",
match_threshold: float = 0.5,
) -> dict[int, list[int]]
Non-maximum merging (non-greedy, transitive) for axis-aligned bounding boxes.
Unlike greedy NMM, this variant allows transitive merging: if box A merges with B and B merges with C, all three are merged together. Dispatches to the resolved backend.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
|
ndarray
|
Array of shape (N, 6) with columns [x1, y1, x2, y2, score, category_id]. |
required |
|
str
|
Overlap metric, "IOU" or "IOS". |
'IOU'
|
|
float
|
Minimum overlap to merge a lower-scored box. |
0.5
|
Returns:
| Type | Description |
|---|---|
dict[int, list[int]]
|
Dict mapping each kept index to a list of indices merged into it. |
Source code in sahi/postprocess/combine.py
batched_nmm
¶
batched_nmm(
predictions: ndarray,
match_metric: str = "IOU",
match_threshold: float = 0.5,
) -> dict[int, list[int]]
Apply non-maximum merging (non-greedy, transitive) independently per category.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
|
ndarray
|
Array of shape (N, 6) with columns [x1, y1, x2, y2, score, category_id]. |
required |
|
str
|
Overlap metric, "IOU" or "IOS". |
'IOU'
|
|
float
|
Minimum overlap to merge a lower-scored box. |
0.5
|
Returns:
| Type | Description |
|---|---|
dict[int, list[int]]
|
Dict mapping each kept index to a list of indices merged into it. |