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

简介: 本文介绍了如何开发支持多人运动检测的AI运动APP,涵盖多人人体检测、定位及运动分析实现方法,助力开发者打造高性能AI运动应用。

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

一、应用场景

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

二、方案实现

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

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

详细的人体检测人体调用,请参考本系列第五章人体检测能力调用,将multiple选项参数设为true即可调用插件的多人人体检测能力,代码如下所示:

import {
   createHumanDetector} from "@/uni_modules/yz-ai-sport";
export default {
   
    data(){
   
        return {
   };
    }
    methods:{
   
        onDetecting(){
   
            let options = {
   
                multiple: true, //启用多人检测
                enabledGPU: true,
                highPerformance: false
            };
            const that = this;
            humanDetector = createHumanDetector(options);
            humanDetector.startExtractAndDetect({
   
                onDetected(result){
   
                    let humans = result.humans; //注意:多人人体结构不是每次按顺序输出,且不能保证每次都能检出3人
                    that.$refs.grapher.drawing(humans);
                }
            });
        }
    }
}

但是上面的代码仅仅只能检出图像中多人人体结果,还无法实现定位人员,提取那个站在中间、左边、右边,所以在获得检出结果后,还需要对人体结果进行定位处理。假设在应用场景中要求人员从左往右横排站立,最多检出3人,我们则可以通过人体中的鼻子关键点(nose)进行定位,nose点的x小于屏幕宽度33%则为,大于33%小于66%则为,大于66%则为,代码调整如下:

import {
   createHumanDetector} from "@/uni_modules/yz-ai-sport";
export default {
   
    data(){
   
        return {
   };
    }
    methods:{
   
        locateHuamn(humans, begin, end) {
   
            if (!Array.isArray(humans))
                return;

            //页面为横屏状态,受检测人员从左往右站立
            //横向将屏幕图像区域平均分配,按区域提取人员

            const that = this;
            let loc = humans.find(hu => {
   
                let nose = hu.keypoints.find(x => x.name == 'nose');
                if (!nose)
                    return false;

                //人体结构中的坐标为相机图像中的坐标,计算出在屏幕中的渲染坐标
                let x = nose.x * that.previewRate + that.previewOffsetX;

                if (x <= that.previewWidth * begin)
                    return false;

                if (end && x > that.previewWidth * end)
                    return false;

                return true;
            });

            return loc;
        },
        onDetecting(){
   
            let options = {
   
                multiple: true, //启用多人检测
                enabledGPU: true,
                highPerformance: false
            };

            const that = this;
            humanDetector = createHumanDetector(options);
            humanDetector.startExtractAndDetect({
   
                onDetected(result){
   
                    let humans = result.humans; //注意:多人人体结构不是每次按顺序输出

                    if (humans.length < 1) {
   
                    that.$refs.grapher.clear();
                    return;
                }
                that.$refs.grapher.drawing(humans);

                //以nose.x进行人体定位为左、中、右
                let leftHuman = that.locateHuamn(humans, 0, 0.33);
                let centerHuman = that.locateHuamn(humans, 0.33, 0.66);
                let rightHuman = that.locateHuamn(humans, 0.66);

                }
            });
        }
    }
}

四、多个运动分析调用

在获得了多人人体结果后,便可以创建多个运动分析器实例来,来分别对每个人的姿态进行分析检测,实现计时计数了,代码如下:

import {
   createSport} from "@/uni_modules/yz-ai-sport";
export default {
   
    data(){
   
        return {
   
            ticks: [{
   
                    counts: 0,
                    times: 0,
                    timeText: '00:00'
                }, {
   
                    counts: 0,
                    times: 0,
                    timeText: '00:00',
                }, {
   
                    counts: 0,
                    times: 0,
                    timeText: '00:00',
            }]
        };
    }
    methods:{
   

    },
    onLoad(options) {
   
        let key = options.sportKey || 'jumping-jack';

        //批量创建运动
        sports = [];
        const ticks = this.ticks;
        for (let i = 0; i < ticks.length; i++) {
   
            let sport = createSport(key);

            //分别将运动计数结果推不同位置数组
            sport.onTick((counts, times) => {
   
                ticks[i].counts = counts;
                ticks[i].times = times;
                ticks[i].timeText = sport.toTimesString();
            });
            sports.push(sport);
        }
    }
}

五、完整实现

下面是完整的实现代码,也可插件的最新支持资料包中获得。

