You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Sod/WebAssemby/face_detection_browser_usag...

94 lines
4.0 KiB

<!DOCTYPE html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>WebAssembly Real-Time Face Detection</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
}
</style>
<body>
<div align="center">
<h1>WebAssembly Real-Time Face Detection <small>via <a href="https://sod.pixlab.io" target="_blank">SOD RealNets</a></small></h1>
<button onclick="face_detect()">Start Face Detection</button><hr/>
<canvas id="face-canvas" style="border: 1px solid black;"></canvas>
<video id="face-video" autoplay playsinline hidden="true"></video>
</div>
<!-- This will load the RealNet WebAssembly face model and run its main.
The model must be downloaded from https://pixlab.io/downloads
Once downloaded, just put it on the directory where this HTML
file `usage.html` reside.
For chrome users, you must test the model on actual Web server,
whether served locally (i.e http://127.0.0.1) or remotely.
This is due to the fact that chrome does not allow WebAssembly
modules to be loaded directly from the file system (
Edge and Firefox does not have such issue).
-->
<script src="facemodel.js"></script>
<script>
function face_detect(){
var grayBuf = null; /* Working buffer holding the grayscale conversion of the current video frame */
var recs = null; /* Each detected face coordinates (top, left, width & height) is recorded in this array */
let vidSz = {width: 640, height: 480 , facingMode: "user" };
if (document.body.clientWidth < 600 ){
vidSz = true;
}
navigator.mediaDevices.getUserMedia({
audio: false,
video: vidSz
}).then(function(mediaStream) {
/* Code taken from https://faceio.net JavaScript Widget */
let video = document.getElementById('face-video');
let vidCanvas = document.getElementById('face-canvas');
let vidctx = vidCanvas.getContext('2d');
video.srcObject = mediaStream;
video.onloadedmetadata = function(e) {
vidCanvas.width = video.videoWidth;
vidCanvas.height = video.videoHeight;
video.play();
}
video.addEventListener('play', function () {
let fps = 1000 / 25; /* Render at 25 fps. Feel free to increase to 30 if you are on a PC/Mac or Modern iPhone */
let loop = function() {
if (!video.paused && !video.ended) {
vidctx.drawImage(video, 0, 0);
if( grayBuf === null ){
grayBuf = _realnet_alloc_gray_image_buffer(640, 480);
recs = new Float32Array(Module.HEAPU8.buffer, _realnet_alloc_face_result_array(), _realnet_face_max_detection());
}else{
let imgData = vidctx.getImageData(0,0, vidCanvas.width, vidCanvas.height);
let gray = new Uint8ClampedArray( Module.HEAPU8.buffer, grayBuf, imgData.width * imgData.height);
for (let i = 0; i < imgData.data.length ; i += 4) {
gray[i >> 2] = (imgData.data[i] * 306 + imgData.data[i + 1] * 601 + imgData.data[i + 2] * 117) >> 10;
}
let faces = _realnet_face_detect(grayBuf, imgData.width, imgData.height, 11.0, recs.byteOffset);
/* faces now hold the total number of detected faces and the recs[] array hold their coordinates */
for(let i = 0; i < faces; i += 5 ){
/* Draw a rectangle on each detected face */
vidctx.beginPath();
vidctx.strokeStyle = "#32cd32";
vidctx.strokeRect(recs[i + 0],recs[i + 1],recs[i + 2],recs[i + 3]);
/* recs[i + 4] hold the score (i.e. threshold) of the current face */
console.log("Face_" + i + ": Score: " + recs[i + 4]);
}
}
setTimeout(loop, fps);
}else{
console.log("Video stream stopped");
}
}
/* Start painting on the canvas */
loop();
});
}).catch(function(err){
console.log("Access not granted", err);
});
}
</script>
</body>
</html>