add dynamic viewport and fix web worker

pull/134/head
Vladimir Mandic 2021-04-05 11:48:24 -04:00
parent 18586f5a9e
commit da8e441ad9
14 changed files with 214 additions and 199 deletions

View File

@ -1,6 +1,6 @@
# @vladmandic/human
Version: **1.3.3**
Version: **1.3.4**
Description: **Human: AI-powered 3D Face Detection, Face Description & Recognition, Body Pose Tracking, Hand & Finger Tracking, Iris Analysis, Age & Gender & Emotion Prediction & Gesture Recognition**
Author: **Vladimir Mandic <mandic00@live.com>**
@ -9,9 +9,13 @@ Repository: **<git+https://github.com/vladmandic/human.git>**
## Changelog
### **HEAD -> main** 2021/04/04 mandic00@live.com
### **HEAD -> main** 2021/04/05 mandic00@live.com
### **1.3.4** 2021/04/04 mandic00@live.com
- implement webhint
### **1.3.3** 2021/04/03 mandic00@live.com
- fix linting and tests

View File

@ -3,7 +3,7 @@
<head>
<title>Human</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, shrink-to-fit=yes">
<meta name="viewport" content="width=device-width">
<meta name="keywords" content="Human">
<meta name="application-name" content="Human">
<meta name="description" content="Human: 3D Face Detection, Body Pose, Hand & Finger Tracking, Iris Tracking, Age & Gender Prediction, Emotion Prediction & Gesture Recognition; Author: Vladimir Mandic <https://github.com/vladmandic>">
@ -19,12 +19,12 @@
body { margin: 0; background: black; color: white; overflow-x: hidden }
body::-webkit-scrollbar { display: none; }
hr { width: 100%; }
.play { position: absolute; width: 250px; height: 250px; z-index: 9; top: 55%; left: 50%; margin-left: -125px; display: none; }
.play { position: absolute; width: 250px; height: 250px; z-index: 9; bottom: 15%; left: 50%; margin-left: -125px; display: none; }
.btn-background { fill:grey; cursor: pointer; opacity: 0.6; }
.btn-background:hover { opacity: 1; }
.btn-foreground { fill:white; cursor: pointer; opacity: 0.8; }
.btn-foreground:hover { opacity: 1; }
.status { position: absolute; width: 100vw; bottom: 15%; text-align: center; font-size: 4rem; font-weight: 100; text-shadow: 2px 2px darkslategrey; }
.status { position: absolute; width: 100vw; bottom: 10%; text-align: center; font-size: 4rem; font-weight: 100; text-shadow: 2px 2px darkslategrey; }
.thumbnail { margin: 8px; box-shadow: 0 0 4px 4px dimgrey; }
.thumbnail:hover { box-shadow: 0 0 8px 8px dimgrey; filter: grayscale(1); }
.log { position: absolute; bottom: 0; margin: 0.4rem; font-size: 0.9rem; }

View File

@ -189,6 +189,9 @@ async function drawResults(input) {
async function setupCamera() {
if (ui.busy) return null;
ui.busy = true;
const viewportScale = Math.min(1, Math.round(100 * window.outerWidth / 700) / 100);
log('demo viewport scale:', viewportScale);
document.querySelector('meta[name=viewport]').setAttribute('content', `width=device-width, shrink-to-fit=no; initial-scale=${viewportScale}`);
const video = document.getElementById('video');
const canvas = document.getElementById('canvas');
const output = document.getElementById('log');
@ -569,6 +572,7 @@ async function main() {
const res = await human.warmup(userConfig); // this is not required, just pre-warms all models for faster initial inference
if (res && res.canvas && ui.drawWarmup) await drawWarmup(res);
}
await setupCamera();
status('human: ready');
document.getElementById('loader').style.display = 'none';
document.getElementById('play').style.display = 'block';

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

164
dist/human.esm.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

164
dist/human.js vendored

File diff suppressed because one or more lines are too long

4
dist/human.js.map vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

6
dist/human.node.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -18,13 +18,13 @@ export function process(input, config): { tensor: tf.Tensor, canvas: OffscreenCa
if (!input) throw new Error('Human: Input is missing');
if (
!(input instanceof tf.Tensor)
&& !(input instanceof Image)
&& !(input instanceof ImageData)
&& !(input instanceof ImageBitmap)
&& !(input instanceof HTMLImageElement)
&& !(input instanceof HTMLVideoElement)
&& !(input instanceof HTMLCanvasElement)
&& !(input instanceof OffscreenCanvas)
&& !(typeof Image !== 'undefined' && input instanceof Image)
&& !(typeof ImageData !== 'undefined' && input instanceof ImageData)
&& !(typeof ImageBitmap !== 'undefined' && input instanceof ImageBitmap)
&& !(typeof HTMLImageElement !== 'undefined' && input instanceof HTMLImageElement)
&& !(typeof HTMLVideoElement !== 'undefined' && input instanceof HTMLVideoElement)
&& !(typeof HTMLCanvasElement !== 'undefined' && input instanceof HTMLCanvasElement)
&& !(typeof OffscreenCanvas !== 'undefined' && input instanceof OffscreenCanvas)
) {
throw new Error('Human: Input type is not recognized');
}
@ -107,14 +107,21 @@ export function process(input, config): { tensor: tf.Tensor, canvas: OffscreenCa
if (fx) fx = null;
}
let pixels;
if (outCanvas.data) {
if (outCanvas.data) { // if we have data, just convert to tensor
const shape = [outCanvas.height, outCanvas.width, 3];
pixels = tf.tensor3d(outCanvas.data, shape, 'int32');
} else if ((config.backend === 'webgl') || (outCanvas instanceof ImageData)) {
// tf kernel-optimized method to get imagedata, also if input is imagedata, just use it
} else if (outCanvas instanceof ImageData) { // if input is imagedata, just use it
pixels = tf.browser.fromPixels(outCanvas);
} else {
// cpu and wasm kernel does not implement efficient fromPixels method nor we can use canvas as-is, so we do a silly one more canvas
} else if (config.backend === 'webgl' || config.backend === 'humangl') { // tf kernel-optimized method to get imagedata
// we can use canvas as-is as it already has a context, so we do a silly one more canvas
const tempCanvas = (typeof OffscreenCanvas !== 'undefined') ? new OffscreenCanvas(targetWidth, targetHeight) : document.createElement('canvas');
tempCanvas.width = targetWidth;
tempCanvas.height = targetHeight;
const tempCtx = tempCanvas.getContext('2d');
tempCtx?.drawImage(outCanvas, 0, 0);
pixels = tf.browser.fromPixels(tempCanvas);
} else { // cpu and wasm kernel does not implement efficient fromPixels method
// we can use canvas as-is as it already has a context, so we do a silly one more canvas
const tempCanvas = (typeof OffscreenCanvas !== 'undefined') ? new OffscreenCanvas(targetWidth, targetHeight) : document.createElement('canvas');
tempCanvas.width = targetWidth;
tempCanvas.height = targetHeight;