feat(v1): relax fall sensitivity for low overhead cameras
Adds configurable event.require_rapid_drop (default off), require_lower_body (default off) and horizontal_angle_threshold_degrees (default 45). With the lenient defaults a sustained horizontal pose alone enters SUSPECT and confirms after the confirm window, which is now the main false-positive guard; missing knees/ankles no longer reject the pose. Thresholds flow into config_version. End-to-end smoke confirms a lying pose; 70 tests pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+14
-2
@@ -49,6 +49,8 @@ class FallPipeline:
|
||||
policy: FallEvidencePolicy,
|
||||
state_machine: FallStateMachine,
|
||||
keypoint_confidence_threshold: float,
|
||||
require_lower_body: bool = True,
|
||||
horizontal_angle_threshold_degrees: float = 35.0,
|
||||
) -> None:
|
||||
if not 0.0 <= keypoint_confidence_threshold <= 1.0:
|
||||
raise ValueError("keypoint_confidence_threshold must be between 0 and 1")
|
||||
@@ -57,6 +59,8 @@ class FallPipeline:
|
||||
self._policy = policy
|
||||
self._state_machine = state_machine
|
||||
self._keypoint_confidence_threshold = float(keypoint_confidence_threshold)
|
||||
self._require_lower_body = bool(require_lower_body)
|
||||
self._horizontal_angle_threshold_degrees = float(horizontal_angle_threshold_degrees)
|
||||
self._previous_evidence: Dict[str, PoseEvidence] = {}
|
||||
self._active_track_ids = set()
|
||||
|
||||
@@ -74,7 +78,10 @@ class FallPipeline:
|
||||
return cls(
|
||||
pose_adapter=pose_adapter,
|
||||
tracker=PersonTracker(),
|
||||
policy=FallEvidencePolicy(config.event.suspect_window_seconds),
|
||||
policy=FallEvidencePolicy(
|
||||
config.event.suspect_window_seconds,
|
||||
require_rapid_drop=config.event.require_rapid_drop,
|
||||
),
|
||||
state_machine=FallStateMachine(
|
||||
confirm_window_seconds=config.event.confirm_window_seconds,
|
||||
recovery_window_seconds=config.event.recovery_window_seconds,
|
||||
@@ -83,6 +90,8 @@ class FallPipeline:
|
||||
session_id=session_id or new_session_id(),
|
||||
),
|
||||
keypoint_confidence_threshold=config.event.keypoint_confidence_threshold,
|
||||
require_lower_body=config.event.require_lower_body,
|
||||
horizontal_angle_threshold_degrees=config.event.horizontal_angle_threshold_degrees,
|
||||
)
|
||||
|
||||
def process(self, packet: FramePacket) -> FrameAnalysis:
|
||||
@@ -102,12 +111,15 @@ class FallPipeline:
|
||||
people = []
|
||||
for tracked in tracked_poses:
|
||||
quality = assess_pose_quality(
|
||||
tracked.pose, threshold=self._keypoint_confidence_threshold
|
||||
tracked.pose,
|
||||
threshold=self._keypoint_confidence_threshold,
|
||||
require_lower_body=self._require_lower_body,
|
||||
)
|
||||
pose_evidence = extract_evidence(
|
||||
tracked.pose,
|
||||
quality=quality,
|
||||
previous=self._previous_evidence.get(tracked.track_id),
|
||||
horizontal_angle_threshold_degrees=self._horizontal_angle_threshold_degrees,
|
||||
)
|
||||
state_before = self._state_machine.state_of(tracked.track_id)
|
||||
evidence = self._policy.evaluate(
|
||||
|
||||
Reference in New Issue
Block a user