diff --git a/README.md b/README.md index 1c8c4b5c..cacbe75f 100644 --- a/README.md +++ b/README.md @@ -28,10 +28,9 @@ - [**Notes on Backends**](https://github.com/vladmandic/human/wiki/Backends) - [**Development Server**](https://github.com/vladmandic/human/wiki/Development-Server) - [**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 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)
diff --git a/assets/screenshot-menu.png b/assets/screenshot-menu.png index a2a4d983..817cfec5 100644 Binary files a/assets/screenshot-menu.png and b/assets/screenshot-menu.png differ diff --git a/demo/browser.js b/demo/browser.js index 5b821f8d..5170f69e 100644 --- a/demo/browser.js +++ b/demo/browser.js @@ -39,6 +39,7 @@ const ui = { buffered: false, bufferedFPSTarget: 24, drawThread: null, + detectThread: null, framesDraw: 0, framesDetect: 0, bench: false, @@ -155,6 +156,7 @@ async function setupCamera() { const canvas = document.getElementById('canvas'); const output = document.getElementById('log'); const live = video.srcObject ? ((video.srcObject.getVideoTracks()[0].readyState === 'live') && (video.readyState > 2) && (!video.paused)) : false; + console.log('camera live', live); let msg = ''; status('setting up camera'); // 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 const size = 14 + (6 * canvas.width / window.innerWidth); ui.baseFont = ui.baseFontProto.replace(/{size}/, `${size}px`); + console.log('camera continue', live); if (live) video.play(); + // eslint-disable-next-line no-use-before-define + if (live && !ui.detectThread) runHumanDetect(video, canvas); ui.busy = false; // do once more because onresize events can be delayed or skipped // if (video.width > window.innerWidth) await setupCamera(); @@ -230,7 +235,7 @@ function webWorker(input, image, canvas, timestamp) { ui.framesDetect++; if (!ui.drawThread) drawResults(input); // 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 @@ -245,7 +250,9 @@ function runHumanDetect(input, canvas, timestamp) { if (!live && input.srcObject) { // stop ui refresh if (ui.drawThread) clearTimeout(ui.drawThread); + if (ui.detectThread) cancelAnimationFrame(ui.detectThread); ui.drawThread = null; + ui.detectThread = null; // if we want to continue and camera not ready, retry in 0.5sec, else just give up if (input.paused) log('camera paused'); 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; if (!ui.drawThread) drawResults(input); ui.framesDetect++; - requestAnimationFrame((now) => runHumanDetect(input, canvas, now)); + ui.detectThread = requestAnimationFrame((now) => runHumanDetect(input, canvas, now)); } }); } @@ -326,7 +333,7 @@ async function detectVideo() { status(''); video.play(); } - runHumanDetect(video, canvas); + if (!ui.detectThread) runHumanDetect(video, canvas); } // just initialize everything and call main function diff --git a/src/age/age.js b/src/age/age.js index ce8d4277..d07d4bbf 100644 --- a/src/age/age.js +++ b/src/age/age.js @@ -16,7 +16,7 @@ async function load(config) { async function predict(image, config) { 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; return last; } diff --git a/src/emotion/emotion.js b/src/emotion/emotion.js index add41718..dbf76b86 100644 --- a/src/emotion/emotion.js +++ b/src/emotion/emotion.js @@ -21,7 +21,7 @@ async function load(config) { async function predict(image, config) { 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; return last; } diff --git a/src/gender/gender.js b/src/gender/gender.js index aeef72ca..5bf82901 100644 --- a/src/gender/gender.js +++ b/src/gender/gender.js @@ -21,7 +21,7 @@ async function load(config) { async function predict(image, config) { 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; return last; } diff --git a/src/hand/handpipeline.js b/src/hand/handpipeline.js index f74639f3..d24b0826 100644 --- a/src/hand/handpipeline.js +++ b/src/hand/handpipeline.js @@ -89,7 +89,7 @@ class HandPipeline { // run new detector every skipFrames unless we only want box to start with 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); // don't reset on test image if ((image.shape[1] !== 255) && (image.shape[2] !== 255)) this.skipped = 0; diff --git a/src/human.js b/src/human.js index 390c3d02..ac62384e 100644 --- a/src/human.js +++ b/src/human.js @@ -12,11 +12,6 @@ import * as profile from './profile.js'; import * as config from '../config.js'; 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 const now = () => { if (typeof performance !== 'undefined') return performance.now(); @@ -327,7 +322,6 @@ class Human { // update configuration this.config = mergeDeep(this.config, userConfig); - if (!this.config.videoOptimized) this.config = mergeDeep(this.config, disableSkipFrames); // sanity checks this.state = 'check'; diff --git a/wiki b/wiki index e29ef088..79cd119c 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit e29ef0887f0be593ef827ee5020fe6a40f588f38 +Subproject commit 79cd119c0c5714324a0dae82477ce36e1d5f40a1