微信小游戏用tensorflow.js人体姿势PoseNet控制
tensorflow.js官方特别支持了微信小程序,看tfjs-core,fjs-backend-webgl等等模块的dist下都一个单独的miniprogram目录。
还特别提供了一个微信小程序的插件:https://github.com/tensorflow/tfjs-wechat
tensorflow.js对微信小游戏还不支持,但是可以类似的实现,但是效率不高;
小游戏不支持插件,直接使用tfjs-webchat源码,我名称改为tfjs-plugin。
试试一个头部姿势,左右,点头控制:
基本的引用:
let sysInfo=wx.getSystemInfoSync();
const fetchWechat = require('fetch-wechat');
//window.fetch=fetchWechat.fetchFunc();const tf_core = require('@tensorflow/tfjs-core');
let tf_poseNet=require('@tensorflow-models/posenet');
const tf_webgl = require('@tensorflow/tfjs-backend-webgl');
const tf_plugin = require('./js/libs/@tensorflow/tfjs-plugin/index.js');//不能用主屏幕,组屏幕是2d的
let tf_canvas=wx.createCanvas();///必须指定webGL 1.0版本,微信小游戏只实现了这个版本,不支持2.0
tf_core.ENV.flagRegistry.WEBGL_VERSION.evaluationFn = function() {return 1;}
//tf_core.ENV.set('WEBGL_PACK', false);tf_plugin.configPlugin({//backendName:'wechat-webgl',fetchFunc: fetchWechat.fetchFunc(),tf:tf_core,webgl:tf_webgl,canvas: tf_canvas
},false);
载入官方预训练好的poseNet模型,先尝试从本地缓存加载,失败时从服务器加载,加载成功后保存到本地缓存:
const POSENET_URL = 'https://ai.flypot.cn/models/posenet/model.json';
const FILE_STORAGE_PATH='poseNet';
const fileStorageHandler = tf_plugin.fileStorageIO(FILE_STORAGE_PATH, wx.getFileSystemManager());
let g_model=null;function loadModel(options){if (g_model){if (options.success) options.success(g_model);return;}let cfg={architecture: 'MobileNetV1',outputStride: 16,//越大速度越快inputResolution: 193,//越小速度越快multiplier: 0.5//越小越快}function loadFromLocal(){console.log('load model from local................');wx.showLoading({title: '从本地加载模型...',mask:true});//https://github.com/tensorflow/tfjs-models/tree/master/posenetcfg.modelUrl=fileStorageHandler;tf_poseNet.load(cfg).then(function(model){console.log('model loaded');wx.hideLoading();//console.log(model);g_model = model;if (options.success){options.success(model);}},function(err){console.log(err);loadFromServer();});}function loadFromServer(){console.log('load model from server................');wx.showLoading({title: '从服务器加载模型...',mask:true});cfg.modelUrl=POSENET_URL;tf_poseNet.load(cfg).then(function(model){console.log('model loaded');wx.hideLoading();//console.log(model);model.baseModel.model.save(fileStorageHandler);g_model = model;if (options.success){options.success(model);}},function(err){console.log(err);wx.hideLoading();if (options.fail){options.fail(err);}});}loadFromLocal();
}
载入模型后,打开camera,开始侦测,没有办法直接画在摄像头的canvas上,所以摄像头的canvas设置为1x1大小,相当于隐藏起来。
因为每次人体姿势检测在手机上大概要花80-110ms,很慢,所以不能摄像头视频每帧都检测,10帧检测一次,否则很卡:
let g_camera=null;
let frameIndex=0;
let canvas_camera,ctx_camera;
let camera_imageData;function startPoseNetControl(options){function doIt(){//demoDetect();openCamera();if (options.success) options.success();options.complete();}if (g_model) {doIt();return;}loadModel({success:function(model){// wx.showModal({// content: 'model loaded.'// });doIt();},fail:function(err){wx.showModal({content: JSON.stringify(err)});if (options.fail) options.fail(err);options.complete();}});
}function stopPoseNetControl(options){if (g_camera){g_camera.destroy();g_camera=null;}canvas_camera=null;if (options.success) options.success();options.complete();
}function openCamera(){g_camera=wx.createCamera({width:1,//不影响onFrame返回的width和heightheight:1,devicePosition:'front',size:'small',flash:'off',success:function(res){console.log('camera opened.');console.log(res);g_camera.listenFrameChange();},fail:function(e){console.log('camera open fail:',e);}});g_camera.onCameraFrame(function(frame){//console.log(frame.width);frameIndex++;if (frameIndex<10) return;if (!canvas_camera){canvas_camera=wx.createCanvas();canvas_camera.width=frame.width;canvas_camera.height=frame.height;ctx_camera=canvas_camera.getContext('2d');camera_imageData = ctx_camera.createImageData(frame.width,frame.height);}let pixels=new Uint8Array(frame.data);detectFrame({pixels:pixels,width:frame.width,height:frame.height,success:function(res){camera_imageData.data.set(pixels);ctx_camera.putImageData(camera_imageData,0,0);displayResult(res);frameIndex=0;},fail:function(err){frameIndex=0;}});});
}
调用人体姿势检测:
function detectFrame(options){//let t1=new Date();g_model.estimateSinglePose({data:options.pixels,width:options.width,height:options.height}, {flipHorizontal: false}).then(function(res){//每次检测,在pc模拟器中:第1次要800-900ms,第2次只要60-90ms//手机上:第2次后每次80-110msoptions.success(res);},function(err){options.fail(err);});
}let g_noseEys_distance=999999;function displayResult(pose){//console.log(pose);const minPoseConfidence = 0.3;const minPartConfidence = 0.3;if (pose.score >= minPoseConfidence) {drawKeypoints(pose.keypoints, minPartConfidence, ctx_camera);//drawBoundingBox(pose.keypoints,ctx_camera);//drawSkeleton(pose.keypoints, minPartConfidence, ctx_camera);if (!wx.tmGlobal.isAllowControl()) return;//鼻子高度-左眼高度let dy1=Math.round(pose.keypoints[0].position.y-pose.keypoints[1].position.y); //左眼高度-右眼高度let dy2=pose.keypoints[1].position.y-pose.keypoints[2].position.y;//console.log(dy2);if (dy1-g_noseEys_distance>10 && dy2>-10 && dy2<10){//低头时,鼻子-左眼间距加大wx.tmGlobal.webGL.releaseCurrentBall();}else{wx.tmGlobal.webGL.moveCurrentBall(dy2);}g_noseEys_distance=dy1;}
}const color = 'aqua';
const boundingBoxColor = 'red';
const lineWidth = 2;function drawKeypoints(keypoints, minConfidence, ctx, scale = 1) {for (let i = 0; i < keypoints.length; i++) {const keypoint = keypoints[i];if (keypoint.score < minConfidence) {continue;}const { y, x } = keypoint.position;drawPoint(ctx, y * scale, x * scale, 5, color);}
}function drawPoint(ctx, y, x, r, color) {ctx.beginPath()ctx.arc(x, y, r, 0, 2 * Math.PI);ctx.fillStyle = color;ctx.fill();ctx.stroke();
}
微信小游戏用tensorflow.js人体姿势PoseNet控制相关推荐
- 微信小游戏_China_Fighting——game.js、game.json、project.config.json
目录 微信小游戏_China_Fighting--前言 微信小游戏_China_Fighting--基础支撑类(sprite.animation.pool) 微信小游戏_China_Fighting- ...
- 微信小游戏、three.js、真机调试,出现锯齿的解决办法
更正: 原文是基于微信小游戏,在微信开发者工具.手机端微信小游戏,该方案没问题. 我今天尝试移植到普通web,该方案出现新问题: 1)不使用该方案,则出现锯齿. 2)使用该方案,则正圆变成椭圆. 暂时 ...
- 新手入门:如何用Laya开发微信小游戏?
1.环境准备 1.1 LayaAirIDE 1.7.14版本才开始集成微信小游戏开发. 1.2 微信小游戏开发工具 微信小游戏开发工具是小游戏开发与测试的环境,由于LayaAir引擎的开发者完全可以使 ...
- Laya之微信小游戏入门
1.环境准备 1.1 LayaAirIDE 1.7.14版本才开始集成微信小游戏开发 1.2 微信小游戏开发工具 微信小游戏开发工具是小游戏开发与测试的环境,由于LayaAir引擎的开发者完全可以使用 ...
- 在微信小游戏中开发一个贪食蛇
为什么80%的码农都做不了架构师?>>> 我自己也写过一个贪食蛇的小游戏,不过是对dom的操作,微信小游戏是采用js语法基于canvas的开发.为了省事在网上直接搜了一个基于c ...
- 微信小游戏_China_Fighting——npc类(enemy、mask、sars)
目录 微信小游戏_China_Fighting--前言 微信小游戏_China_Fighting--基础支撑类(sprite.animation.pool) 微信小游戏_China_Fighting- ...
- 微信小游戏_China_Fighting——后记
目录 微信小游戏_China_Fighting--前言 微信小游戏_China_Fighting--基础支撑类(sprite.animation.pool) 微信小游戏_China_Fighting- ...
- 微信小游戏_China_Fighting——前言
目录 微信小游戏_China_Fighting--前言 微信小游戏_China_Fighting--基础支撑类(sprite.animation.pool) 微信小游戏_China_Fighting- ...
- 微信小游戏 demo 飞机大战 代码分析(四)(enemy.js, bullet.js, index.js)
微信小游戏 demo 飞机大战 代码分析(四)(enemy.js, bullet.js, index.js) 微信小游戏 demo 飞机大战 代码分析(一)(main.js) 微信小游戏 demo 飞 ...
最新文章
- 记录ALiYun EMR常用服务的手动启动和停止命令(hdfs/yarn/mr-jobhistory/zk/spark-history)
- (转)个例子让你了解Java反射机制
- android Mp3播放器之音频文件扫描
- thinkphp几个表的数据合并,并用数组分页
- iar 看时序_IAR 硬件仿真查看运行时间
- C语言程序main入口函数
- c语言 在txt文件中搜索关键词_网络推广外包—网络推广外包如何在搜索引擎中体现关键词优化效果...
- C++中const char *p和char const *p
- asp.net捕获全局未处理异常的几种方法
- 二分答案——小车问题(洛谷 P1258)
- 默认地址路径修改_修改Docker默认路径
- nj04---事件回调函数
- 是谁断送了网络工程师的前途
- Vulkan入门(一)-环境配置.md
- ssm整合开发配置文件
- 论文笔记:Show, Edit and Tell : A Framework for Editing Image Captions
- 记-微服务CPU100%排查之windows版
- OpenCV笔记-对轮廓进行平滑处理
- 破解root密码详细流程
- Hexo博客Next主题配置加载优化性能提升
热门文章
- 基于STM32的智能循迹避障小车实验(小车运动部分)
- ros机器小车运动控制
- Ubuntu 17.04 x64 安装 Docker CE 初窥 Dockerfile 部署 Ngi
- 电大c语言形考作业网上作业,C语言程序设计电大形考作业
- 【论文】:NEZHA(哪吒)
- 口袋妖怪c语言代码大全,口袋妖怪漆黑的魅影金手指代码大全
- Linux下类迅雷的下载神器-uGet 2.0
- 我的世界无限天空服务器,我的世界1.8-1.12魔塔天空RPG服务器
- c++11工厂子类实现自注册的两种方法
- 四个主要的连接池介绍!(建议收藏!)