fix camera restart on resize

pull/293/head
Vladimir Mandic 2020-11-14 07:02:05 -05:00
parent 5777b86748
commit b5aac6e016
9 changed files with 16 additions and 16 deletions

View File

@ -28,10 +28,9 @@
- [**Notes on Backends**](https://github.com/vladmandic/human/wiki/Backends) - [**Notes on Backends**](https://github.com/vladmandic/human/wiki/Backends)
- [**Development Server**](https://github.com/vladmandic/human/wiki/Development-Server) - [**Development Server**](https://github.com/vladmandic/human/wiki/Development-Server)
- [**Build Process**](https://github.com/vladmandic/human/wiki/Build-Process) - [**Build Process**](https://github.com/vladmandic/human/wiki/Build-Process)
- [**List of Models**](https://github.com/vladmandic/human/wiki/Models)
- [**Performance Notes**](https://github.com/vladmandic/human/wiki/Performance) - [**Performance Notes**](https://github.com/vladmandic/human/wiki/Performance)
- [**Performance Profiling**](https://github.com/vladmandic/human/wiki/Profiling) - [**Performance Profiling**](https://github.com/vladmandic/human/wiki/Profiling)
- [**Credits**](https://github.com/vladmandic/human/wiki/Credits) - [**List of Models && Credits**](https://github.com/vladmandic/human/wiki/Models)
<br> <br>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 126 KiB

After

Width:  |  Height:  |  Size: 42 KiB

View File

@ -39,6 +39,7 @@ const ui = {
buffered: false, buffered: false,
bufferedFPSTarget: 24, bufferedFPSTarget: 24,
drawThread: null, drawThread: null,
detectThread: null,
framesDraw: 0, framesDraw: 0,
framesDetect: 0, framesDetect: 0,
bench: false, bench: false,
@ -155,6 +156,7 @@ async function setupCamera() {
const canvas = document.getElementById('canvas'); const canvas = document.getElementById('canvas');
const output = document.getElementById('log'); const output = document.getElementById('log');
const live = video.srcObject ? ((video.srcObject.getVideoTracks()[0].readyState === 'live') && (video.readyState > 2) && (!video.paused)) : false; const live = video.srcObject ? ((video.srcObject.getVideoTracks()[0].readyState === 'live') && (video.readyState > 2) && (!video.paused)) : false;
console.log('camera live', live);
let msg = ''; let msg = '';
status('setting up camera'); status('setting up camera');
// setup webcam. note that navigator.mediaDevices requires that page is accessed via https // setup webcam. note that navigator.mediaDevices requires that page is accessed via https
@ -206,7 +208,10 @@ async function setupCamera() {
// silly font resizing for paint-on-canvas since viewport can be zoomed // silly font resizing for paint-on-canvas since viewport can be zoomed
const size = 14 + (6 * canvas.width / window.innerWidth); const size = 14 + (6 * canvas.width / window.innerWidth);
ui.baseFont = ui.baseFontProto.replace(/{size}/, `${size}px`); ui.baseFont = ui.baseFontProto.replace(/{size}/, `${size}px`);
console.log('camera continue', live);
if (live) video.play(); if (live) video.play();
// eslint-disable-next-line no-use-before-define
if (live && !ui.detectThread) runHumanDetect(video, canvas);
ui.busy = false; ui.busy = false;
// 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();
@ -230,7 +235,7 @@ function webWorker(input, image, canvas, timestamp) {
ui.framesDetect++; ui.framesDetect++;
if (!ui.drawThread) drawResults(input); if (!ui.drawThread) drawResults(input);
// eslint-disable-next-line no-use-before-define // eslint-disable-next-line no-use-before-define
requestAnimationFrame((now) => runHumanDetect(input, canvas, now)); ui.detectThread = requestAnimationFrame((now) => runHumanDetect(input, canvas, now));
}); });
} }
// pass image data as arraybuffer to worker by reference to avoid copy // pass image data as arraybuffer to worker by reference to avoid copy
@ -245,7 +250,9 @@ function runHumanDetect(input, canvas, timestamp) {
if (!live && input.srcObject) { if (!live && input.srcObject) {
// stop ui refresh // stop ui refresh
if (ui.drawThread) clearTimeout(ui.drawThread); if (ui.drawThread) clearTimeout(ui.drawThread);
if (ui.detectThread) cancelAnimationFrame(ui.detectThread);
ui.drawThread = null; ui.drawThread = null;
ui.detectThread = null;
// if we want to continue and camera not ready, retry in 0.5sec, else just give up // if we want to continue and camera not ready, retry in 0.5sec, else just give up
if (input.paused) log('camera paused'); if (input.paused) log('camera paused');
else if ((input.srcObject.getVideoTracks()[0].readyState === 'live') && (input.readyState <= 2)) setTimeout(() => runHumanDetect(input, canvas), 500); else if ((input.srcObject.getVideoTracks()[0].readyState === 'live') && (input.readyState <= 2)) setTimeout(() => runHumanDetect(input, canvas), 500);
@ -274,7 +281,7 @@ function runHumanDetect(input, canvas, timestamp) {
lastDetectedResult = result; lastDetectedResult = result;
if (!ui.drawThread) drawResults(input); if (!ui.drawThread) drawResults(input);
ui.framesDetect++; ui.framesDetect++;
requestAnimationFrame((now) => runHumanDetect(input, canvas, now)); ui.detectThread = requestAnimationFrame((now) => runHumanDetect(input, canvas, now));
} }
}); });
} }
@ -326,7 +333,7 @@ async function detectVideo() {
status(''); status('');
video.play(); video.play();
} }
runHumanDetect(video, canvas); if (!ui.detectThread) runHumanDetect(video, canvas);
} }
// just initialize everything and call main function // just initialize everything and call main function

