安装过程
- 小程序官网 –> 登录 –> 设置 –> 插件 –> 添加插件
- npm init –> install @tensorflow/tfjs-converter 和 @tensorflow/tfjs-core 以及 fetch-wechat
- 小程序开发工具 –> 工具 –> 构建npm
- 按照官网开发文档在app.json中进行声明 以及 在app.js的onLaunch中调用插件
创建camera对象和canvas对象
通过camera对象获取实时的姿势动作,传给后台模型去处理,处理结果通过canvas对象进行显示。
创建camera对象
在
<camera>...</camera>
中添加canvas对象使用TF模型
打开TF官网
- Body 用来实现人物与背景分离
- Text toxicity 用来过滤掉敏感词汇
- Universal sentence encoder 用来将文本进行编码为向量 可以通过向量来比较两个句子之间的相关性 做文本分类的工作
- Object detection 用来检测一张图片上的多个物体 将物体进行分析出位置以及相关信息等
使用PoseNet模型
通过官网进入github页面 按照开发文档步骤 先安装包
1
yarn add @tensorflow-models/posenet引入
1
const posenet = require('@tensorflow-models/posenet')
1
2
3
4
5
6this.net = await posenet.load({
architecture: 'MobileNetV1',
outputStride: 16,
inputResolution: 193,
multiplier: 0.5
})
由于模型比较大,所以一般采取异步的方式去加载
注意: 与前端开发不同
前端开发需要什么包,就直接下载完成包;小程序中要考虑项目大小的问题,安装的都是子包
要实现异步,需要安装npm install regenerator-runtime
使用regenerator需要注意,在小程序开发工具 详情中 去掉ES6->ES5的转化
异步加载模型 并 处理imgData
域名问题 需要 到小程序官网的开发配置中 配置服务器信息 / 或者在开发工具的详情中 勾选不进行域名校验
编写检测姿势函数detectPose(),图像数据是3通道数据,而模型接收到的只能是4通道数据,所以需要进行数据转化。
使用tidy和estimatePose,注意内存的节约
绘制姿态
- 点
- 线
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86// index.js
const tf = require('@tensorflow/tfjs-core')
const posenet = require('@tensorflow-models/posenet')
const regeneratorRuntime = require('regenerator-runtime')
Page({
// 因为模型加载时间会比较大 onLoad是在小程序打开加载时触发 将onLoad改为onReady 加载完成后触发
async onReady() {
const camera = wx.createCameraContext(this)
// 后面需要将canvas去传给别的方法进行调用 所以将canvas作为this下的一个实例属性
this.canvas = wx.createCanvasContext('pose', this)
// 加载模型
this.loadPosenet()
// 计数器每隔4帧 显示信息
let count = 0
const listener = camera.onCameraFrame((frame) => {
count++
if (count === 4){
if (this.net) {
console.log(frame.data)
this.drawPose(frame)
}
count = 0
}
})
// listener.start()
},
async loadPosenet() {
this.net = await posenet.load({
architecture: 'MobileNetV1',
outputStride: 16,
inputResolution: 193,
multiplier: 0.5
})
console.log('模型数据:',this.net);
},
// 检测的函数
async detectPose(frame, net) {
// 数据转化
const imgData = {data: new Uint8Array(frame.data), width: frame.width, height: frame.height}
const imgSlice = tf.tidy(() => {
const imgTensor = tf.browser.fromPixels(imgData, 4)
return imgTensor.slice([0, 0, 0], [-1, -1, 3]) // 第一个参数图片的[宽,高,通道数]
})
const pose = await net.estimateSinglePose(imgSlice, {flipHorizontal: false})
imgSlice.dispose()
return pose
}
// 画出来
async drawPose(frame) {
const pose = await this.detectPose(frame, this.net)
if (pose == null || page.canvas == null) return
if (pose.score >= 0.3) {
for (i in pose.keypoints) {
console.log(pose.keypoints[i]) //画点 下一步就是画线
const point = pose.keypoints[i]
if (point.score >= 0.5) {
const {y, x} = point.position
// Draw circle
this.drawCircle(this.canvas, x, y)
}
}
// Draw lines
const adjacentKeyPoints = posenet.getAdjacentKeyPoints(pose.keypoints, 0.5)
for (i in adjacentKeyPoints) {
const points = adjacentKeyPoints[i]
this.drawLine(points[0])
}
this.canvas.draw()
},
drawCircle(canvas, x, y) {
canvas.beginPath()
canvas.arc(x * 0.72, y * 0.72, 3, 0, 2 * Math.PI)
canvas.fillStyle = 'aqua'
canvas.fill()
},
drawLine(canvas, pos0, pos1) {
canvas.beginPath()
canvas.moveTo(pos0.x * 0.72, pos0.y * 0.72)
canvas.LineTo(pos1.x * 0.72, pos1.y * 0.72)
canvas.lineWidth = 2
canvas.strokeStyle = 'aqua'
canvas.stroke()
}
}
})
版本问题太多了 重新自己跟着开发文档进行
安装包
1
2
3yarn add @tensorflow-models/pose-detection
yarn add @tensorflow/tfjs-core, @tensorflow/tfjs-converter
yarn add @tensorflow/tfjs-backend-webgl