camera exception handling

pull/280/head
Vladimir Mandic 2020-11-20 07:52:50 -05:00
parent 05042392be
commit a84c26c781
3 changed files with 42 additions and 20 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

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;