From 63cc122e9b4593fe8b331563cd84a9053cb619ed Mon Sep 17 00:00:00 2001 From: Vladimir Mandic Date: Mon, 9 Nov 2020 08:57:24 -0500 Subject: [PATCH] implemented blink detection --- README.md | 1 + demo/browser.js | 4 ++-- demo/menu.js | 31 +++++++++++++++++++------------ src/gesture.js | 4 ++++ src/human.js | 9 +++++---- wiki | 2 +- 6 files changed, 32 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 6f2a46cb..65607d3b 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ - [**Usage**](https://github.com/vladmandic/human/wiki/Usage) - [**Configuration**](https://github.com/vladmandic/human/wiki/Configuration) - [**Outputs**](https://github.com/vladmandic/human/wiki/Outputs) +- [**Gesture Recognition**](https://github.com/vladmandic/human/wiki/Gesture) - [**Demos**](https://github.com/vladmandic/human/wiki/Demos) - [**Development Server**](https://github.com/vladmandic/human/wiki/Development-Server) - [**Build Process**](https://github.com/vladmandic/human/wiki/Build-Process) diff --git a/demo/browser.js b/demo/browser.js index 78b1d690..598b5d94 100644 --- a/demo/browser.js +++ b/demo/browser.js @@ -297,7 +297,7 @@ async function detectSampleImages() { } function setupMenu() { - menu = new Menu(document.body, '...', { top: '1rem', right: '1rem' }); + menu = new Menu(document.body, '', { top: '1rem', right: '1rem' }); const btn = menu.addButton('start video', 'pause video', () => detectVideo()); menu.addButton('process images', 'process images', () => detectSampleImages()); document.getElementById('play').addEventListener('click', () => btn.click()); @@ -352,7 +352,7 @@ function setupMenu() { menu.addHTML('
'); menu.addChart('FPS', 'FPS'); - menuFX = new Menu(document.body, '...', { top: '1rem', right: '18rem' }); + menuFX = new Menu(document.body, '', { top: '1rem', right: '18rem' }); menuFX.addLabel('ui options'); menuFX.addBool('crop & scale', ui, 'crop', () => setupCamera()); menuFX.addBool('camera front/back', ui, 'facing', () => setupCamera()); diff --git a/demo/menu.js b/demo/menu.js index 7067e89e..008b150e 100644 --- a/demo/menu.js +++ b/demo/menu.js @@ -55,6 +55,9 @@ function createCSS() { input[type=range] { -webkit-appearance: none; } input[type=range]::-webkit-slider-runnable-track { width: 100%; height: 1rem; cursor: pointer; background: ${theme.itemBackground}; border-radius: var(--rounded); border: 1px; } input[type=range]::-webkit-slider-thumb { border: 1px solid #000000; margin-top: 0.05rem; height: 0.9rem; width: 1.5rem; border-radius: var(--rounded); background: ${theme.rangeBackground}; cursor: pointer; -webkit-appearance: none; } + + .svg-background { fill:darkslategrey; cursor:pointer; opacity: 0.6; } + .svg-foreground { fill:white; cursor:pointer; opacity: 0.8; } `; const el = document.createElement('style'); el.innerHTML = css; @@ -89,18 +92,22 @@ class Menu { this.container.id = `menu-container-${instance}`; this.container.className = 'menu-container menu-container-fadein'; - if (title !== '') { - const elTitle = document.createElement('div'); - elTitle.className = 'menu-title'; - elTitle.id = `menu-title-${instance}`; - elTitle.innerHTML = title; - this.menu.appendChild(elTitle); - elTitle.addEventListener('click', () => { - this.container.classList.toggle('menu-container-fadeout'); - this.container.classList.toggle('menu-container-fadein'); - this.menu.style.borderStyle = this.container.classList.contains('menu-container-fadeout') ? 'none' : 'solid'; - }); - } + // set menu title with pulldown arrow + const elTitle = document.createElement('div'); + elTitle.className = 'menu-title'; + elTitle.id = `menu-title-${instance}`; + const svg = ` + + + `; + elTitle.innerHTML = `${title}${svg}`; + this.menu.appendChild(elTitle); + elTitle.addEventListener('click', () => { + this.container.classList.toggle('menu-container-fadeout'); + this.container.classList.toggle('menu-container-fadein'); + this.menu.style.borderStyle = this.container.classList.contains('menu-container-fadeout') ? 'none' : 'solid'; + }); + this.menu.appendChild(this.container); if (typeof parent === 'object') parent.appendChild(this.menu); else document.getElementById(parent).appendChild(this.menu); diff --git a/src/gesture.js b/src/gesture.js index 23f489d1..618765c9 100644 --- a/src/gesture.js +++ b/src/gesture.js @@ -25,6 +25,10 @@ exports.face = (res) => { if (face.annotations['rightCheek'] && face.annotations['leftCheek'] && (face.annotations['rightCheek'].length > 0) && (face.annotations['leftCheek'].length > 0)) { gestures.push(`facing ${((face.annotations['rightCheek'][0][2] > 0) || (face.annotations['leftCheek'][0][2] < 0)) ? 'right' : 'left'}`); } + const openLeft = Math.abs(face.mesh[374][1] - face.mesh[386][1]) / Math.abs(face.mesh[443][1] - face.mesh[450][1]); // center of eye inner lid y coord div center of wider eye border y coord + if (openLeft < 0.2) gestures.push('blink left eye'); + const openRight = Math.abs(face.mesh[145][1] - face.mesh[159][1]) / Math.abs(face.mesh[223][1] - face.mesh[230][1]); // center of eye inner lid y coord div center of wider eye border y coord + if (openRight < 0.2) gestures.push('blink right eye'); } return gestures; }; diff --git a/src/human.js b/src/human.js index 0a306bee..1fe89b1a 100644 --- a/src/human.js +++ b/src/human.js @@ -245,9 +245,10 @@ class Human { face.image.dispose(); // calculate iris distance - // iris: array[ bottom, left, top, right, center ] - const iris = (face.annotations.leftEyeIris && face.annotations.rightEyeIris) - ? Math.max(face.annotations.leftEyeIris[3][0] - face.annotations.leftEyeIris[1][0], face.annotations.rightEyeIris[3][0] - face.annotations.rightEyeIris[1][0]) + // iris: array[ center, left, top, right, bottom] + const irisSize = (face.annotations.leftEyeIris && face.annotations.rightEyeIris) + /* average human iris size is 11.7mm */ + ? 11.7 * Math.max(Math.abs(face.annotations.leftEyeIris[3][0] - face.annotations.leftEyeIris[1][0]), Math.abs(face.annotations.rightEyeIris[4][1] - face.annotations.rightEyeIris[2][1])) : 0; // combine results @@ -260,7 +261,7 @@ class Human { gender: genderRes.gender, genderConfidence: genderRes.confidence, emotion: emotionRes, - iris: (iris !== 0) ? Math.trunc(100 * 11.7 /* human iris size in mm */ / iris) / 100 : 0, + iris: (irisSize !== 0) ? Math.trunc(irisSize) / 100 : 0, }); this.analyze('End Face'); } diff --git a/wiki b/wiki index b70041ff..63c2347b 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit b70041ff6b67e01ac2ed521bdd01c43a970ff351 +Subproject commit 63c2347b5256777d5154bd5d502b2a075d3d950d