import {
   
        getCameraContext,
        createHumanDetector,
        createSport
    } from "@/uni_modules/yz-ai-sport";

    let humanDetector = null;
    let sports = null;

    export default {
   
        data() {
   

            const winfo = uni.getWindowInfo();
            const settings = uni.getSystemSetting();

            return {
   
                isLandscape: settings.deviceOrientation == 'landscape',
                cameraDevice: 'back',

                frameWidth: 480,
                frameHeight: 640,

                previewWidth: winfo.windowWidth,
                previewHeight: winfo.windowHeight,
                previewRate: 1,
                previewOffsetX: 0,
                previewOffsetY: 0,

                isExtracting: false,

                sportKey: '',
                sportName: '',
                ticks: [{
   
                    counts: 0,
                    times: 0,
                    timeText: '00:00'
                }, {
   
                    counts: 0,
                    times: 0,
                    timeText: '00:00',
                }, {
   
                    counts: 0,
                    times: 0,
                    timeText: '00:00',
                }]
            };
        },
        methods: {
   
            locateHuamn(humans, begin, end) {
   
                if (!Array.isArray(humans))
                    return;

                //页面为横屏状态,受检测人员从左往右站立
                //横向将屏幕图像区域平均分配,按区域提取人员

                const that = this;
                let loc = humans.find(hu => {
   
                    let nose = hu.keypoints.find(x => x.name == 'nose');
                    if (!nose)
                        return false;

                    //人体结构中的坐标为相机图像中的坐标,计算出在屏幕中的渲染坐标
                    let x = nose.x * that.previewRate + that.previewOffsetX;

                    if (x <= that.previewWidth * begin)
                        return false;

                    if (end && x > that.previewWidth * end)
                        return false;

                    return true;
                });

                return loc;
            },
            onDetecting(){
   
                let options = {
   
                    multiple: true, //启用多人检测
                    enabledGPU: true,
                    highPerformance: false
                };

                const that = this;
                humanDetector = createHumanDetector(options);
                humanDetector.startExtractAndDetect({
   
                    onDetected(result){
   
                        let humans = result.humans; //注意:多人人体结构不是每次按顺序输出

                        if (humans.length < 1) {
   
                            that.$refs.grapher.clear();
                            return;
                        }
                        that.$refs.grapher.drawing(humans);

                        //以nose.x进行人体定位为左、中、右
                        let leftHuman = that.locateHuamn(humans, 0, 0.33);
                        let centerHuman = that.locateHuamn(humans, 0.33, 0.66);
                        let rightHuman = that.locateHuamn(humans, 0.66);

                    }
                });
            }
        },
        onLoad(options) {
   
            let key = options.sportKey || 'jumping-jack';

            //批量创建运动
            sports = [];
            const ticks = this.ticks;
            for (let i = 0; i < ticks.length; i++) {
   
                let sport = createSport(key);

                //分别将运动计数结果推不同位置数组
                sport.onTick((counts, times) => {
   
                    ticks[i].counts = counts;
                    ticks[i].times = times;
                    ticks[i].timeText = sport.toTimesString();
                });
                sports.push(sport);
            }
        }
    }

115969-20250828114253867-901130529.png

相关文章
|
9月前
|
人工智能 数据安全/隐私保护
如何识别AI生成内容?探秘“AI指纹”检测技术
如何识别AI生成内容?探秘“AI指纹”检测技术
1828 119
|
9月前
|
机器学习/深度学习 人工智能 自然语言处理
AI检测技术:如何识别机器生成的“数字指纹”?
AI检测技术:如何识别机器生成的“数字指纹”?
551 115
|
9月前
|
人工智能 自然语言处理 算法
揭秘AI文本:当前主流检测技术与挑战
揭秘AI文本:当前主流检测技术与挑战
1664 115
|
9月前
|
人工智能 安全 API
20 万奖金池就位!Higress AI 网关开发挑战赛参赛指南
本次赛事共设三大赛题方向,参赛者可以任选一个方向参赛。本文是对每个赛题方向的参赛指南。
683 71
|
9月前
|
人工智能 运维 安全
加速智能体开发:从 Serverless 运行时到 Serverless AI 运行时
在云计算与人工智能深度融合的背景下,Serverless 技术作为云原生架构的集大成者,正加速向 AI 原生架构演进。阿里云函数计算(FC)率先提出并实践“Serverless AI 运行时”概念,通过技术创新与生态联动,为智能体(Agent)开发提供高效、安全、低成本的基础设施支持。本文从技术演进路径、核心能力及未来展望三方面解析 Serverless AI 的突破性价值。
|
9月前
|
人工智能 运维 Java
Spring AI Alibaba Admin 开源!以数据为中心的 Agent 开发平台
Spring AI Alibaba Admin 正式发布!一站式实现 Prompt 管理、动态热更新、评测集构建、自动化评估与全链路可观测,助力企业高效构建可信赖的 AI Agent 应用。开源共建,现已上线!
8250 120
|
9月前
|
人工智能 数据安全/隐私保护
AI生成的痕迹:我们如何检测机器撰写的文本
AI生成的痕迹:我们如何检测机器撰写的文本
2470 117
|
9月前
|
机器学习/深度学习 人工智能 自然语言处理
如何准确检测AI生成内容?这三大技术是关键
如何准确检测AI生成内容?这三大技术是关键
1205 116
|
9月前
|
机器学习/深度学习 人工智能 算法
火眼金睛:如何检测文本内容是否出自AI之手?
火眼金睛:如何检测文本内容是否出自AI之手?
1614 115

热门文章

最新文章