姿态估计后处理:动作识别与行为分析
姿态估计后处理动作识别与行为分析1. 基于关键点的动作识别动作识别方案 ├── 基于规则角度/距离阈值判断 ├── 基于时序关键点轨迹分析 ├── 基于分类器关键点特征 → 分类模型 └── 基于 Transformer时序关键点序列建模2. 角度计算#!/usr/bin/env python3angle_calc.py - 关键点角度计算importnumpyasnpdefcalculate_angle(a,b,c):计算三个关键点形成的角度b 为顶点a,b,cnp.array(a),np.array(b),np.array(c)baa-b bcc-b cosinenp.dot(ba,bc)/(np.linalg.norm(ba)*np.linalg.norm(bc)1e-8)anglenp.arccos(np.clip(cosine,-1.0,1.0))returnnp.degrees(angle)# 常用角度defget_body_angles(keypoints):获取身体各部位角度angles{}# 左肘角度左肩-左肘-左腕angles[left_elbow]calculate_angle(keypoints[5][:2],keypoints[7][:2],keypoints[9][:2])# 右肘角度右肩-右肘-右腕angles[right_elbow]calculate_angle(keypoints[6][:2],keypoints[8][:2],keypoints[10][:2])# 左膝角度左髋-左膝-左踝angles[left_knee]calculate_angle(keypoints[11][:2],keypoints[13][:2],keypoints[15][:2])# 右膝角度右髋-右膝-右踝angles[right_knee]calculate_angle(keypoints[12][:2],keypoints[14][:2],keypoints[16][:2])# 躯干角度肩膀中点-髋部中点 与垂直线的夹角shoulder_mid(np.array(keypoints[5][:2])np.array(keypoints[6][:2]))/2hip_mid(np.array(keypoints[11][:2])np.array(keypoints[12][:2]))/2trunk_vecshoulder_mid-hip_mid verticalnp.array([0,-1])angles[trunk]np.degrees(np.arccos(np.dot(trunk_vec,vertical)/(np.linalg.norm(trunk_vec)1e-8)))returnangles3. 基于规则的动作识别#!/usr/bin/env python3action_recognition.py - 基于规则的动作识别importnumpyasnpclassActionRecognizer:基于规则的动作识别器def__init__(self):self.history[]# 历史关键点self.max_history30# 1 秒 30fpsdefrecognize(self,keypoints):识别动作anglesget_body_angles(keypoints)self.history.append(keypoints)iflen(self.history)self.max_history:self.history.pop(0)actions[]# 1. 站立ifself._is_standing(angles,keypoints):actions.append(standing)# 2. 坐下ifself._is_sitting(angles,keypoints):actions.append(sitting)# 3. 蹲下ifself._is_squatting(angles,keypoints):actions.append(squatting)# 4. 跌倒ifself._is_falling(keypoints):actions.append(falling)# 5. 举手ifself._is_raising_hand(keypoints):actions.append(raising_hand)# 6. 跑步ifself._is_running(angles):actions.append(running)returnactionsdef_is_standing(self,angles,kpts):判断站立return(angles.get(left_knee,0)160andangles.get(right_knee,0)160andangles.get(trunk,0)20)def_is_sitting(self,angles,kpts):判断坐下return(angles.get(left_knee,0)120andangles.get(left_knee,0)60andangles.get(trunk,0)30)def_is_squatting(self,angles,kpts):判断蹲下return(angles.get(left_knee,0)90andangles.get(right_knee,0)90)def_is_falling(self,kpts):判断跌倒iflen(self.history)10:returnFalse# 检查躯干角度变化shoulder_mid(np.array(kpts[5][:2])np.array(kpts[6][:2]))/2hip_mid(np.array(kpts[11][:2])np.array(kpts[12][:2]))/2trunk_vecshoulder_mid-hip_mid trunk_anglenp.degrees(np.arctan2(abs(trunk_vec[0]),abs(trunk_vec[1])))returntrunk_angle60def_is_raising_hand(self,kpts):判断举手# 左手腕高于左肩left_raisekpts[9][1]kpts[5][1]# 右手腕高于右肩right_raisekpts[10][1]kpts[6][1]returnleft_raiseorright_raisedef_is_running(self,angles):判断跑步iflen(self.history)10:returnFalse# 检查脚踝位置变化速度ankle_positions[(h[15][0],h[16][0])forhinself.history[-10:]]speednp.mean(np.abs(np.diff([a[0]forainankle_positions])))returnspeed104. 跌倒检测#!/usr/bin/env python3fall_detection.py - 跌倒检测importtimeclassFallDetector:跌倒检测器def__init__(self,threshold_angle60,threshold_speed50):self.threshold_anglethreshold_angle self.threshold_speedthreshold_speed self.prev_shoulder_yNoneself.prev_timeNonedefdetect(self,keypoints):检测跌倒# 躯干角度shoulder_mid((keypoints[5][0]keypoints[6][0])/2,(keypoints[5][1]keypoints[6][1])/2)hip_mid((keypoints[11][0]keypoints[12][0])/2,(keypoints[11][1]keypoints[12][1])/2)trunk_vec[shoulder_mid[0]-hip_mid[0],shoulder_mid[1]-hip_mid[1]]trunk_angleabs(np.degrees(np.arctan2(trunk_vec[0],-trunk_vec[1])))# 下落速度current_timetime.time()fall_speed0ifself.prev_shoulder_yisnotNoneandself.prev_timeisnotNone:dtcurrent_time-self.prev_timeifdt0:fall_speed(shoulder_mid[1]-self.prev_shoulder_y)/dt self.prev_shoulder_yshoulder_mid[1]self.prev_timecurrent_time# 判定跌倒is_falling(trunk_angleself.threshold_angleandfall_speedself.threshold_speed)return{is_falling:is_falling,trunk_angle:trunk_angle,fall_speed:fall_speed,}5. 动作计数#!/usr/bin/env python3exercise_counter.py - 运动计数器importnumpyasnpclassExerciseCounter:运动计数器俯卧撑/深蹲/仰卧起坐def__init__(self,exercise_typepushup):self.exercise_typeexercise_type self.count0self.stateup# up / downself.angle_history[]defupdate(self,keypoints):更新计数anglesget_body_angles(keypoints)ifself.exercise_typepushup:angleangles.get(left_elbow,180)up_thresh,down_thresh150,90elifself.exercise_typesquat:angleangles.get(left_knee,180)up_thresh,down_thresh160,90elifself.exercise_typesitup:angleangles.get(trunk,0)up_thresh,down_thresh30,60else:returnself.count self.angle_history.append(angle)# 状态转换ifself.stateupandangledown_thresh:self.statedownelifself.statedownandangleup_thresh:self.stateupself.count1returnself.count6. 实时动作识别系统#!/usr/bin/env python3realtime_action.py - 实时动作识别importcv2fromtrt_poseimportTRTPoseDetector,draw_posefromaction_recognitionimportActionRecognizerdefmain():modelTRTPoseDetector(yolo26n-pose.engine)recognizerActionRecognizer()counterExerciseCounter(squat)capcv2.VideoCapture(0)whileTrue:ret,framecap.read()ifnotret:breakdetectionsmodel.detect(frame)fordetindetections:kptsdet[keypoints]actionsrecognizer.recognize(kpts)countcounter.update(kpts)# 绘制framedraw_pose(frame,[det])# 显示动作y_offset30foractioninactions:cv2.putText(frame,action,(10,y_offset),cv2.FONT_HERSHEY_SIMPLEX,0.8,(0,255,0),2)y_offset30cv2.putText(frame,fCount:{count},(10,y_offset),cv2.FONT_HERSHEY_SIMPLEX,1,(0,0,255),2)cv2.imshow(Action,frame)ifcv2.waitKey(1)0xFFord(q):breakcap.release()cv2.destroyAllWindows()if__name____main__:main()总结动作判断依据准确率站立膝盖角度 160°95%坐下膝盖角度 60-120°90%蹲下膝盖角度 90°92%跌倒躯干角度 60° 下落速度88%举手手腕高于肩膀95%跑步脚踝移动速度85%