chore: import upstream snapshot with attribution
CPU tests Workflow / Testing (ubuntu-latest, 3.12) (push) Failing after 1s
CPU tests Workflow / Testing (ubuntu-latest, 3.13) (push) Failing after 0s
Mypy Type Check / Type Check (push) Failing after 0s
Docs/Test WorkFlow / Test docs build (push) Failing after 1s
PR Conflict Labeler / labeling (push) Failing after 1s
Dependency resolution / Resolve [tflite] extra — Python 3.12 (push) Failing after 0s
Smoke Tests / try-all-models (ubuntu-latest, 3.10) (push) Failing after 0s
Smoke Tests / try-all-models (ubuntu-latest, 3.13) (push) Failing after 1s
CPU tests Workflow / build-pkg (push) Failing after 1s
CPU tests Workflow / Testing (ubuntu-latest, 3.10) (push) Failing after 0s
CPU tests Workflow / Testing (ubuntu-latest, 3.11) (push) Failing after 0s
Smoke Tests / try-all-models (macos-latest, 3.10) (push) Has been cancelled
Smoke Tests / try-all-models (macos-latest, 3.13) (push) Has been cancelled
Smoke Tests / try-all-models (windows-latest, 3.10) (push) Has been cancelled
Smoke Tests / try-all-models (windows-latest, 3.13) (push) Has been cancelled
CPU tests Workflow / Testing (macos-latest, 3.10) (push) Has been cancelled
CPU tests Workflow / Testing (macos-latest, 3.13) (push) Has been cancelled
CPU tests Workflow / Testing (windows-latest, 3.10) (push) Has been cancelled
CPU tests Workflow / Testing (windows-latest, 3.13) (push) Has been cancelled
CPU tests Workflow / testing-guardian (push) Has been cancelled
GPU tests Workflow / Testing (push) Has been cancelled
CPU tests Workflow / Testing (ubuntu-latest, 3.12) (push) Failing after 1s
CPU tests Workflow / Testing (ubuntu-latest, 3.13) (push) Failing after 0s
Mypy Type Check / Type Check (push) Failing after 0s
Docs/Test WorkFlow / Test docs build (push) Failing after 1s
PR Conflict Labeler / labeling (push) Failing after 1s
Dependency resolution / Resolve [tflite] extra — Python 3.12 (push) Failing after 0s
Smoke Tests / try-all-models (ubuntu-latest, 3.10) (push) Failing after 0s
Smoke Tests / try-all-models (ubuntu-latest, 3.13) (push) Failing after 1s
CPU tests Workflow / build-pkg (push) Failing after 1s
CPU tests Workflow / Testing (ubuntu-latest, 3.10) (push) Failing after 0s
CPU tests Workflow / Testing (ubuntu-latest, 3.11) (push) Failing after 0s
Smoke Tests / try-all-models (macos-latest, 3.10) (push) Has been cancelled
Smoke Tests / try-all-models (macos-latest, 3.13) (push) Has been cancelled
Smoke Tests / try-all-models (windows-latest, 3.10) (push) Has been cancelled
Smoke Tests / try-all-models (windows-latest, 3.13) (push) Has been cancelled
CPU tests Workflow / Testing (macos-latest, 3.10) (push) Has been cancelled
CPU tests Workflow / Testing (macos-latest, 3.13) (push) Has been cancelled
CPU tests Workflow / Testing (windows-latest, 3.10) (push) Has been cancelled
CPU tests Workflow / Testing (windows-latest, 3.13) (push) Has been cancelled
CPU tests Workflow / testing-guardian (push) Has been cancelled
GPU tests Workflow / Testing (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
# ------------------------------------------------------------------------
|
||||
# RF-DETR
|
||||
# Copyright (c) 2025 Roboflow. All Rights Reserved.
|
||||
# Licensed under the Apache License, Version 2.0 [see LICENSE for details]
|
||||
# ------------------------------------------------------------------------
|
||||
"""Tests for keypoint matching costs in HungarianMatcher."""
|
||||
|
||||
import torch
|
||||
|
||||
from rfdetr.models.matcher import HungarianMatcher
|
||||
|
||||
|
||||
def _base_outputs(num_queries: int = 2) -> dict[str, torch.Tensor]:
|
||||
"""Build minimal detection outputs used across matcher keypoint tests."""
|
||||
pred_logits = torch.full((1, num_queries, 1), 5.0, dtype=torch.float32)
|
||||
pred_boxes = torch.tensor([0.5, 0.5, 0.2, 0.2], dtype=torch.float32).view(1, 1, 4).repeat(1, num_queries, 1)
|
||||
return {
|
||||
"pred_logits": pred_logits,
|
||||
"pred_boxes": pred_boxes,
|
||||
}
|
||||
|
||||
|
||||
def test_matcher_keypoint_cost_list_of_dicts_targets() -> None:
|
||||
"""Keypoint matching costs should work with public list-of-dicts targets."""
|
||||
matcher = HungarianMatcher(
|
||||
cost_class=0.0,
|
||||
cost_bbox=1.0,
|
||||
cost_giou=0.0,
|
||||
num_keypoints_per_class=[1],
|
||||
keypoint_l1_loss_coef=10.0,
|
||||
keypoint_findable_loss_coef=0.0,
|
||||
keypoint_visible_loss_coef=0.0,
|
||||
keypoint_nll_loss_coef=0.0,
|
||||
)
|
||||
outputs = _base_outputs()
|
||||
outputs["pred_keypoints"] = torch.zeros((1, 2, 1, 8), dtype=torch.float32)
|
||||
outputs["pred_keypoints"][0, 0, 0, :2] = torch.tensor([0.5, 0.5], dtype=torch.float32)
|
||||
outputs["pred_keypoints"][0, 1, 0, :2] = torch.tensor([0.0, 0.0], dtype=torch.float32)
|
||||
targets = [
|
||||
{
|
||||
"labels": torch.tensor([0], dtype=torch.int64),
|
||||
"boxes": torch.tensor([[0.5, 0.5, 0.2, 0.2]], dtype=torch.float32),
|
||||
"keypoints": torch.tensor([[[0.5, 0.5, 2.0]]], dtype=torch.float32),
|
||||
}
|
||||
]
|
||||
|
||||
matched_queries, matched_targets = matcher(outputs, targets)[0]
|
||||
|
||||
assert matched_queries.tolist() == [0]
|
||||
assert matched_targets.tolist() == [0]
|
||||
|
||||
|
||||
def test_matcher_keypoint_cost_coefficients_off() -> None:
|
||||
"""Zero keypoint coefficients should preserve non-keypoint matching behavior."""
|
||||
base_matcher = HungarianMatcher(cost_class=1.0, cost_bbox=1.0, cost_giou=1.0)
|
||||
keypoint_matcher = HungarianMatcher(
|
||||
cost_class=1.0,
|
||||
cost_bbox=1.0,
|
||||
cost_giou=1.0,
|
||||
num_keypoints_per_class=[1],
|
||||
keypoint_l1_loss_coef=0.0,
|
||||
keypoint_findable_loss_coef=0.0,
|
||||
keypoint_visible_loss_coef=0.0,
|
||||
keypoint_nll_loss_coef=0.0,
|
||||
)
|
||||
outputs = _base_outputs()
|
||||
outputs["pred_logits"][0, 0, 0] = 10.0
|
||||
outputs["pred_logits"][0, 1, 0] = -10.0
|
||||
outputs["pred_boxes"][0, 1, :] = torch.tensor([0.1, 0.1, 0.1, 0.1], dtype=torch.float32)
|
||||
targets = [
|
||||
{
|
||||
"labels": torch.tensor([0], dtype=torch.int64),
|
||||
"boxes": torch.tensor([[0.5, 0.5, 0.2, 0.2]], dtype=torch.float32),
|
||||
"keypoints": torch.tensor([[[0.0, 0.0, 2.0]]], dtype=torch.float32),
|
||||
}
|
||||
]
|
||||
outputs_with_keypoints = dict(outputs)
|
||||
outputs_with_keypoints["pred_keypoints"] = torch.zeros((1, 2, 1, 8), dtype=torch.float32)
|
||||
|
||||
base_indices = base_matcher(outputs, targets)[0]
|
||||
keypoint_indices = keypoint_matcher(outputs_with_keypoints, targets)[0]
|
||||
|
||||
assert base_indices[0].tolist() == keypoint_indices[0].tolist()
|
||||
assert base_indices[1].tolist() == keypoint_indices[1].tolist()
|
||||
|
||||
|
||||
def test_matcher_keypoint_empty_targets() -> None:
|
||||
"""Empty keypoint targets should return valid empty match results."""
|
||||
matcher = HungarianMatcher(
|
||||
cost_class=1.0,
|
||||
cost_bbox=1.0,
|
||||
cost_giou=1.0,
|
||||
num_keypoints_per_class=[1],
|
||||
keypoint_l1_loss_coef=1.0,
|
||||
keypoint_findable_loss_coef=1.0,
|
||||
keypoint_visible_loss_coef=1.0,
|
||||
keypoint_nll_loss_coef=1.0,
|
||||
)
|
||||
outputs = _base_outputs(num_queries=3)
|
||||
outputs["pred_keypoints"] = torch.zeros((1, 3, 1, 8), dtype=torch.float32)
|
||||
targets = [
|
||||
{
|
||||
"labels": torch.zeros((0,), dtype=torch.int64),
|
||||
"boxes": torch.zeros((0, 4), dtype=torch.float32),
|
||||
"keypoints": torch.zeros((0, 1, 3), dtype=torch.float32),
|
||||
}
|
||||
]
|
||||
|
||||
matched_queries, matched_targets = matcher(outputs, targets)[0]
|
||||
|
||||
assert matched_queries.numel() == 0
|
||||
assert matched_targets.numel() == 0
|
||||
Reference in New Issue
Block a user