173 lines
4.5 KiB
JavaScript
173 lines
4.5 KiB
JavaScript
/**
|
|
* 原地踏步走运动
|
|
* 1.要求侧位视图。
|
|
* 2.左、右任一次摆臂和提脚视计数1。
|
|
*
|
|
* @alphaair
|
|
* 20230329 created.
|
|
**/
|
|
|
|
const utils = require("../../utils/utils");
|
|
const AiSport = requirePlugin("aiSport");
|
|
const SportBase = AiSport.sports.SportBase;
|
|
const Calculator = AiSport.calc.Calculator;
|
|
|
|
const CalcBase = AiSport.calc.CalcBase;
|
|
|
|
/**
|
|
* 原地踏步运动分析器
|
|
*/
|
|
class SportWalkInPlace extends SportBase {
|
|
|
|
/**
|
|
* 本运动检测规则
|
|
*/
|
|
rules = null
|
|
|
|
stateTran = -1
|
|
|
|
/**
|
|
* 初始化分析器
|
|
*
|
|
* @param {int?} pointThreshold 计算器取点评分阈值
|
|
*/
|
|
constructor(pointThreshold) {
|
|
super(pointThreshold);
|
|
|
|
this.tickMode = true; //计次模式
|
|
this._calcBase = new CalcBase();
|
|
this._calculator = new Calculator();
|
|
this._calculator.pointThreshold = this.pointThreshold;
|
|
|
|
this.rules = {};
|
|
this.buildRules();
|
|
}
|
|
|
|
/**
|
|
* 构建检测规则
|
|
*/
|
|
buildRules() {
|
|
|
|
this.rules.basePose = {
|
|
name: '站立状态',
|
|
calc: 'stand',
|
|
offset: 80
|
|
};
|
|
|
|
this.rules.armPose = {
|
|
name: '摆臂状态',
|
|
calc: '$and',
|
|
rules: [{
|
|
name: '左手伸值',
|
|
calc: 'match-angle',
|
|
angleKey: 'left_elbow',
|
|
secondKey: 'left_shoulder',
|
|
thirdKey: 'left_wrist',
|
|
angle: 155,
|
|
offset: 25
|
|
}, {
|
|
name: '左手摆臂',
|
|
calc: 'match-angle',
|
|
angleKey: 'left_shoulder',
|
|
secondKey: 'left_hip',
|
|
thirdKey: 'left_wrist',
|
|
angle: 68,
|
|
offset: 43
|
|
}, {
|
|
name: '右手伸值',
|
|
calc: 'match-angle',
|
|
angleKey: 'right_elbow',
|
|
secondKey: 'right_shoulder',
|
|
thirdKey: 'right_wrist',
|
|
angle: 155,
|
|
offset: 25
|
|
}, {
|
|
name: '右手摆臂',
|
|
calc: 'match-angle',
|
|
angleKey: 'right_shoulder',
|
|
secondKey: 'right_hip',
|
|
thirdKey: 'right_wrist',
|
|
angle: 68,
|
|
offset: 43
|
|
}]
|
|
};
|
|
|
|
this.rules.leftLeg = {
|
|
name: '左脚抬起',
|
|
calc: 'match-angle',
|
|
angleKey: 'left_knee',
|
|
secondKey: 'left_hip',
|
|
thirdKey: 'left_ankle',
|
|
angle: 125,
|
|
offset: 35
|
|
};
|
|
|
|
this.rules.rightLeg = {
|
|
name: '右脚抬起',
|
|
calc: 'match-angle',
|
|
angleKey: 'right_knee',
|
|
secondKey: 'right_hip',
|
|
thirdKey: 'right_ankle',
|
|
angle: 125,
|
|
offset: 35
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 启动分析
|
|
*/
|
|
start() {
|
|
super.start();
|
|
this.stateTran = -1;
|
|
}
|
|
|
|
/**
|
|
* 接受帧识别结果,进行分析
|
|
*
|
|
* @param {BodyDetectionResult} body 人体检测结果
|
|
*/
|
|
pushing(body) {
|
|
|
|
if (utils.isNone(body))
|
|
return;
|
|
|
|
//基本姿态
|
|
if (!this._calculator.calculating(body, this.rules.basePose) ||
|
|
!this._calculator.calculating(body, this.rules.armPose)) {
|
|
console.debug('基本姿态未通过');
|
|
return;
|
|
}
|
|
|
|
let leg = -1; //1-左边 2-右边
|
|
if (this.stateTran === -1 || this.stateTran === 2) {
|
|
if (this._calculator.calculating(body, this.rules.leftLeg))
|
|
leg = 1;
|
|
else
|
|
console.error('左侧未通过');
|
|
}
|
|
|
|
if (leg === -1 || this.stateTran === 1) {
|
|
if (this._calculator.calculating(body, this.rules.rightLeg))
|
|
leg = 2;
|
|
else
|
|
console.error('右侧未通过');
|
|
}
|
|
|
|
const leftAngle = this._calcBase.angle(body.keypoints[13], body.keypoints[11], body.keypoints[15]);
|
|
const rightAngle = this._calcBase.angle(body.keypoints[14], body.keypoints[13], body.keypoints[16]);
|
|
|
|
console.debug(this.stateTran, leg, leftAngle, rightAngle);
|
|
if (this.stateTran === leg || leg === -1)
|
|
return;
|
|
|
|
//互斥才计数,防止中间动作被计数
|
|
this.stateTran = leg;
|
|
this.countTimes();
|
|
this.emitTick();
|
|
}
|
|
}
|
|
|
|
SportWalkInPlace.KEY = "Walk-In-Place";
|
|
SportWalkInPlace.NAME = "自定义-原地踏步";
|
|
|
|
module.exports = SportWalkInPlace; |