View File

@ -16,7 +16,7 @@ async function load(config) {
async function predict(image, config) { async function predict(image, config) {
if (!models.age) return null; if (!models.age) return null;
if ((frame < config.face.age.skipFrames) && last.age && (last.age > 0)) { if ((frame < config.face.age.skipFrames) && config.videoOptimized && last.age && (last.age > 0)) {
frame += 1; frame += 1;
return last; return last;
} }

View File

@ -21,7 +21,7 @@ async function load(config) {
async function predict(image, config) { async function predict(image, config) {
if (!models.emotion) return null; if (!models.emotion) return null;
if ((frame < config.face.emotion.skipFrames) && (last.length > 0)) { if ((frame < config.face.emotion.skipFrames) && config.videoOptimized && (last.length > 0)) {
frame += 1; frame += 1;
return last; return last;
} }

View File

@ -21,7 +21,7 @@ async function load(config) {
async function predict(image, config) { async function predict(image, config) {
if (!models.gender) return null; if (!models.gender) return null;
if ((frame < config.face.gender.skipFrames) && last.gender !== '') { if ((frame < config.face.gender.skipFrames) && config.videoOptimized && last.gender !== '') {
frame += 1; frame += 1;
return last; return last;
} }

View File

@ -89,7 +89,7 @@ class HandPipeline {
// run new detector every skipFrames unless we only want box to start with // run new detector every skipFrames unless we only want box to start with
let boxes; let boxes;
if ((this.skipped > config.skipFrames) || !config.landmarks) { if ((this.skipped > config.skipFrames) || !config.landmarks || !config.videoOptimized) {
boxes = await this.boxDetector.estimateHandBounds(image, config); boxes = await this.boxDetector.estimateHandBounds(image, config);
// don't reset on test image // don't reset on test image
if ((image.shape[1] !== 255) && (image.shape[2] !== 255)) this.skipped = 0; if ((image.shape[1] !== 255) && (image.shape[2] !== 255)) this.skipped = 0;

View File

@ -12,11 +12,6 @@ import * as profile from './profile.js';
import * as config from '../config.js'; import * as config from '../config.js';
import * as app from '../package.json'; import * as app from '../package.json';
// static config override for non-video detection
const disableSkipFrames = {
face: { detector: { skipFrames: 0 }, age: { skipFrames: 0 }, gender: { skipFrames: 0 }, emotion: { skipFrames: 0 } }, hand: { skipFrames: 0 },
};
// helper function: gets elapsed time on both browser and nodejs // helper function: gets elapsed time on both browser and nodejs
const now = () => { const now = () => {
if (typeof performance !== 'undefined') return performance.now(); if (typeof performance !== 'undefined') return performance.now();
@ -327,7 +322,6 @@ class Human {
// update configuration // update configuration
this.config = mergeDeep(this.config, userConfig); this.config = mergeDeep(this.config, userConfig);
if (!this.config.videoOptimized) this.config = mergeDeep(this.config, disableSkipFrames);
// sanity checks // sanity checks
this.state = 'check'; this.state = 'check';

2
wiki

@ -1 +1 @@
Subproject commit e29ef0887f0be593ef827ee5020fe6a40f588f38 Subproject commit 79cd119c0c5714324a0dae82477ce36e1d5f40a1