- A+
所属分类:Web前端
随着人工智能技术的不断发展,阿里体育等IT大厂,推出的“乐动力”、“天天跳绳”AI运动APP,让云上运动会、线上运动会、健身打卡、AI体育指导等概念空前火热。那么,能否将这些在APP成功应用的场景搬上小程序,分享这些概念的红利呢?本系列文章就带您一步一步从零开始开发一个AI运动小程序,本系列文章将使用“云智AI运动识别小程序插件”,请先行在微信服务市场或官网了解详情。
一、骨骼图绘制原理
人体骨骼图的绘制,是通过在camera
组件上附一个同等大小的透明canvas
组件,在上面绘制关键点达到与人体图像重合的目的。
二、绘制代码
<template> <view class="human-detection"> <camera id="preview" class="preview" :style="videoStyles" flash="off" :device-position="deviceKey" resolution="high" frame-size="low" @initdone="onCameraReady"> </camera> <canvas v-if="poseDrawEnabled" class="preview graphs" type="2d" id="graphics" :style="videoStyles"></canvas> </view> </template> <script> const AiSports = requirePlugin("aiSport"); const PoseGraphs = AiSports.PoseGraphs; const humanDetection = AiSports.humanDetection; export default { data() { return { zoom: 1, deviceKey: "back", previewWidth: 480, previewHeight: 640, previewRate: 1, frameWidth: 480, frameHeight: 640, status: 'unknown', fps: 0, poseFps: 0, isHumanBody: false }; }, computed: { videoStyles() { const style = `width:${this.previewWidth}px;height:${this.previewHeight}px;`; return style; } }, mounted() { this.autoFitPreview(480, 640); this.initCanvas(); }, methods: { autoFitPreview(width, height) { const sifno = uni.getSystemInfoSync(); let rate = sifno.windowWidth / width; this.previewWidth = width * rate; this.previewHeight = height * rate; this.previewRate = rate; this.frameWidth = width; this.frameHeight = height; }, initCanvas() { const that = this; const query = uni.createSelectorQuery().in(that); query.select('#graphics') .fields({ node: true, size: true }) .exec((res) => { if (utils.isEmptyArray(res)) return; const canvas = res[0].node; const ctx = canvas.getContext('2d'); const dpr = uni.getSystemInfoSync().pixelRatio; canvas.width = res[0].width * dpr; canvas.height = res[0].height * dpr; ctx.scale(dpr, dpr); that.canvas = canvas; that.ctx = ctx; that.poseGraphs = new PoseGraphs(ctx, canvas.width, canvas.height, 1); that.poseGraphs.lineColor = "#FF8E148C";//线条颜色 }); }, async detection(frame) { const human = await humanDetection.detectionAsync(frame); //无结果 if (!human) this.poseGraphs.clear(); else this.poseGraphs.drawing(human.keypoints); }, initVideo() { if (this.camera) return; const that = this; this.camera = new CameraDevice(); this.camera.onFrame = frame => { that.fps = that.camera.fps; //重新自适应 if (frame.width != that.frameWidth || frame.height != that.frameHeight) { that.autoFitPreview(frame.width, frame.height); that.initCanvas(); } that.detection(frame); }; } } } </script> <style lang="scss"> .human-detection { width: auto; height: auto; .preview { margin: auto; width: 480px; height: 640px; } .graphs { position: absolute; top: 0; left: 0; z-index: 9999; box-shadow: 0 0 14.4928rpx #CCC; background-color: rgba(0, 0, 0, 0.01); } } </style>
三、注意事项
小程序的抽帧图像大小与camera
实时图像可能不一致(https://developers.weixin.qq.com/miniprogram/dev/component/camera.html#Bug-Tip),所以camera
和canvas
组件必须保持与帧图像保持同比缩放,否则可能导致骨骼与实时图像不一致。
下篇我们将为您介绍如何进行运动分析,敬请期待...