You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

52 lines
2.2 KiB

import math
from src.config_loader import HeadPoseSettings
from src.head_pose import HeadPoseEstimator
from src.models import FaceLandmark
def settings(max_angle: float = 90.0) -> HeadPoseSettings:
return HeadPoseSettings(True, "solvepnp", True, "ema", .4, max_angle)
def landmarks() -> list[FaceLandmark]:
return [FaceLandmark(index, float(index), float(index + 1), 0.0)
for index in HeadPoseEstimator.LANDMARK_INDICES]
def test_missing_landmarks_and_input_builders() -> None:
estimator = HeadPoseEstimator(settings())
assert estimator.estimate([], 640, 480).failure_reason == "insufficient_landmarks"
assert len(estimator.build_image_points(landmarks()) or []) == 6
matrix = estimator.build_camera_matrix(640, 480)
assert matrix == [[640.0, 0.0, 320.0], [0.0, 640.0, 240.0], [0.0, 0.0, 1.0]]
def test_euler_conversion_returns_floats() -> None:
angles = HeadPoseEstimator.rotation_matrix_to_euler([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]])
assert all(isinstance(value, float) for value in angles)
assert angles == (0.0, -0.0, 0.0)
def test_angle_range_validation() -> None:
estimator = HeadPoseEstimator(settings(45.0))
assert estimator.result_from_angles((10.0, 20.0, 5.0)).success
failed = estimator.result_from_angles((10.0, 60.0, 5.0))
assert failed.failure_reason == "angle_out_of_range"
assert (failed.pitch, failed.yaw, failed.roll) == (10.0, 60.0, 5.0)
assert estimator.result_from_angles((math.nan, 0.0, 0.0)).failure_reason == "angle_out_of_range"
def test_face_model_uses_image_coordinate_y_direction() -> None:
_, chin, left_eye, right_eye, left_mouth, right_mouth = HeadPoseEstimator.MODEL_POINTS
assert chin[1] > 0
assert left_eye[1] < 0 and right_eye[1] < 0
assert left_mouth[1] > 0 and right_mouth[1] > 0
def test_roll_near_180_is_canonicalized_for_upright_face() -> None:
estimator = HeadPoseEstimator(settings())
assert estimator.normalize_angles((2.0, -5.0, -170.0)) == (2.0, -5.0, 10.0)
assert estimator.normalize_angles((2.0, -5.0, 170.0)) == (2.0, -5.0, -10.0)
result = estimator.result_from_angles((2.0, -5.0, -170.0))
assert result.success and result.roll == 10.0