feat(v1): per-frame fall decision diagnostics overlay
PersonAnalysis now carries the policy Evidence; view_model builds a Qt-free per-person diagnostic line (acc/horiz/ang/rapid/cand/state, or the reject reason) and VideoView overlays it in a corner. Read-only, no decision change; locates where a real fall stops. 67 tests pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -99,6 +99,34 @@ class MonitorViewState:
|
||||
people: Tuple[PersonOverlay, ...]
|
||||
events: Tuple[EventBadge, ...]
|
||||
highest_state: FallState
|
||||
diagnostics: Tuple[str, ...] = ()
|
||||
|
||||
|
||||
def person_diagnostic_line(person) -> str:
|
||||
"""Compact per-person view of the fall decision, to locate where it stops.
|
||||
|
||||
Shows the quality gate (``acc``), horizontal geometry (``horiz``/``ang``),
|
||||
the rapid-drop signal (``rapid``), the policy candidate (``cand``) and the
|
||||
state. When the pose is rejected it shows the reason instead.
|
||||
"""
|
||||
|
||||
track_id = person.tracked_pose.track_id
|
||||
state = person.state.value
|
||||
pose_evidence = person.pose_evidence
|
||||
if pose_evidence is None or not pose_evidence.accepted:
|
||||
reason = getattr(pose_evidence, "reason", "no_evidence")
|
||||
return "{0} {1} acc=0 {2}".format(track_id, state, reason)
|
||||
angle = pose_evidence.horizontal_angle_degrees
|
||||
angle_text = "{0:.0f}deg".format(angle) if angle is not None else "-"
|
||||
candidate = int(getattr(person.evidence, "is_fall_candidate", False))
|
||||
return "{0} {1} acc=1 horiz={2} ang={3} rapid={4} cand={5}".format(
|
||||
track_id,
|
||||
state,
|
||||
int(pose_evidence.horizontal_pose),
|
||||
angle_text,
|
||||
int(pose_evidence.rapid_vertical_change),
|
||||
candidate,
|
||||
)
|
||||
|
||||
|
||||
def build_monitor_view(analysis, keypoint_min_confidence: float = 0.4) -> MonitorViewState:
|
||||
@@ -128,6 +156,7 @@ def build_monitor_view(analysis, keypoint_min_confidence: float = 0.4) -> Monito
|
||||
people=overlays,
|
||||
events=events,
|
||||
highest_state=_highest_state(overlays),
|
||||
diagnostics=tuple(person_diagnostic_line(person) for person in analysis.people),
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user