再投影誤差による破綻フレームの除外および窓の時間指定の実装と実験陽設定の更新

This commit is contained in:
agomizi1cm committed 2026-10-02 16:45:21 +09:00
1 parent d042ef9790
commit ca10876101
10 files changed
+256 -30

No files matched your search

+15 -2
View File
@@ -55,6 +55,8 @@ class HeadPoseEstimator:
image_points = self.build_image_points(landmarks)
if image_points is None:
return HeadPoseEstimation(False, failure_reason="insufficient_landmarks")
# Outer eye corners (landmarks 33 and 263) are model points 2 and 3.
eye_distance = math.hypot(image_points[3][0] - image_points[2][0], image_points[3][1] - image_points[2][1])
try:
import cv2
import numpy as np
@@ -74,13 +76,24 @@ class HeadPoseEstimator:
error = float(np.sqrt(np.mean(np.sum((projected.reshape(-1, 2) - image) ** 2, axis=1))))
except Exception:
return HeadPoseEstimation(False, failure_reason="solvepnp_failed")
return self.result_from_angles(angles, error)
return self.result_from_angles(angles, error, eye_distance_px=eye_distance)
def result_from_angles(
self, angles: tuple[float, float, float], reprojection_error: float | None = None,
eye_distance_px: float | None = None,
) -> HeadPoseEstimation:
"""Validate calculated angles and construct a normalized result."""
"""Validate calculated angles and construct a normalized result.
When ``max_reprojection_error_ratio`` is set, a pose whose reprojection error
exceeds that multiple of ``eye_distance_px`` is rejected: it is a degenerate
solution (typically a very small or leaving face), not a noisy measurement.
"""
normalized = self.normalize_angles(angles)
ratio = self.config.max_reprojection_error_ratio
if (ratio > 0.0 and reprojection_error is not None and eye_distance_px is not None
and eye_distance_px > 0.0 and reprojection_error > ratio * eye_distance_px):
return HeadPoseEstimation(False, *normalized, reprojection_error=reprojection_error,
failure_reason="reprojection_error_too_large")
if any(not math.isfinite(value) or abs(value) > self.config.max_abs_angle for value in normalized):
return HeadPoseEstimation(False, *normalized, reprojection_error=reprojection_error,
failure_reason="angle_out_of_range")