camera exception handling

pull/50/head
Vladimir Mandic 2020-11-20 07:52:50 -05:00
parent 12ab61bb0a
commit e537a7dce7
21 changed files with 109 additions and 86 deletions

View File

@ -134,10 +134,10 @@ async function drawResults(input) {
const avgDetect = Math.trunc(10 * ui.detectFPS.reduce((a, b) => a + b, 0) / ui.detectFPS.length) / 10; const avgDetect = Math.trunc(10 * ui.detectFPS.reduce((a, b) => a + b, 0) / ui.detectFPS.length) / 10;
const avgDraw = Math.trunc(10 * ui.drawFPS.reduce((a, b) => a + b, 0) / ui.drawFPS.length) / 10; const avgDraw = Math.trunc(10 * ui.drawFPS.reduce((a, b) => a + b, 0) / ui.drawFPS.length) / 10;
const warning = (ui.detectFPS.length > 5) && (avgDetect < 5) ? '<font color="lightcoral">warning: your performance is low: try switching to higher performance backend, lowering resolution or disabling some models</font>' : ''; const warning = (ui.detectFPS.length > 5) && (avgDetect < 5) ? '<font color="lightcoral">warning: your performance is low: try switching to higher performance backend, lowering resolution or disabling some models</font>' : '';
document.getElementById('log').innerHTML = ` document.getElementById('log').innerText = `
video: ${ui.camera.name} | facing: ${ui.camera.facing} | screen: ${window.innerWidth} x ${window.innerHeight} camera: ${ui.camera.width} x ${ui.camera.height} ${processing}<br> video: ${ui.camera.name} | facing: ${ui.camera.facing} | screen: ${window.innerWidth} x ${window.innerHeight} camera: ${ui.camera.width} x ${ui.camera.height} ${processing}
backend: ${human.tf.getBackend()} | ${memory}<br> backend: ${human.tf.getBackend()} | ${memory}
performance: ${str(result.performance)} FPS process:${avgDetect} refresh:${avgDraw}<br> performance: ${str(result.performance)}ms FPS process:${avgDetect} refresh:${avgDraw}
${warning} ${warning}
`; `;
@ -169,7 +169,8 @@ async function setupCamera() {
output.innerText += `\n${msg}`; output.innerText += `\n${msg}`;
log(msg); log(msg);
status(msg); status(msg);
return null; ui.busy = false;
return msg;
} }
let stream; let stream;
const constraints = { const constraints = {
@ -181,15 +182,20 @@ async function setupCamera() {
try { try {
stream = await navigator.mediaDevices.getUserMedia(constraints); stream = await navigator.mediaDevices.getUserMedia(constraints);
} catch (err) { } catch (err) {
if (err.name === 'PermissionDeniedError') msg = 'camera permission denied'; if (err.name === 'PermissionDeniedError' || err.name === 'NotAllowedError') msg = 'camera permission denied';
else if (err.name === 'SourceUnavailableError') msg = 'camera not available'; else if (err.name === 'SourceUnavailableError') msg = 'camera not available';
else msg = 'camera error'; else msg = `camera error: ${err.message || err}`;
output.innerText += `\n${msg}`; output.innerText += `\n${msg}`;
status(msg); status(msg);
log(err); log('camera error:', err);
ui.busy = false;
return msg;
} }
if (stream) video.srcObject = stream; if (stream) video.srcObject = stream;
else return null; else {
ui.busy = false;
return 'camera stream empty';
}
const track = stream.getVideoTracks()[0]; const track = stream.getVideoTracks()[0];
const settings = track.getSettings(); const settings = track.getSettings();
// log('camera constraints:', constraints, 'window:', { width: window.innerWidth, height: window.innerHeight }, 'settings:', settings, 'track:', track); // log('camera constraints:', constraints, 'window:', { width: window.innerWidth, height: window.innerHeight }, 'settings:', settings, 'track:', track);
@ -215,7 +221,7 @@ async function setupCamera() {
// do once more because onresize events can be delayed or skipped // do once more because onresize events can be delayed or skipped
// if (video.width > window.innerWidth) await setupCamera(); // if (video.width > window.innerWidth) await setupCamera();
status(''); status('');
resolve(video); resolve();
}; };
}); });
} }
@ -299,8 +305,10 @@ function runHumanDetect(input, canvas, timestamp) {
bench.nextFrame(timestamp); bench.nextFrame(timestamp);
} }
if (document.getElementById('gl-bench')) document.getElementById('gl-bench').style.display = ui.bench ? 'block' : 'none'; if (document.getElementById('gl-bench')) document.getElementById('gl-bench').style.display = ui.bench ? 'block' : 'none';
if (result.error) log(result.error); if (result.error) {
else { log(result.error);
document.getElementById('log').innerText += `\nHuman error: ${result.error}`;
} else {
lastDetectedResult = result; lastDetectedResult = result;
if (!ui.drawThread) drawResults(input); if (!ui.drawThread) drawResults(input);
ui.framesDetect++; ui.framesDetect++;
@ -352,15 +360,19 @@ async function detectVideo() {
status('paused'); status('paused');
video.pause(); video.pause();
} else { } else {
await setupCamera(); const cameraError = await setupCamera();
document.getElementById('play').style.display = 'none'; if (!cameraError) {
for (const m of Object.values(menu)) m.hide(); document.getElementById('play').style.display = 'none';
status(''); for (const m of Object.values(menu)) m.hide();
document.getElementById('btnStart').className = 'button button-stop'; status('');
document.getElementById('btnStart').innerHTML = 'pause<br>video'; document.getElementById('btnStart').className = 'button button-stop';
video.play(); document.getElementById('btnStart').innerHTML = 'pause<br>video';
await video.play();
if (!ui.detectThread) runHumanDetect(video, canvas);
} else {
status(cameraError);
}
} }
if (!ui.detectThread) runHumanDetect(video, canvas);
} }
// just initialize everything and call main function // just initialize everything and call main function

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,7 +1,7 @@
{ {
"inputs": { "inputs": {
"demo/browser.js": { "demo/browser.js": {
"bytes": 24811, "bytes": 25185,
"imports": [ "imports": [
{ {
"path": "dist/human.esm.js" "path": "dist/human.esm.js"
@ -30,7 +30,7 @@
"imports": [] "imports": []
}, },
"dist/human.esm.js": { "dist/human.esm.js": {
"bytes": 1783426, "bytes": 1783650,
"imports": [] "imports": []
} }
}, },
@ -38,14 +38,14 @@
"dist/demo-browser-index.js.map": { "dist/demo-browser-index.js.map": {
"imports": [], "imports": [],
"inputs": {}, "inputs": {},
"bytes": 2675999 "bytes": 2677420
}, },
"dist/demo-browser-index.js": { "dist/demo-browser-index.js": {
"imports": [], "imports": [],
"exports": [], "exports": [],
"inputs": { "inputs": {
"dist/human.esm.js": { "dist/human.esm.js": {
"bytesInOutput": 1776302 "bytesInOutput": 1776526
}, },
"demo/draw.js": { "demo/draw.js": {
"bytesInOutput": 7668 "bytesInOutput": 7668
@ -57,10 +57,10 @@
"bytesInOutput": 7436 "bytesInOutput": 7436
}, },
"demo/browser.js": { "demo/browser.js": {
"bytesInOutput": 19152 "bytesInOutput": 19406
} }
}, },
"bytes": 1829661 "bytes": 1830139
} }
} }
} }

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -290,7 +290,7 @@
"imports": [] "imports": []
}, },
"src/human.js": { "src/human.js": {
"bytes": 15657, "bytes": 15842,
"imports": [ "imports": [
{ {
"path": "dist/tfjs.esm.js" "path": "dist/tfjs.esm.js"
@ -334,7 +334,7 @@
] ]
}, },
"src/image.js": { "src/image.js": {
"bytes": 5701, "bytes": 5862,
"imports": [ "imports": [
{ {
"path": "dist/tfjs.esm.js" "path": "dist/tfjs.esm.js"
@ -357,7 +357,7 @@
"dist/human.esm-nobundle.js.map": { "dist/human.esm-nobundle.js.map": {
"imports": [], "imports": [],
"inputs": {}, "inputs": {},
"bytes": 2581163 "bytes": 2582027
}, },
"dist/human.esm-nobundle.js": { "dist/human.esm-nobundle.js": {
"imports": [], "imports": [],
@ -450,13 +450,13 @@
"bytesInOutput": 13638 "bytesInOutput": 13638
}, },
"src/image.js": { "src/image.js": {
"bytesInOutput": 3993 "bytesInOutput": 4079
}, },
"dist/tfjs.esm.js": { "dist/tfjs.esm.js": {
"bytesInOutput": 1529550 "bytesInOutput": 1529550
}, },
"src/human.js": { "src/human.js": {
"bytesInOutput": 10345 "bytesInOutput": 10483
}, },
"src/hand/box.js": { "src/hand/box.js": {
"bytesInOutput": 1880 "bytesInOutput": 1880
@ -471,7 +471,7 @@
"bytesInOutput": 21 "bytesInOutput": 21
} }
}, },
"bytes": 1783435 "bytes": 1783659
} }
} }
} }

