找回密码
 立即注册
首页 业界区 安全 【一步步开发AI运动APP】十一、同时检测识别多人运动, ...

【一步步开发AI运动APP】十一、同时检测识别多人运动,分别进行运动计时计数

庞悦 6 小时前
之前我们为您分享了【一步步开发AI运动小程序】开发系列博文,通过该系列博文,很多开发者开发出了很多精美的AI健身、线上运动赛事、AI学生体测、美体、康复锻炼等应用场景的AI运动小程序;为了帮助开发者继续深耕AI运动领域市场,今天开始我们将为您分享新系列【一步步开发AI运动APP】的博文,带您开发性能更强、体验更好的AI运动APP。
一、应用场景

在赛事活动多人PK对战、学生体测教学、运动角设备等开发应用场景中,经常存在需要同时检测多人运动需求;此需求在AI小程序时受限于小程序的运行环境,一直无法实现。而且APP版插件因为是原生执行环境,检测分析性能得以大幅提升,已可以实现同时检测多人姿态和运动能力了。
二、方案实现

根据下面的AI运动分析的流程图所示,要实现同时多人运动分析能力,须先实现多人的人体姿态检测,再将检出的多人人体结果,分别推送到不同的运动分析器实例,即可实现多人运动检测分析。
1.png

三、调用多人人体检测能力

详细的人体检测人体调用,请参考本系列第五章人体检测能力调用,将multiple选项参数设为true即可调用插件的多人人体检测能力,代码如下所示:
  1. import {createHumanDetector} from "@/uni_modules/yz-ai-sport";
  2. export default {
  3.         data(){
  4.                 return {};
  5.         }
  6.         methods:{
  7.                 onDetecting(){
  8.                         let options = {
  9.                                 multiple: true, //启用多人检测
  10.                                 enabledGPU: true,
  11.                                 highPerformance: false
  12.                         };
  13.                         const that = this;
  14.                         humanDetector = createHumanDetector(options);
  15.                         humanDetector.startExtractAndDetect({
  16.                                 onDetected(result){
  17.                                         let humans = result.humans; //注意:多人人体结构不是每次按顺序输出,且不能保证每次都能检出3人
  18.                                         that.$refs.grapher.drawing(humans);
  19.                                 }
  20.                         });
  21.                 }
  22.         }
  23. }
复制代码
但是上面的代码仅仅只能检出图像中多人人体结果,还无法实现定位人员,提取那个站在中间、左边、右边,所以在获得检出结果后,还需要对人体结果进行定位处理。假设在应用场景中要求人员从左往右横排站立,最多检出3人,我们则可以通过人体中的鼻子关键点(nose)进行定位,nose点的x小于屏幕宽度33%则为左,大于33%小于66%则为中,大于66%则为右,代码调整如下:
  1. import {createHumanDetector} from "@/uni_modules/yz-ai-sport";
  2. export default {
  3.         data(){
  4.                 return {};
  5.         }
  6.         methods:{
  7.                 locateHuamn(humans, begin, end) {
  8.                         if (!Array.isArray(humans))
  9.                                 return;
  10.                         //页面为横屏状态,受检测人员从左往右站立
  11.                         //横向将屏幕图像区域平均分配,按区域提取人员
  12.                         const that = this;
  13.                         let loc = humans.find(hu => {
  14.                                 let nose = hu.keypoints.find(x => x.name == 'nose');
  15.                                 if (!nose)
  16.                                         return false;
  17.                                 //人体结构中的坐标为相机图像中的坐标,计算出在屏幕中的渲染坐标
  18.                                 let x = nose.x * that.previewRate + that.previewOffsetX;
  19.                                 if (x <= that.previewWidth * begin)
  20.                                         return false;
  21.                                 if (end && x > that.previewWidth * end)
  22.                                         return false;
  23.                                 return true;
  24.                         });
  25.                         return loc;
  26.                 },
  27.                 onDetecting(){
  28.                         let options = {
  29.                                 multiple: true, //启用多人检测
  30.                                 enabledGPU: true,
  31.                                 highPerformance: false
  32.                         };
  33.                        
  34.                         const that = this;
  35.                         humanDetector = createHumanDetector(options);
  36.                         humanDetector.startExtractAndDetect({
  37.                                 onDetected(result){
  38.                                         let humans = result.humans; //注意:多人人体结构不是每次按顺序输出
  39.                                        
  40.                                         if (humans.length < 1) {
  41.                                         that.$refs.grapher.clear();
  42.                                         return;
  43.                                 }
  44.                                 that.$refs.grapher.drawing(humans);
  45.                                 //以nose.x进行人体定位为左、中、右
  46.                                 let leftHuman = that.locateHuamn(humans, 0, 0.33);
  47.                                 let centerHuman = that.locateHuamn(humans, 0.33, 0.66);
  48.                                 let rightHuman = that.locateHuamn(humans, 0.66);
  49.                                
  50.                                 }
  51.                         });
  52.                 }
  53.         }
  54. }
复制代码
四、多个运动分析调用

