Files
wehub-resource-sync 16031aae96
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
chore: import upstream snapshot with attribution
2026-07-13 12:26:24 +08:00

188 lines
7.5 KiB
Python

# ------------------------------------------------------------------------
# RF-DETR
# Copyright (c) 2025 Roboflow. All Rights Reserved.
# Licensed under the Apache License, Version 2.0 [see LICENSE for details]
# ------------------------------------------------------------------------
"""Tests for private RF-DETR keypoint visualization helpers."""
from pathlib import Path
import numpy as np
import pytest
import supervision as sv
from rfdetr.utilities.keypoints import precision_cholesky_to_pixel_covariance
from rfdetr.visualize.keypoints import _key_points_for_display, _keypoint_prediction_records
def test_precision_cholesky_to_pixel_covariance_identity_precision() -> None:
"""Identity normalized precision should scale to width/height pixel variance."""
precision_cholesky = np.array([[[0.0, 0.0, 0.0]]], dtype=np.float32)
source_shape = np.array([[10.0, 20.0]], dtype=np.float32)
covariance = precision_cholesky_to_pixel_covariance(
precision_cholesky=precision_cholesky,
source_shape=source_shape,
)
np.testing.assert_allclose(
covariance,
np.array([[[[400.0, 0.0], [0.0, 100.0]]]], dtype=np.float32),
rtol=1e-4,
atol=1e-6,
)
def test_precision_cholesky_to_pixel_covariance_does_not_clamp_log_cholesky() -> None:
"""Covariance display should use raw RF-DETR precision parameters."""
precision_cholesky = np.array([[[25.0, 0.0, 0.0]]], dtype=np.float32)
source_shape = np.array([[1.0, 1.0]], dtype=np.float32)
covariance = precision_cholesky_to_pixel_covariance(
precision_cholesky=precision_cholesky,
source_shape=source_shape,
)
np.testing.assert_allclose(
covariance[0, 0, 0, 0],
np.exp(-50.0),
rtol=1e-4,
atol=1e-28,
)
def test_precision_cholesky_to_pixel_covariance_rejects_bad_shape() -> None:
"""Invalid precision and source shapes should fail before annotation."""
with pytest.raises(ValueError, match=r"precision_cholesky must have shape"):
precision_cholesky_to_pixel_covariance(
precision_cholesky=np.zeros((1, 2, 4), dtype=np.float32),
source_shape=np.zeros((1, 2), dtype=np.float32),
)
with pytest.raises(ValueError, match=r"source_shape must have shape"):
precision_cholesky_to_pixel_covariance(
precision_cholesky=np.zeros((2, 1, 3), dtype=np.float32),
source_shape=np.zeros((1, 2), dtype=np.float32),
)
def test_key_points_for_display_builds_keypoints_with_covariance_and_masks_low_confidence() -> None:
"""RF-DETR keypoints should become annotator-ready keypoints with optional covariance."""
predictions = sv.KeyPoints(
xy=np.array([[[1.0, 2.0], [3.0, 4.0]]], dtype=np.float32),
keypoint_confidence=np.array([[0.9, 0.1]], dtype=np.float32),
detection_confidence=np.array([0.95], dtype=np.float32),
class_id=np.array([3], dtype=int),
data={
"keypoint_precision_cholesky": np.array([[[0.0, 0.0, 0.0], [0.0, 0.0, 0.0]]], dtype=np.float32),
"source_shape": np.array([[10, 20]], dtype=np.int64),
"xyxy": np.array([[0, 0, 10, 10]], dtype=np.float32),
},
)
key_points = _key_points_for_display(predictions, keypoint_threshold=0.2)
np.testing.assert_allclose(
key_points.xy,
np.array([[[1.0, 2.0], [3.0, 4.0]]], dtype=np.float32),
rtol=1e-4,
atol=1e-6,
)
np.testing.assert_allclose(
key_points.keypoint_confidence, np.array([[0.9, 0.1]], dtype=np.float32), rtol=1e-4, atol=1e-6
)
np.testing.assert_array_equal(key_points.visible, np.array([[True, False]]))
np.testing.assert_array_equal(key_points.class_id, np.array([3]))
assert "covariance" in key_points.data
assert key_points.data["covariance"].shape == (1, 2, 2, 2)
def test_key_points_for_display_accepts_keypoints_directly() -> None:
"""RF-DETR KeyPoints should be annotator-ready without converting through Detections."""
predictions = sv.KeyPoints(
xy=np.array([[[1.0, 2.0], [3.0, 4.0]]], dtype=np.float32),
keypoint_confidence=np.array([[0.9, 0.1]], dtype=np.float32),
detection_confidence=np.array([0.95], dtype=np.float32),
data={
"keypoint_precision_cholesky": np.array([[[0.0, 0.0, 0.0], [0.0, 0.0, 0.0]]], dtype=np.float32),
"source_shape": np.array([[10, 20]], dtype=np.int64),
"xyxy": np.array([[0, 0, 10, 10]], dtype=np.float32),
},
)
key_points = _key_points_for_display(predictions, keypoint_threshold=0.2)
np.testing.assert_allclose(
key_points.xy,
np.array([[[1.0, 2.0], [3.0, 4.0]]], dtype=np.float32),
rtol=1e-4,
atol=1e-6,
)
np.testing.assert_array_equal(key_points.visible, np.array([[True, False]]))
np.testing.assert_array_equal(key_points.data["xyxy"], predictions.data["xyxy"])
np.testing.assert_array_equal(key_points.detection_confidence, predictions.detection_confidence)
assert "covariance" in key_points.data
def test_key_points_for_display_preserves_existing_covariance() -> None:
"""Display preparation should not overwrite covariance emitted by prediction."""
covariance = np.array([[[[1.0, 0.0], [0.0, 2.0]]]], dtype=np.float32)
predictions = sv.KeyPoints(
xy=np.array([[[1.0, 2.0]]], dtype=np.float32),
keypoint_confidence=np.array([[0.9]], dtype=np.float32),
data={
"covariance": covariance,
"keypoint_precision_cholesky": np.array([[[0.0, 0.0, 0.0]]], dtype=np.float32),
"source_shape": np.array([[10, 20]], dtype=np.int64),
},
)
key_points = _key_points_for_display(predictions)
np.testing.assert_array_equal(key_points.data["covariance"], covariance)
def test_key_points_for_display_rejects_keypoints_without_confidence_channel() -> None:
"""RF-DETR display helper expects per-keypoint confidence."""
key_points = sv.KeyPoints(xy=np.array([[[1.0, 2.0]]], dtype=np.float32))
with pytest.raises(ValueError, match=r"Expected RF-DETR keypoints"):
_key_points_for_display(key_points)
def test_key_points_for_display_empty_detections_returns_without_raising() -> None:
"""Empty KeyPoints (zero detections) should be returned unchanged without raising."""
empty_predictions = sv.KeyPoints.empty()
result = _key_points_for_display(empty_predictions)
assert len(result) == 0, f"Expected empty KeyPoints, got len={len(result)}"
def test_keypoint_prediction_records_flattens_visible_keypoints() -> None:
"""Prediction records should expose detection and keypoint confidence for visible non-zero points."""
key_points = sv.KeyPoints(
xy=np.array([[[1.0, 2.0], [0.0, 0.0], [3.0, 4.0]]], dtype=np.float32),
keypoint_confidence=np.array([[0.9, 0.99, 0.1]], dtype=np.float32),
detection_confidence=np.array([0.95], dtype=np.float32),
class_id=np.array([2], dtype=int),
visible=np.array([[True, True, False]]),
data={"class_name": np.array(["dartboard"], dtype=object)},
)
records = _keypoint_prediction_records(key_points, image=Path("/tmp/sample.jpg"), keypoint_threshold=0.2)
assert records == [
{
"image": "sample.jpg",
"detection_index": 0,
"class_id": 2,
"class_name": "dartboard",
"detection_confidence": pytest.approx(0.95),
"keypoint_index": 0,
"x": pytest.approx(1.0),
"y": pytest.approx(2.0),
"keypoint_confidence": pytest.approx(0.9),
}
]