4
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

12
dist/human.esm.json vendored
View File

@ -290,7 +290,7 @@
"imports": [] "imports": []
}, },
"src/human.js": { "src/human.js": {
"bytes": 15657, "bytes": 15842,
"imports": [ "imports": [
{ {
"path": "dist/tfjs.esm.js" "path": "dist/tfjs.esm.js"
@ -334,7 +334,7 @@
] ]
}, },
"src/image.js": { "src/image.js": {
"bytes": 5701, "bytes": 5862,
"imports": [ "imports": [
{ {
"path": "dist/tfjs.esm.js" "path": "dist/tfjs.esm.js"
@ -357,7 +357,7 @@
"dist/human.esm.js.map": { "dist/human.esm.js.map": {
"imports": [], "imports": [],
"inputs": {}, "inputs": {},
"bytes": 2581163 "bytes": 2582027
}, },
"dist/human.esm.js": { "dist/human.esm.js": {
"imports": [], "imports": [],
@ -450,13 +450,13 @@
"bytesInOutput": 13638 "bytesInOutput": 13638
}, },
"src/image.js": { "src/image.js": {
"bytesInOutput": 3993 "bytesInOutput": 4079
}, },
"dist/tfjs.esm.js": { "dist/tfjs.esm.js": {
"bytesInOutput": 1529550 "bytesInOutput": 1529550
}, },
"src/human.js": { "src/human.js": {
"bytesInOutput": 10345 "bytesInOutput": 10483
}, },
"src/hand/box.js": { "src/hand/box.js": {
"bytesInOutput": 1880 "bytesInOutput": 1880
@ -471,7 +471,7 @@
"bytesInOutput": 21 "bytesInOutput": 21
} }
}, },
"bytes": 1783426 "bytes": 1783650
} }
} }
} }

