0%

pose_score | tensorflow.js 实时评估改进

之前,我是用的是定时器的方式。来做实时评估,具体可以参考。

后来,看了一下 google 的代码书写方式。

我改正了我的代码。具体如下。

逻辑都很简单,这里只贴一下比较重要的代码。

js

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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
...
import * as posenet from '@tensorflow-models/posenet';
...

const defaultPoseNetArchitecture = 'MobileNetV1';
const defaultQuantBytes = 2;
const defaultMultiplier = 1.0;
const defaultStride = 16;
const defaultInputResolution = 257;
let minPartConfidence = 0.5;
let nmsRadius = 30.0;

let canvas_video = document.getElementById("canvas_video")
const ctx_video = canvas_video.getContext('2d');

console.log("model is downloading ... ");


// 根据屏幕大小来绘制 canvas 和 video
let win_height = parseFloat($(document.body).height());

let videoHeight = win_height * 0.8;
let videoWidth = videoHeight * 0.7;
...

const load_menu = () => {
...
};

const show_image = (id) => {
...
}

const register = () => {
...
}

async function setupCamera() {
if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
throw new Error(
'Browser API navigator.mediaDevices.getUserMedia not available');
}

const video = document.getElementById('video');
video.width = videoWidth;
video.height = videoHeight;

video.srcObject = await navigator.mediaDevices.getUserMedia({
'audio': false,
'video': {
facingMode: 'user',
width: videoWidth,
height: videoHeight,
},
});

return new Promise((resolve) => {
video.onloadedmetadata = () => {
resolve(video);
};
});
}

async function loadVideo() {
const video = await setupCamera();
video.play();

return video;
}

const load = () => {
...
}

function detectPoseInRealTime(net, video) {

let tmp_canvas = document.createElement("canvas");
let tmp_ctx = tmp_canvas.getContext("2d");
tmp_canvas.width = videoWidth;
tmp_canvas.height = videoHeight;

async function poseDetectionFrame() {


let pose = await net.estimateSinglePose(video, {
flipHorizontal: false,
decodingMethod: 'multi-person',
maxDetections: 1,
scoreThreshold: minPartConfidence,
nmsRadius: nmsRadius,
});

tmp_ctx.clearRect(0, 0, videoWidth, videoHeight);
// Draw video
tmp_ctx.save();
tmp_ctx.scale(-1, 1);
tmp_ctx.translate(-videoWidth, 0);
tmp_ctx.drawImage(video, 0, 0, videoWidth, videoHeight);
drawKeypoints(pose.keypoints, tmp_ctx, 1);
drawSkeleton(pose.keypoints, tmp_ctx, 1);
tmp_ctx.restore();

ctx_video.drawImage(tmp_canvas, 0, 0, videoWidth, videoHeight);

let video_pose_theta = getVideoPose(pose.keypoints);
let score = getRealScore(getScore(image_pose_theta, video_pose_theta));
p_score.innerText = parseInt(score);

// 循环绘制,代替之前的定时绘制
requestAnimationFrame(poseDetectionFrame);
}

poseDetectionFrame();
}

async function bindPage() {
load();

//加载模型的时候 loading
$("#load").show();
$("#main").hide();
const net = await posenet.load({
architecture: defaultPoseNetArchitecture,
outputStride: defaultStride,
inputResolution: defaultInputResolution,
multiplier: defaultMultiplier,
quantBytes: defaultQuantBytes,
});
//模型加载出来出现画面
$("#load").hide();
$("#main").show();


let video;
try {
video = await loadVideo();
canvas_video.width = videoWidth;
canvas_video.height = videoHeight;
} catch (e) {
console.log(e);
throw e;
}
detectPoseInRealTime(net, video);
}

bindPage();

html

逻辑都非常简单,这里只说一下 load 画面布局。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<html>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<head>
<meta charset="UTF-8">
<title>实时舞姿比对</title>
</head>
<body>
<div id="load" style="text-align: center">

</div>
<div id="main">
这里面放 video
</div>
</body>

</html>
请我喝杯咖啡吧~