Jump to content

Connect Leeroopedia MCP: Equip your AI agents to search best practices, build plans, verify code, diagnose failures, and look up hyperparameter defaults.

Heuristic:Obss Sahi Class Agnostic vs Per Class NMS

From Leeroopedia




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

Related Pages

Page Connections

Double-click a node to navigate. Hold to expand connections.
Principle
Implementation
Heuristic
Environment