Heuristic:Obss Sahi Class Agnostic vs Per Class NMS
| Knowledge Sources | |
|---|---|
| Domains | Computer_Vision, Object_Detection, Optimization |
| Last Updated | 2026-02-08 12:00 GMT |
Overview
Decision framework for choosing between class-agnostic and per-class postprocessing, affecting how overlapping predictions of different categories are handled.
Description
SAHI's postprocessing (NMS, NMM, GREEDYNMM) can operate in two modes:
Per-class mode (`class_agnostic=False`, default): Only predictions of the same category are compared and merged/suppressed. Two overlapping boxes of different classes are both kept. This is implemented via `batched_greedy_nmm()` / `batched_nms()` which partition predictions by category ID before processing.
Class-agnostic mode (`class_agnostic=True`): All predictions are compared regardless of category. Two overlapping boxes of different classes will be merged or one suppressed, with the category of the higher-confidence prediction winning.
Usage
Use this heuristic when configuring `postprocess_class_agnostic` in `get_sliced_prediction()`. Consider adjusting when:
- Overlapping objects of different classes should coexist (use per-class)
- Multi-label scenarios where the same region may have multiple valid classes (use per-class)
- Single-class detection or when overlapping different-class predictions are always errors (use class-agnostic)
- The dataset has many similar/confusable classes and the model sometimes predicts different classes for the same object in different tiles
The Insight (Rule of Thumb)
- Default: `postprocess_class_agnostic=False` (per-class processing)
- Use per-class (False) when:
- The dataset has objects that naturally overlap (e.g., "person" on "bicycle")
- Different classes represent genuinely different objects that may share spatial regions
- You want maximum recall across all classes
- Use class-agnostic (True) when:
- Doing single-class detection (irrelevant but slightly faster)
- The model tends to predict different classes for the same object in different tiles
- You want the postprocessor to resolve class confusion (higher-confidence class wins)
- Trade-off: Per-class preserves more predictions (higher recall, possible duplicates across classes). Class-agnostic is more aggressive (fewer duplicates, risk of losing valid overlapping objects).
Reasoning
The per-class default is the safer choice because it never incorrectly suppresses a valid detection. In sliced inference, the same physical object may produce predictions in multiple tiles. If the model consistently predicts the same class, per-class mode correctly merges them. If the model inconsistently predicts different classes for the same object (e.g., "car" in one tile, "truck" in the adjacent tile), per-class mode will keep both — which is preferable to silently discarding one.
Class-agnostic mode should only be used when you are confident that overlapping different-class predictions always represent the same physical object. This is common in single-class scenarios or when the detection categories are mutually exclusive within any spatial region.
Code evidence from `sahi/postprocess/combine.py:527-545`:
class GreedyNMMPostprocess(PostprocessPredictions):
def __call__(self, object_predictions):
object_prediction_list = ObjectPredictionList(object_predictions)
object_predictions_as_torch = object_prediction_list.totensor()
if self.class_agnostic:
keep_to_merge_list = greedy_nmm(
object_predictions_as_torch,
match_threshold=self.match_threshold,
match_metric=self.match_metric,
)
else:
keep_to_merge_list = batched_greedy_nmm(
object_predictions_as_torch,
match_threshold=self.match_threshold,
match_metric=self.match_metric,
)
Merge category resolution from `sahi/postprocess/utils.py` — the category of the higher-scoring prediction is kept when merging:
merged_category = get_merged_category(pred1, pred2) # From higher score