mirror of https://github.com/vladmandic/human
implemented blink detection
parent
65d045547d
commit
63cc122e9b
|
@ -22,6 +22,7 @@
|
||||||
- [**Usage**](https://github.com/vladmandic/human/wiki/Usage)
|
- [**Usage**](https://github.com/vladmandic/human/wiki/Usage)
|
||||||
- [**Configuration**](https://github.com/vladmandic/human/wiki/Configuration)
|
- [**Configuration**](https://github.com/vladmandic/human/wiki/Configuration)
|
||||||
- [**Outputs**](https://github.com/vladmandic/human/wiki/Outputs)
|
- [**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)
|
- [**Demos**](https://github.com/vladmandic/human/wiki/Demos)
|
||||||
- [**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)
|
||||||
|
|
|
@ -297,7 +297,7 @@ async function detectSampleImages() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupMenu() {
|
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());
|
const btn = menu.addButton('start video', 'pause video', () => detectVideo());
|
||||||
menu.addButton('process images', 'process images', () => detectSampleImages());
|
menu.addButton('process images', 'process images', () => detectSampleImages());
|
||||||
document.getElementById('play').addEventListener('click', () => btn.click());
|
document.getElementById('play').addEventListener('click', () => btn.click());
|
||||||
|
@ -352,7 +352,7 @@ function setupMenu() {
|
||||||
menu.addHTML('<hr style="min-width: 200px; border-style: inset; border-color: dimgray">');
|
menu.addHTML('<hr style="min-width: 200px; border-style: inset; border-color: dimgray">');
|
||||||
menu.addChart('FPS', 'FPS');
|
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.addLabel('ui options');
|
||||||
menuFX.addBool('crop & scale', ui, 'crop', () => setupCamera());
|
menuFX.addBool('crop & scale', ui, 'crop', () => setupCamera());
|
||||||
menuFX.addBool('camera front/back', ui, 'facing', () => setupCamera());
|
menuFX.addBool('camera front/back', ui, 'facing', () => setupCamera());
|
||||||
|
|
13
demo/menu.js
13
demo/menu.js
|
@ -55,6 +55,9 @@ function createCSS() {
|
||||||
input[type=range] { -webkit-appearance: none; }
|
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-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; }
|
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');
|
const el = document.createElement('style');
|
||||||
el.innerHTML = css;
|
el.innerHTML = css;
|
||||||
|
@ -89,18 +92,22 @@ class Menu {
|
||||||
this.container.id = `menu-container-${instance}`;
|
this.container.id = `menu-container-${instance}`;
|
||||||
this.container.className = 'menu-container menu-container-fadein';
|
this.container.className = 'menu-container menu-container-fadein';
|
||||||
|
|
||||||
if (title !== '') {
|
// set menu title with pulldown arrow
|
||||||
const elTitle = document.createElement('div');
|
const elTitle = document.createElement('div');
|
||||||
elTitle.className = 'menu-title';
|
elTitle.className = 'menu-title';
|
||||||
elTitle.id = `menu-title-${instance}`;
|
elTitle.id = `menu-title-${instance}`;
|
||||||
elTitle.innerHTML = title;
|
const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512" style="width: 2rem; height: 2rem; vertical-align: top;">
|
||||||
|
<path d="M400 32H48A48 48 0 0 0 0 80v352a48 48 0 0 0 48 48h352a48 48 0 0 0 48-48V80a48 48 0 0 0-48-48zm-51.37 182.31L232.06 348.16a10.38 10.38 0 0 1-16.12 0L99.37 214.31C92.17 206 97.28 192 107.43 192h233.14c10.15 0 15.26 14 8.06 22.31z" class="svg-background"/>
|
||||||
|
<path d="M348.63 214.31L232.06 348.16a10.38 10.38 0 0 1-16.12 0L99.37 214.31C92.17 206 97.28 192 107.43 192h233.14c10.15 0 15.26 14 8.06 22.31z" class="svg-foreground"/>
|
||||||
|
</svg>`;
|
||||||
|
elTitle.innerHTML = `${title}${svg}`;
|
||||||
this.menu.appendChild(elTitle);
|
this.menu.appendChild(elTitle);
|
||||||
elTitle.addEventListener('click', () => {
|
elTitle.addEventListener('click', () => {
|
||||||
this.container.classList.toggle('menu-container-fadeout');
|
this.container.classList.toggle('menu-container-fadeout');
|
||||||
this.container.classList.toggle('menu-container-fadein');
|
this.container.classList.toggle('menu-container-fadein');
|
||||||
this.menu.style.borderStyle = this.container.classList.contains('menu-container-fadeout') ? 'none' : 'solid';
|
this.menu.style.borderStyle = this.container.classList.contains('menu-container-fadeout') ? 'none' : 'solid';
|
||||||
});
|
});
|
||||||
}
|
|
||||||
this.menu.appendChild(this.container);
|
this.menu.appendChild(this.container);
|
||||||
if (typeof parent === 'object') parent.appendChild(this.menu);
|
if (typeof parent === 'object') parent.appendChild(this.menu);
|
||||||
else document.getElementById(parent).appendChild(this.menu);
|
else document.getElementById(parent).appendChild(this.menu);
|
||||||
|
|
|
@ -25,6 +25,10 @@ exports.face = (res) => {
|
||||||
if (face.annotations['rightCheek'] && face.annotations['leftCheek'] && (face.annotations['rightCheek'].length > 0) && (face.annotations['leftCheek'].length > 0)) {
|
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'}`);
|
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;
|
return gestures;
|
||||||
};
|
};
|
||||||
|
|
|
@ -245,9 +245,10 @@ class Human {
|
||||||
face.image.dispose();
|
face.image.dispose();
|
||||||
|
|
||||||
// calculate iris distance
|
// calculate iris distance
|
||||||
// iris: array[ bottom, left, top, right, center ]
|
// iris: array[ center, left, top, right, bottom]
|
||||||
const iris = (face.annotations.leftEyeIris && face.annotations.rightEyeIris)
|
const irisSize = (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])
|
/* 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;
|
: 0;
|
||||||
|
|
||||||
// combine results
|
// combine results
|
||||||
|
@ -260,7 +261,7 @@ class Human {
|
||||||
gender: genderRes.gender,
|
gender: genderRes.gender,
|
||||||
genderConfidence: genderRes.confidence,
|
genderConfidence: genderRes.confidence,
|
||||||
emotion: emotionRes,
|
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');
|
this.analyze('End Face');
|
||||||
}
|
}
|
||||||
|
|
2
wiki
2
wiki
|
@ -1 +1 @@
|
||||||
Subproject commit b70041ff6b67e01ac2ed521bdd01c43a970ff351
|
Subproject commit 63c2347b5256777d5154bd5d502b2a075d3d950d
|
Loading…
Reference in New Issue