Files
silver_pose/v2/internal/fall/evidence.go
T

63 lines
2.2 KiB
Go
Raw Normal View History

2026-07-22 16:18:16 +08:00
package fall
import (
"math"
"silverpose/v2/internal/pose"
)
var torsoJoints = [...]int{5, 6, 11, 12}
var lowerJoints = [...]int{13, 14, 15, 16}
func assessPoseQuality(person pose.PersonPose, threshold float32, requireLowerBody bool) PoseQuality {
if threshold < 0 || threshold > 1 {
return PoseQuality{Reason: "invalid_threshold"}
}
visible := 0
for _, keypoint := range person.Keypoints {
if keypoint.Confidence >= threshold {
visible++
}
}
for _, index := range torsoJoints {
if person.Keypoints[index].Confidence < threshold {
return PoseQuality{Reason: "required_joint_low_confidence", VisibleJointCount: visible}
}
}
if requireLowerBody {
for _, index := range lowerJoints {
if person.Keypoints[index].Confidence < threshold {
return PoseQuality{Reason: "required_joint_low_confidence", VisibleJointCount: visible}
}
}
}
return PoseQuality{Accepted: true, Reason: "accepted", VisibleJointCount: visible}
}
func extractEvidence(person pose.PersonPose, quality PoseQuality, previous *PoseEvidence, horizontalAngleThreshold float32) PoseEvidence {
if !quality.Accepted {
return PoseEvidence{Reason: quality.Reason}
}
shoulderX, shoulderY := midpoint(person, 5, 6)
hipX, hipY := midpoint(person, 11, 12)
vectorX := hipX - shoulderX
vectorY := hipY - shoulderY
torsoLength := float32(math.Hypot(float64(vectorX), float64(vectorY)))
if torsoLength == 0 {
return PoseEvidence{HipCenterY: hipY, HasHipCenterY: true, TorsoLength: 0, Reason: "degenerate_torso"}
}
cosine := math.Max(-1, math.Min(1, math.Abs(float64(vectorX))/float64(torsoLength)))
angle := float32(math.Acos(cosine) * 180 / math.Pi)
rapid := previous != nil && previous.Accepted && previous.HasHipCenterY && hipY-previous.HipCenterY >= 0.5*torsoLength
return PoseEvidence{
Accepted: true, HorizontalPose: angle <= horizontalAngleThreshold,
RapidVerticalChange: rapid, HorizontalAngleDegree: angle, HasAngle: true,
HipCenterY: hipY, HasHipCenterY: true, TorsoLength: torsoLength, Reason: "accepted",
}
}
func midpoint(person pose.PersonPose, first, second int) (float32, float32) {
return (person.Keypoints[first].X + person.Keypoints[second].X) / 2,
(person.Keypoints[first].Y + person.Keypoints[second].Y) / 2
}