在获得了多人人体结果后,便可以创建多个运动分析器实例来,来分别对每个人的姿态进行分析检测,实现计时计数了,代码如下:
  1. import {createSport} from "@/uni_modules/yz-ai-sport";
  2. export default {
  3.         data(){
  4.                 return {
  5.                         ticks: [{
  6.                                         counts: 0,
  7.                                         times: 0,
  8.                                         timeText: '00:00'
  9.                                 }, {
  10.                                         counts: 0,
  11.                                         times: 0,
  12.                                         timeText: '00:00',
  13.                                 }, {
  14.                                         counts: 0,
  15.                                         times: 0,
  16.                                         timeText: '00:00',
  17.                         }]
  18.                 };
  19.         }
  20.         methods:{
  21.        
  22.         },
  23.         onLoad(options) {
  24.                 let key = options.sportKey || 'jumping-jack';
  25.                 //批量创建运动
  26.                 sports = [];
  27.                 const ticks = this.ticks;
  28.                 for (let i = 0; i < ticks.length; i++) {
  29.                         let sport = createSport(key);
  30.                         //分别将运动计数结果推不同位置数组
  31.                         sport.onTick((counts, times) => {
  32.                                 ticks[i].counts = counts;
  33.                                 ticks[i].times = times;
  34.                                 ticks[i].timeText = sport.toTimesString();
  35.                         });
  36.                         sports.push(sport);
  37.                 }
  38.         }
  39. }
复制代码
五、完整实现

下面是完整的实现代码,也可插件的最新支持资料包中获得。
  1. import {
  2.                 getCameraContext,
  3.                 createHumanDetector,
  4.                 createSport
  5.         } from "@/uni_modules/yz-ai-sport";
  6.        
  7.         let humanDetector = null;
  8.         let sports = null;
  9.        
  10.         export default {
  11.                 data() {
  12.                         const winfo = uni.getWindowInfo();
  13.                         const settings = uni.getSystemSetting();
  14.                         return {
  15.                                 isLandscape: settings.deviceOrientation == 'landscape',
  16.                                 cameraDevice: 'back',
  17.                                 frameWidth: 480,
  18.                                 frameHeight: 640,
  19.                                 previewWidth: winfo.windowWidth,
  20.                                 previewHeight: winfo.windowHeight,
  21.                                 previewRate: 1,
  22.                                 previewOffsetX: 0,
  23.                                 previewOffsetY: 0,
  24.                                 isExtracting: false,
  25.                                 sportKey: '',
  26.                                 sportName: '',
  27.                                 ticks: [{
  28.                                         counts: 0,
  29.                                         times: 0,
  30.                                         timeText: '00:00'
  31.                                 }, {
  32.                                         counts: 0,
  33.                                         times: 0,
  34.                                         timeText: '00:00',
  35.                                 }, {
  36.                                         counts: 0,
  37.                                         times: 0,
  38.                                         timeText: '00:00',
  39.                                 }]
  40.                         };
  41.                 },
  42.                 methods: {
  43.                         locateHuamn(humans, begin, end) {
  44.                                 if (!Array.isArray(humans))
  45.                                         return;
  46.                                 //页面为横屏状态,受检测人员从左往右站立
  47.                                 //横向将屏幕图像区域平均分配,按区域提取人员
  48.                                 const that = this;
  49.                                 let loc = humans.find(hu => {
  50.                                         let nose = hu.keypoints.find(x => x.name == 'nose');
  51.                                         if (!nose)
  52.                                                 return false;
  53.                                         //人体结构中的坐标为相机图像中的坐标,计算出在屏幕中的渲染坐标
  54.                                         let x = nose.x * that.previewRate + that.previewOffsetX;
  55.                                         if (x <= that.previewWidth * begin)
  56.                                                 return false;
  57.                                         if (end && x > that.previewWidth * end)
  58.                                                 return false;
  59.                                         return true;
  60.                                 });
  61.                                 return loc;
  62.                         },
  63.                         onDetecting(){
  64.                                 let options = {
  65.                                         multiple: true, //启用多人检测
  66.                                         enabledGPU: true,
  67.                                         highPerformance: false
  68.                                 };
  69.                                 const that = this;
  70.                                 humanDetector = createHumanDetector(options);
  71.                                 humanDetector.startExtractAndDetect({
  72.                                         onDetected(result){
  73.                                                 let humans = result.humans; //注意:多人人体结构不是每次按顺序输出
  74.                                                 if (humans.length < 1) {
  75.                                                         that.$refs.grapher.clear();
  76.                                                         return;
  77.                                                 }
  78.                                                 that.$refs.grapher.drawing(humans);
  79.                                                 //以nose.x进行人体定位为左、中、右
  80.                                                 let leftHuman = that.locateHuamn(humans, 0, 0.33);
  81.                                                 let centerHuman = that.locateHuamn(humans, 0.33, 0.66);
  82.                                                 let rightHuman = that.locateHuamn(humans, 0.66);
  83.                                         }
  84.                                 });
  85.                         }
  86.                 },
  87.                 onLoad(options) {
  88.                         let key = options.sportKey || 'jumping-jack';
  89.                         //批量创建运动
  90.                         sports = [];
  91.                         const ticks = this.ticks;
  92.                         for (let i = 0; i < ticks.length; i++) {
  93.                                 let sport = createSport(key);
  94.                                 //分别将运动计数结果推不同位置数组
  95.                                 sport.onTick((counts, times) => {
  96.                                         ticks[i].counts = counts;
  97.                                         ticks[i].times = times;
  98.                                         ticks[i].timeText = sport.toTimesString();
  99.                                 });
  100.                                 sports.push(sport);
  101.                         }
  102.                 }
  103.         }
复制代码
2.png


来源:豆瓜网用户自行投稿发布,如果侵权,请联系站长删除

相关推荐

您需要登录后才可以回帖 登录 | 立即注册