forked from nihui/ncnn-webassembly-yolov5
-
Notifications
You must be signed in to change notification settings - Fork 3
/
cn.html
344 lines (273 loc) · 13.5 KB
/
cn.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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
<html lang="zh">
<head>
<meta charset="utf-8">
<title>WearMask: 口罩检测AI | 实时快速,即开即用</title>
<meta name="description" content="浏览器内置免费口罩检测器。只需一个平板,你就能获得一个口罩检测AI!为小商业和公共场所设计,让我们共同应对COVID-19。" />
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-ZJ6JEE5PWX"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-ZJ6JEE5PWX');
</script>
<link rel="stylesheet" type="text/css" href="index.css?version=2.0.4">
<style>
a:link,a:visited{
text-decoration:none;
}
a:hover{
text-decoration:underline;
}
video {
/* position: absolute;
visibility: hidden; */
}
canvas {
border: 1px solid lightgray;
}
</style>
</head>
<body>
<div class="wrapper">
<div class="logo-wrapper">
<a href="https://facemask-detection.com/cn.html" target="_parent" rel="noopener noreferrer">
<img class="logo" src="gallary/logo.png">
</a>
<h3>WearMask: 实时口罩检测</h3>
<div class="tags">
<a class="tag" href="https://facemask-detection.com/" title="English Version">English</a>
<a class="tag" href="https://facemask-detection.com/es.html" title="Spanish Version">Español</a>
<a class="tag" href="https://facemask-detection.com/cn.html" title="Chinese Version">中文</a>
</div>
<div class='remind_box'>
<h1 id="remind", font size="50">加载中...</h1>
</div>
</div>
<div class='video_box'>
<canvas id="canvas" width="640"></canvas>
<video autoplay muted playsinline id="video"></video>
</div>
<div class='box_bottom'>
<div class='tips'>
<p>
小提示:只有<b>完全</b>覆盖鼻孔和嘴巴才能预防病毒哦!
</p>
</div>
<div class="feedback">
<div class="tags">
<a class="tag" href="mailto:[email protected]?subject=Feedback&body=如有错误结果截图,请放在此处。" title="报告失败案例或与开发者交流" >Feedback</a>
</div>
</div>
</div>
<br /><br /><br />
<div class="intro">
<details open>
<summary>介绍</summary>
<h2>如何获得最佳体验?</h2>
<p>
1. 启动最新版<a href="https://www.google.com/chrome/" target="_blank" rel="noopener noreferrer">Chrome 浏览器</a><br />
2. 在地址栏输入并打开<i> chrome://flags </i><br />
3. 启动所有 <i>WebAssembly</i> 相关功能<br />
4. 重启Chrome浏览器并允许开启摄像头<br />
<br />检测帧率取决于您的设备CPU。iOS系统用户暂时只能使用Safari,检测帧数可能相对较低。
</p>
<h2>隐私声明</h2>
<p>
不用担心。该口罩检测程序完全在您浏览器内运行,不会保存任何数据或上传任何内容到服务器。您甚至可以在开始运行后切断网络连接。
<br />您也可以查看完整的<a href="https://facemask-detection.com/statement_cn.html" target="_parent" rel="noopener noreferrer">服务申明</a>。
</p>
<h2>项目简介</h2>
<p>
Web-based efficient AI recognition of masks (WearMask) 是一个深度学习项目。所用模型修改自<a href="https://github.com/dog-qiuqiu/Yolo-Fastest" target="_blank" rel="noopener noreferrer">Yolo-Fastest</a>,并基于<a href="https://github.com/dog-qiuqiu/Yolo-Fastest" target="_blank" rel="noopener noreferrer">Pytorch</a> 框架训练,通过<a href="https://github.com/Tencent/ncnn" target="_blank" rel="noopener noreferrer">NCNN</a>和<a href="https://webassembly.org/" target="_blank" rel="noopener noreferrer">WebAssembly</a>实现浏览器内运行。
</p>
<p>
所有内容已在<a href="https://github.com/waittim/mask-detector" target="_blank" rel="noopener noreferrer">Github</a>开源,您可访问<a href="https://arxiv.org/abs/2101.00784" target="_blank" rel="noopener noreferrer">arXiv</a>和我的<a href="https://waittim.github.io/2020/11/27/mask-detection/" target="_blank" rel="noopener noreferrer">博客</a>了解更多细节。如果您也想为本项目做出贡献,可将包含错误结果的截图发送至<a href="mailto:[email protected]?subject=Incorrect case&body=请将截图放在此处。" title="feedback" >该邮箱</a>,谢谢!
</p>
<br /><br /><br /><br /><br />
<div class='footer'>
<p>
<!-- <a href="https://www.linkedin.com/in/zekun-wang/" > <img src="gallary/linkedin-logo.png" alt="View Zekun Wang’s profile on LinkedIn"></a>
-->
<!-- <a href="https://github.com/waittim/mask-detector/" > <img src="gallary/github-logo.png" alt="View Zekun Wang’s Github"></a>
-->
<a href="https://www.nsf.gov/" > <img src="gallary/nsf-logo.png" alt="View National Science Foundation"></a>
<a href="https://www.vanderbilt.edu/" > <img src="gallary/VU-logo.jpg" alt="View Vanderbilt University"></a>
<br />
<br />
<a href="https://www.linkedin.com/in/zekun-wang/" target="_blank" rel="noopener noreferrer">Zekun Wang</a> | <a href="https://www.vanderbilt.edu/datascience/" target="_blank" rel="noopener noreferrer">Vanderbilt University</a>
<br />
<br />
</p>
</div>
</details>
</div>
</div>
<script src="wasmFeatureDetect.js?version=2.0.3"></script>
<script type='text/javascript'>
var Module = {};
var has_simd;
var has_threads;
var wasmModuleLoaded = false;
var wasmModuleLoadedCallbacks = [];
Module.onRuntimeInitialized = function() {
wasmModuleLoaded = true;
for (var i = 0; i < wasmModuleLoadedCallbacks.length; i++) {
wasmModuleLoadedCallbacks[i]();
}
}
wasmFeatureDetect.simd().then(simdSupported => {
has_simd = simdSupported;
wasmFeatureDetect.threads().then(threadsSupported => {
has_threads = threadsSupported;
if (has_simd & has_threads)
{
yolo_module_name = 'yolo';
console.log('simd&threads enabled.');
}
else
{
yolo_module_name = 'ios/yolo-ios';
console.log('cannot enable simd&threads.');
}
console.log('load ' + yolo_module_name);
var yolowasm = yolo_module_name + '.wasm';
var yolojs = yolo_module_name + '.js';
fetch(yolowasm)
.then(response => response.arrayBuffer())
.then(buffer => {
Module.wasmBinary = buffer;
var script = document.createElement('script');
script.src = yolojs;
script.onload = function() {
console.log('Emscripten boilerplate loaded.');
}
document.body.appendChild(script);
});
});
});
var dst = null;
var resultarray = null;
var resultbuffer = null;
window.addEventListener('DOMContentLoaded', function() {
var isStreaming = false;
video = document.getElementById('video');
canvas = document.getElementById('canvas');
ctx = canvas.getContext('2d');
w = 640;
h = 480;
var constraints = { audio: false, video: { width: w, height: h } };
navigator.mediaDevices.getUserMedia(constraints)
.then(function(mediaStream) {
var video = document.querySelector('video');
video.srcObject = mediaStream;
video.onloadedmetadata = function(e) {
video.play();
};
})
.catch(function(err) {
console.log(err.message);
});
// Wait until the video stream canvas play
video.addEventListener('canplay', function(e) {
if (!isStreaming) {
// videoWidth isn't always set correctly in all browsers
if (video.videoWidth > 0) h = video.videoHeight / (video.videoWidth / w);
canvas.setAttribute('width', w);
canvas.setAttribute('height', h);
isStreaming = true;
}
}, false);
// Wait for the video to start to play
video.addEventListener('play', function() {
//Setup image memory
var id = ctx.getImageData(0, 0, canvas.width, canvas.height);
var d = id.data;
if (wasmModuleLoaded) {
mallocAndCallSFilter();
} else {
wasmModuleLoadedCallbacks.push(mallocAndCallSFilter);
}
function mallocAndCallSFilter() {
dst = _malloc(d.length);
// max 20 objects
resultarray = new Float32Array(6 * 20);
resultbuffer = _malloc(6 * 20 * Float32Array.BYTES_PER_ELEMENT);
HEAPF32.set(resultarray, resultbuffer / Float32Array.BYTES_PER_ELEMENT);
//console.log("What " + d.length);
sFilter();
}
});
});
var class_names = [
"background",
"无口罩", "有口罩"
];
var colors = [
"rgb( 255, 69, 0)",
"rgb( 32, 178, 170)"
];
function ncnn_yolo() {
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
var data = imageData.data;
ctx.font = '12px sans-serif'
HEAPU8.set(data, dst);
_yolo_ncnn(dst, canvas.width, canvas.height, resultbuffer);
// resultarray
var qaqarray = HEAPF32.subarray(resultbuffer / Float32Array.BYTES_PER_ELEMENT, resultbuffer / Float32Array.BYTES_PER_ELEMENT + 6 * 20);
var i;
var remind_ctx = '欢迎光临';
for (i = 0; i < 20; i++) {
var label = qaqarray[i * 6 + 0];
var prob = qaqarray[i * 6 + 1];
var bbox_x = qaqarray[i * 6 + 2];
var bbox_y = qaqarray[i * 6 + 3];
var bbox_w = qaqarray[i * 6 + 4];
var bbox_h = qaqarray[i * 6 + 5];
if (label == -233)
continue;
console.log('qaq ' + label + ' = ' + prob);
//ctx.strokeStyle = colors[i % 19];
if (label == 1) {
ctx.strokeStyle = colors[0];
ctx.fillStyle = colors[0];
remind_ctx = '请戴好口罩';
}
else {
ctx.strokeStyle = colors[1];
ctx.fillStyle = colors[1];
}
ctx.strokeRect(bbox_x, bbox_y, bbox_w, bbox_h);
ctx.lineWidth = 2;
var text = class_names[label] + ": " + parseFloat(prob * 100).toFixed(2) + "%";
ctx.textBaseline = 'top';
var text_width = ctx.measureText(text).width;
var text_height = parseInt(ctx.font, 10);
var x = bbox_x;
var y = bbox_y - text_height;
if (y < 0)
y = 0;
if (x + text_width > canvas.width)
x = canvas.width - text_width;
//ctx.fillStyle = "rgb(255,255,255)";
ctx.fillRect(x-1, y-2, text_width+4, text_height+2);
ctx.fillStyle = "rgb(255,255,255)";
ctx.fillText(text, x+1, y-2);
}
// console.log(remind_ctx);
document.getElementById('remind').innerHTML = remind_ctx;
}
//Request Animation Frame function
var sFilter = function() {
if (video.paused || video.ended) return;
ctx.fillRect(0, 0, w, h);
ctx.drawImage(video, 0, 0, w, h);
ncnn_yolo();
window.requestAnimationFrame(sFilter);
}
</script>
</body>
</html>