mirror of https://github.com/vladmandic/human
added multi backend support
parent
a6024c40e8
commit
51d3b429e6
58
README.md
58
README.md
|
@ -1,8 +1,10 @@
|
|||
# Human: 3D Face Detection, Body Pose, Hand & Finger Tracking, Iris Tracking, Age & Gender Prediction & Emotion Prediction
|
||||
# Human Library
|
||||
|
||||
## 3D Face Detection, Body Pose, Hand & Finger Tracking, Iris Tracking, Age & Gender Prediction & Emotion Prediction
|
||||
|
||||
- [**Documentation**](https://github.com/vladmandic/human#readme)
|
||||
- [**Code Repository**](https://github.com/vladmandic/human)
|
||||
- [**Package**](https://www.npmjs.com/package/@vladmandic/human)
|
||||
- [**NPM Package**](https://www.npmjs.com/package/@vladmandic/human)
|
||||
- [**Issues Tracker**](https://github.com/vladmandic/human/issues)
|
||||
- [**Live Demo**](https://vladmandic.github.io/human/demo/demo-esm.html)
|
||||
|
||||
|
@ -30,6 +32,25 @@ Compatible with Browser, WebWorker and NodeJS execution!
|
|||
|
||||
There are multiple ways to use `Human` library, pick one that suits you:
|
||||
|
||||
### Included
|
||||
|
||||
- `dist/human.js`: IIFE format minified bundle with TFJS for Browsers
|
||||
- `dist/human.esm.js`: ESM format minified bundle with TFJS for Browsers
|
||||
- `dist/human.esm-nobundle.js`: ESM format non-minified bundle without TFJS for Browsers
|
||||
- `dist/human.cjs`: CommonJS format minified bundle with TFJS for NodeJS
|
||||
- `dist/human-nobundle.cjs`: CommonJS format non-minified bundle without TFJS for NodeJS
|
||||
|
||||
All versions include `sourcemap`
|
||||
|
||||
Defaults:
|
||||
```json
|
||||
{
|
||||
"main": "dist/human.cjs",
|
||||
"module": "dist/human.esm.js",
|
||||
"browser": "dist/human.esm.js",
|
||||
}
|
||||
```
|
||||
|
||||
### 1. [IIFE](https://developer.mozilla.org/en-US/docs/Glossary/IIFE) script
|
||||
|
||||
*Simplest way for usage within Browser*
|
||||
|
@ -43,8 +64,6 @@ Simply download `dist/human.js`, include it in your `HTML` file & it's ready to
|
|||
IIFE script auto-registers global namespace `human` within global `Window` object
|
||||
This way you can also use `Human` library within embbedded `<script>` tag within your `html` page for all-in-one approach
|
||||
|
||||
IIFE script is distributed in minified form with attached sourcemap
|
||||
|
||||
### 2. [ESM](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) module
|
||||
|
||||
*Recommended for usage within `Browser`*
|
||||
|
@ -53,18 +72,25 @@ IIFE script is distributed in minified form with attached sourcemap
|
|||
|
||||
If you're using bundler *(such as rollup, webpack, esbuild)* to package your client application, you can import ESM version of `Human` library which supports full tree shaking
|
||||
|
||||
Install with:
|
||||
```shell
|
||||
npm install @vladmandic/human
|
||||
```
|
||||
```js
|
||||
import human from '@vladmandic/human'; // points to @vladmandic/human/dist/human.esm.js
|
||||
```
|
||||
|
||||
Or if you prefer to package your version of `tfjs`, you can use `nobundle` version
|
||||
|
||||
Install with:
|
||||
```shell
|
||||
npm install @vladmandic/human @tensorflow/tfjs-node
|
||||
```
|
||||
```js
|
||||
import tf from '@tensorflow/tfjs'
|
||||
import human from '@vladmandic/human/dist/human.nobundle.js'; // same functionality as default import, but without tfjs bundled
|
||||
import human from '@vladmandic/human/dist/human.esm-nobundle.js'; // same functionality as default import, but without tfjs bundled
|
||||
```
|
||||
|
||||
|
||||
#### 2.2 Using Script Module
|
||||
You could use same syntax within your main `JS` file if it's imported with `<script type="module">`
|
||||
|
||||
|
@ -74,11 +100,10 @@ You could use same syntax within your main `JS` file if it's imported with `<scr
|
|||
and then in your `index.js`
|
||||
|
||||
```js
|
||||
import human from 'dist/human.esm.js';
|
||||
import * as tf from `https://cdnjs.cloudflare.com/ajax/libs/tensorflow/2.6.0/tf.es2017.min.js`; // load tfjs directly from CDN link
|
||||
import human from 'dist/human.esm.js'; // for direct import must use path to module, not package name
|
||||
```
|
||||
|
||||
ESM script is distributed in minified form with attached sourcemap
|
||||
|
||||
### 3. [NPM](https://www.npmjs.com/) module
|
||||
|
||||
*Recommended for `NodeJS` projects that will execute in the backend*
|
||||
|
@ -88,13 +113,22 @@ You also need to install and include `tfjs-node` or `tfjs-node-gpu` in your proj
|
|||
|
||||
Install with:
|
||||
```shell
|
||||
npm install @tensorflow/tfjs-node @vladmandic/human
|
||||
npm install @vladmandic/human
|
||||
```
|
||||
And then use with:
|
||||
```js
|
||||
const tf = require('@tensorflow/tfjs-node');
|
||||
const human = require('@vladmandic/human'); // points to @vladmandic/human/dist/human.node.js
|
||||
const human = require('@vladmandic/human'); // points to @vladmandic/human/dist/human.cjs
|
||||
```
|
||||
or
|
||||
```shell
|
||||
npm install @vladmandic/human @tensorflow/tfjs-node
|
||||
```
|
||||
And then use with:
|
||||
```js
|
||||
const tf = require('@tensorflow/tfjs-node'); // can also use '@tensorflow/tfjs-node-gpu' if you have environment with CUDA extensions
|
||||
const human = require('@vladmandic/human/dist/human-nobundle.cjs');
|
||||
```
|
||||
|
||||
|
||||
Since NodeJS projects load `weights` from local filesystem instead of using `http` calls, you must modify default configuration to include correct paths with `file://` prefix
|
||||
For example:
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
/* global QuickSettings */
|
||||
/* global tf, QuickSettings */
|
||||
|
||||
import human from '../dist/human.esm.js';
|
||||
|
||||
const ui = {
|
||||
backend: 'wasm',
|
||||
baseColor: 'rgba(255, 200, 255, 0.3)',
|
||||
baseLabel: 'rgba(255, 200, 255, 0.8)',
|
||||
baseFont: 'small-caps 1.2rem "Segoe UI"',
|
||||
|
@ -34,6 +35,15 @@ function str(...msg) {
|
|||
return line;
|
||||
}
|
||||
|
||||
async function setupTF() {
|
||||
if (ui.backend === 'wasm') {
|
||||
tf.env().set('WASM_HAS_SIMD_SUPPORT', false);
|
||||
tf.env().set('WASM_HAS_MULTITHREAD_SUPPORT', true);
|
||||
}
|
||||
await human.tf.setBackend(ui.backend);
|
||||
await human.tf.ready();
|
||||
}
|
||||
|
||||
async function drawFace(result, canvas) {
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.strokeStyle = ui.baseColor;
|
||||
|
@ -217,9 +227,10 @@ async function runHumanDetect(input, canvas) {
|
|||
drawHand(result.hand, canvas);
|
||||
// update log
|
||||
const engine = await human.tf.engine();
|
||||
const memory = `Memory: ${engine.state.numBytes.toLocaleString()} bytes ${engine.state.numDataBuffers.toLocaleString()} buffers ${engine.state.numTensors.toLocaleString()} tensors`;
|
||||
const memory = `${engine.state.numBytes.toLocaleString()} bytes ${engine.state.numDataBuffers.toLocaleString()} buffers ${engine.state.numTensors.toLocaleString()} tensors`;
|
||||
const gpu = engine.backendInstance.numBytesInGPU ? `GPU: ${engine.backendInstance.numBytesInGPU.toLocaleString()} bytes` : '';
|
||||
log.innerText = `
|
||||
TFJS Version: ${human.tf.version_core} | ${memory} | GPU: ${engine.backendInstance.numBytesInGPU.toLocaleString()} bytes
|
||||
TFJS Version: ${human.tf.version_core} | Backend: ${human.tf.getBackend()} | Memory: ${memory} ${gpu}
|
||||
Performance: ${str(result.performance)} | Object size: ${(str(result)).length.toLocaleString()} bytes
|
||||
`;
|
||||
// rinse & repeate
|
||||
|
@ -255,6 +266,11 @@ function setupGUI() {
|
|||
}
|
||||
runHumanDetect(video, canvas);
|
||||
});
|
||||
settings.addDropDown('Backend', ['webgl', 'wasm', 'cpu'], (val) => {
|
||||
ui.backend = val.value;
|
||||
setupTF();
|
||||
});
|
||||
settings.addHTML('title', 'Enabled Models'); settings.hideTitle('title');
|
||||
settings.addBoolean('Face Detect', config.face.enabled, (val) => config.face.enabled = val);
|
||||
settings.addBoolean('Face Mesh', config.face.mesh.enabled, (val) => config.face.mesh.enabled = val);
|
||||
settings.addBoolean('Face Iris', config.face.iris.enabled, (val) => config.face.iris.enabled = val);
|
||||
|
@ -263,7 +279,7 @@ function setupGUI() {
|
|||
settings.addBoolean('Face Emotion', config.face.emotion.enabled, (val) => config.face.emotion.enabled = val);
|
||||
settings.addBoolean('Body Pose', config.body.enabled, (val) => config.body.enabled = val);
|
||||
settings.addBoolean('Hand Pose', config.hand.enabled, (val) => config.hand.enabled = val);
|
||||
settings.addHTML('line3', '<hr>'); settings.hideTitle('line3');
|
||||
settings.addHTML('title', 'Model Parameters'); settings.hideTitle('title');
|
||||
settings.addRange('Max Objects', 1, 20, 5, 1, (val) => {
|
||||
config.face.detector.maxFaces = parseInt(val);
|
||||
config.body.maxDetections = parseInt(val);
|
||||
|
@ -288,7 +304,7 @@ function setupGUI() {
|
|||
config.face.detector.iouThreshold = parseFloat(val);
|
||||
config.hand.iouThreshold = parseFloat(val);
|
||||
});
|
||||
settings.addHTML('line1', '<hr>'); settings.hideTitle('line1');
|
||||
settings.addHTML('title', 'UI Options'); settings.hideTitle('title');
|
||||
settings.addBoolean('Draw Boxes', true);
|
||||
settings.addBoolean('Draw Points', true);
|
||||
settings.addBoolean('Draw Polygons', true);
|
||||
|
@ -342,8 +358,7 @@ async function setupImage() {
|
|||
|
||||
async function main() {
|
||||
// initialize tensorflow
|
||||
await human.tf.setBackend('webgl');
|
||||
await human.tf.ready();
|
||||
await setupTF();
|
||||
// setup ui control panel
|
||||
await setupGUI();
|
||||
// setup webcam
|
||||
|
|
13
package.json
13
package.json
|
@ -3,9 +3,9 @@
|
|||
"version": "0.3.1",
|
||||
"description": "human: 3D Face Detection, Iris Tracking and Age & Gender Prediction",
|
||||
"sideEffects": false,
|
||||
"main": "dist/human.node.js",
|
||||
"main": "dist/human.cjs",
|
||||
"module": "dist/human.esm.js",
|
||||
"browser": "dist/human.esmjs",
|
||||
"browser": "dist/human.esm.js",
|
||||
"author": "Vladimir Mandic <mandic00@live.com>",
|
||||
"bugs": {
|
||||
"url": "https://github.com/vladmandic/human/issues"
|
||||
|
@ -36,11 +36,12 @@
|
|||
"scripts": {
|
||||
"start": "node --trace-warnings --trace-uncaught --no-deprecation demo/demo-node.js",
|
||||
"lint": "eslint src/*.js demo/*.js",
|
||||
"build": "rimraf dist/ && npm run build-iife && npm run build-esm && npm run build-nobundle && npm run build-node && ls -l dist/",
|
||||
"build-iife": "esbuild --bundle --platform=browser --sourcemap --target=esnext --format=iife --minify --external:fs --global-name=human --outfile=dist/human.js src/index.js",
|
||||
"build-esm": "esbuild --bundle --platform=browser --sourcemap --target=esnext --format=esm --external:fs --outfile=dist/human.esm.js src/index.js",
|
||||
"build-nobundle": "esbuild --bundle --platform=browser --sourcemap --target=esnext --format=esm --minify --external:@tensorflow --external:fs --outfile=dist/human.nobundle.js src/index.js",
|
||||
"build-node": "esbuild --bundle --platform=node --sourcemap --target=esnext --format=cjs --external:@tensorflow --outfile=dist/human.node.js src/index.js",
|
||||
"build-esm-bundle": "esbuild --bundle --platform=browser --sourcemap --target=esnext --format=esm --external:fs --outfile=dist/human.esm.js src/index.js",
|
||||
"build-esm-nobundle": "esbuild --bundle --platform=browser --sourcemap --target=esnext --format=esm --minify --external:@tensorflow --external:fs --outfile=dist/human.esm-nobundle.js src/index.js",
|
||||
"build-node-bundle": "esbuild --bundle --platform=node --sourcemap --target=esnext --format=cjs --minify --outfile=dist/human.cjs src/index.js",
|
||||
"build-node-nobundle": "esbuild --bundle --platform=node --sourcemap --target=esnext --format=cjs --external:@tensorflow --outfile=dist/human-nobundle.cjs src/index.js",
|
||||
"build": "rimraf dist/* && npm run build-iife && npm run build-esm-bundle && npm run build-esm-nobundle && npm run build-node-bundle && npm run build-node-nobundle && ls -l dist/",
|
||||
"update": "npm update --depth 20 && npm dedupe && npm prune && npm audit"
|
||||
},
|
||||
"keywords": [
|
||||
|
|
Loading…
Reference in New Issue