Files
wehub-resource-sync 9194ef5abd
Docs/Test Workflow / Test docs build (push) Failing after 0s
Check links & references / links-check (push) Failing after 1s
Pytest/Test Workflow / Import Test and Pytest Run (ubuntu-latest, 3.10) (push) Failing after 0s
Pytest/Test Workflow / Import Test and Pytest Run (ubuntu-latest, 3.11) (push) Failing after 0s
PR Conflict Labeler / main (push) Failing after 2s
Pytest/Test Workflow / Import Test and Pytest Run (ubuntu-latest, 3.12) (push) Failing after 2s
Pytest/Test Workflow / Import Test and Pytest Run (ubuntu-latest, 3.13) (push) Failing after 0s
Pytest/Test Workflow / Build this Package (push) Failing after 5s
Pytest/Test Workflow / Import Test and Pytest Run (macos-latest, 3.10) (push) Has been cancelled
Pytest/Test Workflow / Import Test and Pytest Run (macos-latest, 3.11) (push) Has been cancelled
Pytest/Test Workflow / Import Test and Pytest Run (macos-latest, 3.12) (push) Has been cancelled
Pytest/Test Workflow / Import Test and Pytest Run (macos-latest, 3.13) (push) Has been cancelled
Pytest/Test Workflow / Import Test and Pytest Run (windows-latest, 3.10) (push) Has been cancelled
Pytest/Test Workflow / Import Test and Pytest Run (windows-latest, 3.11) (push) Has been cancelled
Pytest/Test Workflow / Import Test and Pytest Run (windows-latest, 3.12) (push) Has been cancelled
Pytest/Test Workflow / Import Test and Pytest Run (windows-latest, 3.13) (push) Has been cancelled
Pytest/Test Workflow / testing-guardian (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:06:10 +08:00

60 lines
2.7 KiB
Python

"""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)]