4
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

12
dist/human.json vendored
View File

@ -290,7 +290,7 @@
"imports": [] "imports": []
}, },
"src/human.js": { "src/human.js": {
"bytes": 15657, "bytes": 15842,
"imports": [ "imports": [
{ {
"path": "dist/tfjs.esm.js" "path": "dist/tfjs.esm.js"
@ -334,7 +334,7 @@
] ]
}, },
"src/image.js": { "src/image.js": {
"bytes": 5701, "bytes": 5862,
"imports": [ "imports": [
{ {
"path": "dist/tfjs.esm.js" "path": "dist/tfjs.esm.js"
@ -357,7 +357,7 @@
"dist/human.js.map": { "dist/human.js.map": {
"imports": [], "imports": [],
"inputs": {}, "inputs": {},
"bytes": 2548927 "bytes": 2549411
}, },
"dist/human.js": { "dist/human.js": {
"imports": [], "imports": [],
@ -448,10 +448,10 @@
"bytesInOutput": 13638 "bytesInOutput": 13638
}, },
"src/image.js": { "src/image.js": {
"bytesInOutput": 3958 "bytesInOutput": 4044
}, },
"src/human.js": { "src/human.js": {
"bytesInOutput": 10409 "bytesInOutput": 10547
}, },
"dist/tfjs.esm.js": { "dist/tfjs.esm.js": {
"bytesInOutput": 1529041 "bytesInOutput": 1529041
@ -469,7 +469,7 @@
"bytesInOutput": 21 "bytesInOutput": 21
} }
}, },
"bytes": 1782737 "bytes": 1782961
} }
} }
} }

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -290,7 +290,7 @@
"imports": [] "imports": []
}, },
"src/human.js": { "src/human.js": {
"bytes": 15657, "bytes": 15842,
"imports": [ "imports": [
{ {
"path": "dist/tfjs.esm.js" "path": "dist/tfjs.esm.js"
@ -334,7 +334,7 @@
] ]
}, },
"src/image.js": { "src/image.js": {
"bytes": 5701, "bytes": 5862,
"imports": [ "imports": [
{ {
"path": "dist/tfjs.esm.js" "path": "dist/tfjs.esm.js"
@ -357,7 +357,7 @@
"dist/human.node-nobundle.js.map": { "dist/human.node-nobundle.js.map": {
"imports": [], "imports": [],
"inputs": {}, "inputs": {},
"bytes": 2597270 "bytes": 2598324
}, },
"dist/human.node-nobundle.js": { "dist/human.node-nobundle.js": {
"imports": [], "imports": [],
@ -448,10 +448,10 @@
"bytesInOutput": 13640 "bytesInOutput": 13640
}, },
"src/image.js": { "src/image.js": {
"bytesInOutput": 3995 "bytesInOutput": 4081
}, },
"src/human.js": { "src/human.js": {
"bytesInOutput": 10383 "bytesInOutput": 10521
}, },
"dist/tfjs.esm.js": { "dist/tfjs.esm.js": {
"bytesInOutput": 1529722 "bytesInOutput": 1529722
@ -469,7 +469,7 @@
"bytesInOutput": 21 "bytesInOutput": 21
} }
}, },
"bytes": 1783767 "bytes": 1783991
} }
} }
} }

