"""Tests for supervision.metrics.utils.matching — greedy one-to-one IoU matching.""" from __future__ import annotations import numpy as np from supervision.metrics.utils.matching import _greedy_match class TestGreedyMatch: """Verify greedy highest-IoU-first one-to-one assignment.""" def test_empty_inputs_yield_no_matches(self) -> None: """Empty candidate-index arrays yield an empty match sequence.""" iou = np.zeros((0, 0), dtype=np.float32) matched_indices = ( np.array([], dtype=np.intp), np.array([], dtype=np.intp), ) assert list(_greedy_match(iou, matched_indices)) == [] def test_no_candidate_pairs_above_threshold(self) -> None: """A non-empty IoU matrix with no candidate pairs yields no matches.""" iou = np.array([[0.1, 0.2], [0.05, 0.3]], dtype=np.float32) matched_indices = np.where(iou >= 0.5) assert list(_greedy_match(iou, matched_indices)) == [] def test_single_candidate_pair_matches(self) -> None: """A single candidate pair is matched directly.""" iou = np.array([[0.9]], dtype=np.float32) matched_indices = np.where(iou >= 0.5) assert list(_greedy_match(iou, matched_indices)) == [(0, 0)] def test_ties_broken_by_stable_index_order(self) -> None: """Equal-IoU candidates are assigned in stable (original) order.""" iou = np.array([[0.7, 0.0], [0.7, 0.0]], dtype=np.float32) matched_indices = np.where(iou >= 0.5) # target 0 and target 1 both only candidate-match prediction 0 at equal # IoU; stable ordering means target 0 (appears first) wins prediction 0. assert list(_greedy_match(iou, matched_indices)) == [(0, 0)] def test_higher_iou_pair_wins_contested_prediction(self) -> None: """When two targets compete for one prediction, the higher IoU wins.""" iou = np.array([[0.6, 0.0], [0.9, 0.0]], dtype=np.float32) matched_indices = np.where(iou >= 0.5) assert list(_greedy_match(iou, matched_indices)) == [(1, 0)] def test_two_non_conflicting_pairs_are_matched(self) -> None: """Two non-conflicting pairs are matched.""" iou = np.array([[0.9, 0.8], [0.85, 0.0], [0.0, 0.7]], dtype=np.float32) matched_indices = np.where(iou >= 0.5) result = list(_greedy_match(iou, matched_indices)) assert result == [(0, 0), (2, 1)] def test_docstring_example_reproducible(self) -> None: """The matching example from the function docstring is reproducible.""" iou = np.array([[1.0, 0.667], [0.333, 0.538]], dtype=np.float32) matched_indices = np.where(iou >= 0.5) assert list(_greedy_match(iou, matched_indices)) == [(0, 0), (1, 1)]