1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
| """ OOP检测算法: 基于关键点的乘员姿态估计
输入: OMS摄像头帧 (RGB, 全局快门) 输出: 乘员姿态等级 + 安全气囊控制信号
关键点检测: 头部中心, 左右肩, 左右髋, 左右膝 姿态计算: 躯干角度, 侧倾角度, 前倾距离, submarining风险 """
import numpy as np from typing import Tuple
class OOPDetector: """乘员异常姿态检测器""" def __init__(self): self.KEYPOINTS = [ "head_center", "left_shoulder", "right_shoulder", "left_hip", "right_hip", "left_knee", "right_knee" ] self.FORWARD_TILT_THRESHOLD = 20.0 self.BACKWARD_TILT_THRESHOLD = -15.0 self.LATERAL_TILT_THRESHOLD = 15.0 self.SUBMARINING_HIP_OFFSET = 50 def detect_pose(self, keypoints: np.ndarray) -> dict: """ 从关键点检测乘员姿态 Args: keypoints: shape=(7, 2), 7个关键点的(x,y)坐标 [head, L_shoulder, R_shoulder, L_hip, R_hip, L_knee, R_knee] Returns: pose: { 'torso_angle': 躯干前倾/后仰角度(正=前倾), 'lateral_angle': 侧倾角度(正=右倾), 'forward_offset': 前倾距离(mm), 'submarining_risk': 0-1, 'oop_level': 0=正常, 1=轻度, 2=中度, 3=重度, 'airbag_mode': 'low_power'|'high_power'|'standard'|'disable' } """ head, l_sh, r_sh, l_hip, r_hip, l_knee, r_knee = keypoints shoulder_mid = (l_sh + r_sh) / 2 hip_mid = (l_hip + r_hip) / 2 torso_vec = shoulder_mid - hip_mid torso_angle = np.degrees(np.arctan2(torso_vec[0], -torso_vec[1])) shoulder_vec = r_sh - l_sh lateral_angle = np.degrees(np.arctan2(shoulder_vec[1], shoulder_vec[0])) forward_offset = abs(shoulder_mid[0] - hip_mid[0]) knee_mid = (l_knee + r_knee) / 2 hip_knee_vec = knee_mid - hip_mid hip_forward = hip_knee_vec[1] < -20 submarining_risk = 0.0 if hip_forward and torso_angle > 10: submarining_risk = 0.7 elif hip_forward: submarining_risk = 0.4 elif torso_angle > self.FORWARD_TILT_THRESHOLD: submarining_risk = 0.3 oop_level = 0 airbag_mode = "standard" if torso_angle > self.FORWARD_TILT_THRESHOLD: oop_level = 2 airbag_mode = "low_power" elif torso_angle < self.BACKWARD_TILT_THRESHOLD: oop_level = 1 airbag_mode = "high_power" if abs(lateral_angle) > self.LATERAL_TILT_THRESHOLD: oop_level = max(oop_level, 2) airbag_mode = "low_power" if submarining_risk > 0.5: oop_level = 3 airbag_mode = "disable" return { 'torso_angle': round(float(torso_angle), 1), 'lateral_angle': round(float(lateral_angle), 1), 'forward_offset': round(float(forward_offset), 1), 'submarining_risk': round(float(submarining_risk), 2), 'oop_level': oop_level, 'airbag_mode': airbag_mode }
if __name__ == "__main__": detector = OOPDetector() normal_pose = np.array([ [320, 100], [280, 200], [360, 200], [290, 350], [350, 350], [285, 500], [355, 500], ], dtype=np.float32) result = detector.detect_pose(normal_pose) print(f"正常坐姿: OOP={result['oop_level']}, 模式={result['airbag_mode']}, 躯干角度={result['torso_angle']}°") forward_pose = np.array([ [340, 120], [310, 210], [370, 210], [290, 350], [350, 350], [285, 500], [355, 500], ], dtype=np.float32) result2 = detector.detect_pose(forward_pose) print(f"前倾坐姿: OOP={result2['oop_level']}, 模式={result2['airbag_mode']}, 躯干角度={result2['torso_angle']}°") submarining_pose = np.array([ [330, 130], [295, 230], [365, 230], [310, 340], [370, 340], [280, 480], [360, 480], ], dtype=np.float32) result3 = detector.detect_pose(submarining_pose) print(f"Submarining风险: OOP={result3['oop_level']}, 模式={result3['airbag_mode']}, 风险={result3['submarining_risk']}")
|