4
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

12
dist/human.node.json vendored
View File

@ -290,7 +290,7 @@
"imports": [] "imports": []
}, },
"src/human.js": { "src/human.js": {
"bytes": 15657, "bytes": 15842,
"imports": [ "imports": [
{ {
"path": "dist/tfjs.esm.js" "path": "dist/tfjs.esm.js"
@ -334,7 +334,7 @@
] ]
}, },
"src/image.js": { "src/image.js": {
"bytes": 5701, "bytes": 5862,
"imports": [ "imports": [
{ {
"path": "dist/tfjs.esm.js" "path": "dist/tfjs.esm.js"
@ -357,7 +357,7 @@
"dist/human.node.js.map": { "dist/human.node.js.map": {
"imports": [], "imports": [],
"inputs": {}, "inputs": {},
"bytes": 2597270 "bytes": 2598324
}, },
"dist/human.node.js": { "dist/human.node.js": {
"imports": [], "imports": [],
@ -448,10 +448,10 @@
"bytesInOutput": 13640 "bytesInOutput": 13640
}, },
"src/image.js": { "src/image.js": {
"bytesInOutput": 3995 "bytesInOutput": 4081
}, },
"src/human.js": { "src/human.js": {
"bytesInOutput": 10383 "bytesInOutput": 10521
}, },
"dist/tfjs.esm.js": { "dist/tfjs.esm.js": {
"bytesInOutput": 1529722 "bytesInOutput": 1529722
@ -469,7 +469,7 @@
"bytesInOutput": 21 "bytesInOutput": 21
} }
}, },
"bytes": 1783758 "bytes": 1783982
} }
} }
} }

View File

@ -348,6 +348,11 @@ class Human {
timeStamp = now(); timeStamp = now();
const process = image.process(input, this.config); const process = image.process(input, this.config);
if (!process || !process.tensor) {
this.log('could not convert input to tensor');
resolve({ error: 'could not convert input to tensor' });
return;
}
this.perf.image = Math.trunc(now() - timeStamp); this.perf.image = Math.trunc(now() - timeStamp);
this.analyze('Get Image:'); this.analyze('Get Image:');

View File

@ -21,6 +21,11 @@ function process(input, config) {
else if (config.filter.height > 0) targetWidth = originalWidth * (config.filter.height / originalHeight); else if (config.filter.height > 0) targetWidth = originalWidth * (config.filter.height / originalHeight);
if (config.filter.height > 0) targetHeight = config.filter.height; if (config.filter.height > 0) targetHeight = config.filter.height;
else if (config.filter.width > 0) targetHeight = originalHeight * (config.filter.width / originalWidth); else if (config.filter.width > 0) targetHeight = originalHeight * (config.filter.width / originalWidth);
if (!targetWidth || !targetHeight) {
// eslint-disable-next-line no-console
console.log('Human: invalid input', input);
return null;
}
if (!inCanvas || (inCanvas.width !== targetWidth) || (inCanvas.height !== targetHeight)) { if (!inCanvas || (inCanvas.width !== targetWidth) || (inCanvas.height !== targetHeight)) {
inCanvas = (typeof OffscreenCanvas !== 'undefined') ? new OffscreenCanvas(targetWidth, targetHeight) : document.createElement('canvas'); inCanvas = (typeof OffscreenCanvas !== 'undefined') ? new OffscreenCanvas(targetWidth, targetHeight) : document.createElement('canvas');
if (inCanvas.width !== targetWidth) inCanvas.width = targetWidth; if (inCanvas.width !== targetWidth) inCanvas.width = targetWidth;