optimized camera and mobile layout

pull/50/head
Vladimir Mandic 2020-11-05 09:06:09 -05:00
parent 8d91c9237d
commit b669277223
6 changed files with 56 additions and 47 deletions

View File

@ -135,7 +135,7 @@ function drawResults(input, result, canvas) {
const avg = Math.trunc(10 * fps.reduce((a, b) => a + b) / fps.length) / 10;
document.getElementById('log').innerText = `
video: ${camera.name} | facing: ${camera.facing} | resolution: ${camera.width} x ${camera.height} ${processing}
backend: ${human.tf.getBackend()} | ${memory} | object size: ${(str(result)).length.toLocaleString()} bytes
backend: ${human.tf.getBackend()} | ${memory}
performance: ${str(result.performance)} FPS:${avg}
`;
}
@ -159,26 +159,27 @@ async function setupCamera() {
return null;
}
let stream;
const constraints = {
audio: false,
video: { facingMode: (ui.facing ? 'user' : 'environment'), resizeMode: 'none' },
};
try {
stream = await navigator.mediaDevices.getUserMedia({
audio: false,
video: {
facingMode: (ui.facing ? 'user' : 'environment'),
width: window.innerWidth,
height: window.innerHeight,
resizeMode: 'none',
contrast: 75,
},
});
if (window.innerWidth > window.innerHeight) constraints.video.width = { ideal: window.innerWidth };
else constraints.video.height = { ideal: window.innerHeight };
stream = await navigator.mediaDevices.getUserMedia(constraints);
} catch (err) {
output.innerText += '\nCamera permission denied';
status('camera permission denied');
if (err.name === 'PermissionDeniedError') msg = 'camera permission denied';
else if (err.name === 'SourceUnavailableError') msg = 'camera not available';
else msg = 'camera error';
output.innerText += `\n${msg}`;
status(msg);
log(err);
}
if (stream) video.srcObject = stream;
else return null;
const track = stream.getVideoTracks()[0];
const settings = track.getSettings();
log('camera constraints:', constraints, 'window:', { width: window.innerWidth, height: window.innerHeight });
log('camera settings:', settings);
log('camera track:', track);
camera = { name: track.label, width: settings.width, height: settings.height, facing: settings.facingMode === 'user' ? 'front' : 'back' };
@ -402,11 +403,11 @@ async function main() {
setupMenu();
document.getElementById('log').innerText = `Human: version ${human.version} TensorFlow/JS: version ${human.tf.version_core}`;
// this is not required, just pre-warms the library
if (!ui.modelsPreload) {
if (ui.modelsPreload) {
status('loading');
await human.load();
}
if (!ui.modelsWarmup) {
if (ui.modelsWarmup) {
status('initializing');
const warmup = new ImageData(50, 50);
await human.detect(warmup);

View File

@ -6,7 +6,7 @@
<meta content="text/html">
<meta charset="UTF-8">
<meta name="description" content="3D Face Detection, Body Pose, Hand & Finger Tracking, Iris Tracking, Age & Gender Prediction & Emotion Prediction; Author: Vladimir Mandic <mandic00@live.com>">
<meta name="viewport" content="width=device-width, initial-scale=0.5, minimum-scale=0.1, maximum-scale=4.0, shrink-to-fit=yes, user-scalable=yes">
<meta name="viewport" content="width=device-width, initial-scale=0.6, minimum-scale=0.1, maximum-scale=4.0, shrink-to-fit=yes, user-scalable=yes">
<meta name="theme-color" content="#000000"/>
<meta name="application-name" content="Human">
<meta name="msapplication-tooltip" content="Human: AI-powered 3D Human Detection">
@ -22,20 +22,21 @@
<!-- alternatively load demo sources directly -->
<!-- <script src="browser.js" type="module"></script> -->
<style>
body { margin: 0; background: black; color: white; font-family: 'Segoe UI'; font-size: 16px; font-variant: small-caps; overflow-x: hidden; scrollbar-width: none; }
html { font-family: 'Segoe UI'; font-size: 16px; font-variant: small-caps; }
body { margin: 0; background: black; color: white; overflow-x: hidden; scrollbar-width: none; }
body::-webkit-scrollbar { display: none; }
.play { position: absolute; width: 300px; height: 300px; z-index: 25; top: 30%; left: 50%; margin-left: -150px; display: none; }
.play { position: absolute; width: 300px; height: 300px; z-index: 9; top: 30%; left: 50%; margin-left: -150px; display: none; }
.play-background { fill:darkslategray; cursor:pointer; opacity: 0.6; }
.play-foreground { fill:white; cursor:pointer; opacity: 0.8; }
.play-foreground:hover { opacity: 1; }
.status { position: absolute; width: 100vw; top: 100px; text-align: center; font-size: 4rem; font-weight: 100; text-shadow: 2px 2px darkslategrey; }
.status { position: absolute; width: 100vw; bottom: 15%; 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: fixed; bottom: 0; margin: 0.4rem; }
.log { position: fixed; bottom: 0; margin: 0.4rem; font-size: 0.9rem; }
.samples-container { display: flex; flex-wrap: wrap; }
.video { display: none; }
.canvas { margin: 0 auto; width: 100%; }
.loader { width: 300px; height: 300px; border: 3px solid transparent; border-radius: 50%; border-top: 4px solid #f15e41; animation: spin 4s linear infinite; position: absolute; top: 30%; left: 50%; margin-left: -150px; }
.canvas { margin: 0 auto; height: 100%; }
.loader { width: 300px; height: 300px; border: 3px solid transparent; border-radius: 50%; border-top: 4px solid #f15e41; animation: spin 4s linear infinite; position: absolute; top: 30%; left: 50%; margin-left: -150px; z-index: 15; }
.loader::before, .loader::after { content: ""; position: absolute; top: 6px; bottom: 6px; left: 6px; right: 6px; border-radius: 50%; border: 4px solid transparent; }
.loader::before { border-top-color: #bad375; animation: 3s spin linear infinite; }
.loader::after { border-top-color: #26a9e0; animation: spin 1.5s linear infinite; }

View File

@ -18,7 +18,7 @@ let theme = {
function createCSS() {
if (CSScreated) return;
const css = `
.menu { position: fixed; top: 0rem; right: 0; width: fit-content; padding: 0 0.8rem 0 0.8rem; line-height: 1.8rem; z-index: 10; max-height: calc(100% - 4rem);
.menu { position: absolute; top: 0rem; right: 0; width: fit-content; padding: 0 0.8rem 0 0.8rem; line-height: 1.8rem; z-index: 10; max-height: calc(100% - 4rem);
box-shadow: 0 0 8px dimgrey; background: ${theme.background}; border-radius: 1rem; border-color: black; border-style: solid; border-width: thin; }
.menu:hover { box-shadow: 0 0 8px ${theme.hover}; }

View File

@ -33646,7 +33646,7 @@ function createCSS() {
if (CSScreated)
return;
const css = `
.menu { position: fixed; top: 0rem; right: 0; width: fit-content; padding: 0 0.8rem 0 0.8rem; line-height: 1.8rem; z-index: 10; max-height: calc(100% - 4rem);
.menu { position: absolute; top: 0rem; right: 0; width: fit-content; padding: 0 0.8rem 0 0.8rem; line-height: 1.8rem; z-index: 10; max-height: calc(100% - 4rem);
box-shadow: 0 0 8px dimgrey; background: ${theme.background}; border-radius: 1rem; border-color: black; border-style: solid; border-width: thin; }
.menu:hover { box-shadow: 0 0 8px ${theme.hover}; }
@ -34040,7 +34040,7 @@ function drawResults(input, result, canvas) {
const avg = Math.trunc(10 * fps.reduce((a, b) => a + b) / fps.length) / 10;
document.getElementById("log").innerText = `
video: ${camera.name} | facing: ${camera.facing} | resolution: ${camera.width} x ${camera.height} ${processing}
backend: ${human.tf.getBackend()} | ${memory} | object size: ${str(result).length.toLocaleString()} bytes
backend: ${human.tf.getBackend()} | ${memory}
performance: ${str(result.performance)} FPS:${avg}
`;
}
@ -34063,20 +34063,26 @@ ${msg}`;
return null;
}
let stream;
const constraints = {
audio: false,
video: {facingMode: ui.facing ? "user" : "environment", resizeMode: "none"}
};
try {
stream = await navigator.mediaDevices.getUserMedia({
audio: false,
video: {
facingMode: ui.facing ? "user" : "environment",
width: window.innerWidth,
height: window.innerHeight,
resizeMode: "none",
contrast: 75
}
});
if (window.innerWidth > window.innerHeight)
constraints.video.width = {ideal: window.innerWidth};
else
constraints.video.height = {ideal: window.innerHeight};
stream = await navigator.mediaDevices.getUserMedia(constraints);
} catch (err) {
output.innerText += "\nCamera permission denied";
status("camera permission denied");
if (err.name === "PermissionDeniedError")
msg = "camera permission denied";
else if (err.name === "SourceUnavailableError")
msg = "camera not available";
else
msg = "camera error";
output.innerText += `
${msg}`;
status(msg);
log(err);
}
if (stream)
@ -34085,6 +34091,7 @@ ${msg}`;
return null;
const track = stream.getVideoTracks()[0];
const settings = track.getSettings();
log("camera constraints:", constraints, "window:", {width: window.innerWidth, height: window.innerHeight});
log("camera settings:", settings);
log("camera track:", track);
camera = {name: track.label, width: settings.width, height: settings.height, facing: settings.facingMode === "user" ? "front" : "back"};
@ -34287,11 +34294,11 @@ async function main() {
log("Human: demo starting ...");
setupMenu();
document.getElementById("log").innerText = `Human: version ${human.version} TensorFlow/JS: version ${human.tf.version_core}`;
if (!ui.modelsPreload) {
if (ui.modelsPreload) {
status("loading");
await human.load();
}
if (!ui.modelsWarmup) {
if (ui.modelsWarmup) {
status("initializing");
const warmup = new ImageData(50, 50);
await human.detect(warmup);

File diff suppressed because one or more lines are too long

View File

@ -1,7 +1,7 @@
{
"inputs": {
"demo/browser.js": {
"bytes": 17419,
"bytes": 17704,
"imports": [
{
"path": "dist/human.esm.js"
@ -19,7 +19,7 @@
"imports": []
},
"demo/menu.js": {
"bytes": 12354,
"bytes": 12357,
"imports": []
},
"dist/human.esm.js": {
@ -31,7 +31,7 @@
"dist/demo-browser-index.js.map": {
"imports": [],
"inputs": {},
"bytes": 5520028
"bytes": 5520480
},
"dist/demo-browser-index.js": {
"imports": [],
@ -46,13 +46,13 @@
"bytesInOutput": 7389
},
"demo/menu.js": {
"bytesInOutput": 12356
"bytesInOutput": 12359
},
"demo/browser.js": {
"bytesInOutput": 15580
"bytesInOutput": 15889
}
},
"bytes": 1704669
"bytes": 1704981
}
}
}