-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathdetect-camera.html
150 lines (130 loc) · 5.5 KB
/
detect-camera.html
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
147
148
149
150
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>tfjs - face deta</title>
<script src="./lib/js/tfjs.js"></script>
<script src="./lib/js/blazeface.js"></script>
</head>
<body>
<input type="checkbox" name="" id="loveInEyes" checked>情人西施
<input type="checkbox" name="" id="wearMask">防疫达人
<input type="checkbox" name="" id="redMouse">烈焰红唇
<input type="checkbox" name="" id="smile">蜜汁微笑
<div id="container">
<video src="" autoplay playsinline muted onloadeddata="onLoad()" onloadedmetadata="main()"></video>
</div>
<script>
let model = null;
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
const input = document.querySelector('video');
document.querySelector('#container').appendChild(canvas);
async function main() {
const currentTime = Date.now();
if (model) {
// Pass in an image or video to the model. The model returns an array of
// bounding boxes, probabilities, and landmarks, one for each detected face.
const returnTensors = false; // Pass in `true` to get tensors back, rather than values.
// 通常我们会把这一些计算放到 worker 中,但是由于 work 不能传递 DOM 节点
const predictions = await model.estimateFaces(input, returnTensors);
context.clearRect(0, 0, canvas.width, canvas.height);
context.drawImage(input, 0, 0);
// Pass in an image or video to the model. The model returns an array of
// bounding boxes, probabilities, and landmarks, one for each detected face.
if (predictions.length > 0) {
console.log('predictions ', predictions);
/*
`predictions` is an array of objects describing each detected face, for example:
[
{
topLeft: [232.28, 145.26],
bottomRight: [449.75, 308.36],
probability: [0.998],
landmarks: [
[295.13, 177.64], // right eye
[382.32, 175.56], // left eye
[341.18, 205.03], // nose
[345.12, 250.61], // mouth
[252.76, 211.37], // right ear
[431.20, 204.93] // left ear
]
}
]
*/
for (let i = 0; i < predictions.length; i++) {
const start = predictions[i].topLeft;
const end = predictions[i].bottomRight;
const size = [end[0] - start[0], end[1] - start[1]];
const rightEyeP = predictions[i].landmarks[0];
const leftEyeP = predictions[i].landmarks[1];
const noseP = predictions[i].landmarks[2];
const mouseP = predictions[i].landmarks[3];
const rightEarP = predictions[i].landmarks[4];
const leftEarP = predictions[i].landmarks[5];
// Render a rectangle over each detected face.
// context.fillRect(start[0], start[1], size[0], size[1]);
// 覆盖
// const fontSize = end[1] - start[1];
// context.font = `${fontSize}px/${fontSize}px serif`
// context.fillText('😗', start[0], start[1] + fontSize);
// 姚明迷之微笑
if (smile.checked) {
const image = new Image();
image.src = "./assets/images/yaoMingSmile.jpeg";
image.onload = function() {
const top = noseP[1] - start[1];
const left = start[0];
// 嘴巴为中心点,一半上面一半下面
context.drawImage(image, start[0], start[1], size[0], size[1]);
}
}
// 眼睛添加爱心
if (loveInEyes.checked) {
const fontSize = rightEyeP[1] - start[1];
context.font = `${fontSize}px/${fontSize}px serif`;
context.fillStyle = 'red';
context.fillText('❤️', rightEyeP[0] - fontSize / 2, rightEyeP[1]);
context.fillText('❤️', leftEyeP[0] - fontSize / 2, leftEyeP[1]);
}
// 戴口罩
if (wearMask.checked) {
const image = new Image();
image.src = "./assets/images/mouthMask.png";
image.onload = function() {
const top = noseP[1] - start[1];
const left = start[0];
// 嘴巴为中心点,一半上面一半下面
context.drawImage(image, mouseP[0] - size[0] / 2, mouseP[1] - size[1] / 2, size[0], size[1]);
}
}
// 加个烈焰红唇
if (redMouse.checked) {
// 嘴巴大概是眼睛之前的宽度
const fontSize = Math.abs(rightEyeP[0] - leftEyeP[0]);
context.font = `${fontSize}px/${fontSize}px serif`;
context.fillStyle = 'red';
context.fillText('👄', mouseP[0] - fontSize / 2, mouseP[1] + fontSize / 2);
}
}
}
}
requestAnimationFrame(main)
}
async function start() {
const localStream = await navigator.mediaDevices.getUserMedia({video: {}});
input.srcObject = localStream;
}
async function onLoad() {
canvas.width = input.videoWidth;
canvas.height = input.videoHeight;
// Load the model.
model = await blazeface.load();
}
start();
// main();
</script>
</body>
</html>