【一步步开发AI运动小程序】六、人体骨骼图绘制

  • 【一步步开发AI运动小程序】六、人体骨骼图绘制已关闭评论
  • 197 次浏览
  • A+
所属分类:Web前端
摘要

随着人工智能技术的不断发展,阿里体育等IT大厂,推出的“乐动力”、“天天跳绳”AI运动APP,让云上运动会、线上运动会、健身打卡、AI体育指导等概念空前火热。那么,能否将这些在APP成功应用的场景搬上小程序,分享这些概念的红利呢?本系列文章就带您一步一步从零开始开发一个AI运动小程序,本系列文章将使用“云智AI运动识别小程序插件”,请先行在微信服务市场或官网了解详情。


随着人工智能技术的不断发展,阿里体育等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),所以cameracanvas组件必须保持与帧图像保持同比缩放,否则可能导致骨骼与实时图像不一致。

下篇我们将为您介绍如何进行运动分析,敬请期待...