mirror of https://github.com/vladmandic/human
add wasm bundle
parent
a9c393635f
commit
de2819a96e
|
@ -18,12 +18,13 @@
|
|||
### Wiki pages:
|
||||
|
||||
- [**Home**](https://github.com/vladmandic/human/wiki)
|
||||
- [**Demos**](https://github.com/vladmandic/human/wiki/Demos)
|
||||
- [**Installation**](https://github.com/vladmandic/human/wiki/Install)
|
||||
- [**Usage**](https://github.com/vladmandic/human/wiki/Usage)
|
||||
- [**Usage**](https://github.com/vladmandic/human/wiki/Backends)
|
||||
- [**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)
|
||||
- [**Profiling**](https://github.com/vladmandic/human/wiki/Profiling)
|
||||
|
@ -33,7 +34,7 @@
|
|||
<br>
|
||||
|
||||
Compatible with *Browser*, *WebWorker* and *NodeJS* execution on both Windows and Linux
|
||||
- Browser/WebWorker: Compatible with *CPU*, *WebGL*, *WASM* and *WebGPU* backends
|
||||
- Browser/WebWorker: Compatible with *CPU*, *WebGL* and *WASM* backends
|
||||
- NodeJS: Compatible with software *tfjs-node* and CUDA accelerated backends *tfjs-node-gpu*
|
||||
|
||||
(and maybe with React-Native as it doesn't use any DOM objects)
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
export default {
|
||||
backend: 'webgl', // select tfjs backend to use
|
||||
wasmPath: '../assets/', // path for wasm binaries
|
||||
// only used for backend: wasm
|
||||
console: true, // enable debugging output to console
|
||||
async: true, // execute enabled models in parallel
|
||||
// this disables per-model performance data but
|
||||
|
|
|
@ -157,7 +157,7 @@ async function setupCamera() {
|
|||
const track = stream.getVideoTracks()[0];
|
||||
const settings = track.getSettings();
|
||||
// log('camera constraints:', constraints, 'window:', { width: window.innerWidth, height: window.innerHeight }, 'settings:', settings, 'track:', track);
|
||||
ui.camera = { name: track.label, width: settings.width, height: settings.height, facing: settings.facingMode === 'user' ? 'front' : 'back' };
|
||||
ui.camera = { name: track.label?.toLowerCase(), width: settings.width, height: settings.height, facing: settings.facingMode === 'user' ? 'front' : 'back' };
|
||||
return new Promise((resolve) => {
|
||||
video.onloadeddata = async () => {
|
||||
video.width = video.videoWidth;
|
||||
|
@ -303,7 +303,7 @@ function setupMenu() {
|
|||
document.getElementById('play').addEventListener('click', () => btn.click());
|
||||
|
||||
menu.addHTML('<hr style="min-width: 200px; border-style: inset; border-color: dimgray">');
|
||||
menu.addList('backend', ['cpu', 'webgl', 'wasm', 'webgpu'], human.config.backend, (val) => human.config.backend = val);
|
||||
menu.addList('backend', ['cpu', 'webgl', 'wasm'], human.config.backend, (val) => human.config.backend = val);
|
||||
menu.addBool('async operations', human.config, 'async', (val) => human.config.async = val);
|
||||
menu.addBool('enable profiler', human.config, 'profile', (val) => human.config.profile = val);
|
||||
menu.addBool('memory shield', human.config, 'deallocate', (val) => human.config.deallocate = val);
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<meta http-equiv="content-type">
|
||||
<meta content="text/html">
|
||||
<meta charset="UTF-8">
|
||||
<meta name="description" content="3D Face Detection, Body Pose, Hand & Finger Tracking, Iris Tracking, Age & Gender Prediction & Emotion Prediction; Author: Vladimir Mandic <mandic00@live.com>">
|
||||
<meta name="description" content="3D Face Detection, Body Pose, Hand & Finger Tracking, Iris Tracking, Age & Gender Prediction, Emotion Prediction & Gesture Recognition; Author: Vladimir Mandic <https://github.com/vladmandic>">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.6, minimum-scale=0.1, maximum-scale=4.0, shrink-to-fit=yes, user-scalable=yes">
|
||||
<meta name="theme-color" content="#000000"/>
|
||||
<meta name="application-name" content="Human">
|
||||
|
@ -13,13 +13,9 @@
|
|||
<link rel="manifest" href="./manifest.json">
|
||||
<link rel="shortcut icon" href="../favicon.ico" type="image/x-icon">
|
||||
<link rel="apple-touch-icon" href="../assets/icon.png">
|
||||
<!-- not required for tfjs cpu or webgl backends, required if you want to use tfjs wasm or webgpu backends -->
|
||||
<!-- <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@2.7.0/dist/tf.es2017.js"></script> -->
|
||||
<!-- <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-backend-wasm@2.7.0/dist/tf-backend-wasm.es2017.js"></script> -->
|
||||
<!-- <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-backend-webgpu@0.0.1-alpha.0/dist/tf-webgpu.js"></script> -->
|
||||
<!-- load compiled demo js -->
|
||||
<script src="../dist/demo-browser-index.js"></script>
|
||||
<!-- alternatively load demo sources directly, this is not supported on mobile platforms as they don't support type=module -->
|
||||
<!-- alternatively load demo sources directly -->
|
||||
<!-- <script src="./browser.js" type="module"></script> -->
|
||||
<style>
|
||||
@font-face { font-family: 'Lato'; font-display: swap; font-style: normal; font-weight: 400; src: local('Lato'), url('../assets/lato.ttf') format('truetype'); }
|
||||
|
|
16
demo/menu.js
16
demo/menu.js
|
@ -33,28 +33,34 @@ function createCSS() {
|
|||
|
||||
.menu-list { margin-right: 0.8rem; }
|
||||
select:focus { outline: none; }
|
||||
.menu-list-item { background: ${theme.itemBackground}; color: ${theme.itemColor}; border: none; padding: 0.2rem; font-family: inherit; font-variant: inherit; border-radius: var(--rounded); font-weight: 800; }
|
||||
.menu-list-item { background: ${theme.itemBackground}; color: ${theme.itemColor}; border: none; padding: 0.2rem; font-family: inherit;
|
||||
font-variant: inherit; border-radius: var(--rounded); font-weight: 800; }
|
||||
|
||||
.menu-chart-title { padding: 0; font-size: 0.8rem; font-weight: 800; align-items: center}
|
||||
.menu-chart-canvas { background: transparent; margin: 0.2rem 0 0.2rem 0.6rem; }
|
||||
|
||||
.menu-button { border: 0; background: ${theme.buttonBackground}; width: -webkit-fill-available; padding: 8px; margin: 8px 0 8px 0; cursor: pointer; box-shadow: 4px 4px 4px 0 dimgrey;
|
||||
border-radius: var(--rounded); justify-content: center; font-family: inherit; font-variant: inherit; font-size: 1rem; font-weight: 800; }
|
||||
.menu-button { border: 0; background: ${theme.buttonBackground}; width: 100%; padding: 8px; margin: 8px 0 8px 0; cursor: pointer; box-shadow: 4px 4px 4px 0 dimgrey;
|
||||
border-radius: var(--rounded); justify-content: center; font-family: inherit; font-variant: inherit; font-size: 1rem; font-weight: 800; }
|
||||
.menu-button:hover { background: ${theme.buttonHover}; box-shadow: 4px 4px 4px 0 black; }
|
||||
.menu-button:focus { outline: none; }
|
||||
|
||||
.menu-checkbox { width: 2.8rem; height: 1rem; background: ${theme.itemBackground}; margin: 0.5rem 0.8rem 0 0; position: relative; border-radius: var(--rounded); }
|
||||
.menu-checkbox:after { content: 'OFF'; color: ${theme.checkboxOff}; position: absolute; right: 0.2rem; top: -0.4rem; font-weight: 800; font-size: 0.5rem; }
|
||||
.menu-checkbox:before { content: 'ON'; color: ${theme.checkboxOn}; position: absolute; left: 0.3rem; top: -0.4rem; font-weight: 800; font-size: 0.5rem; }
|
||||
.menu-checkbox-label { width: 1.3rem; height: 0.8rem; cursor: pointer; position: absolute; top: 0.1rem; left: 0.1rem; z-index: 1; background: ${theme.checkboxOff}; border-radius: var(--rounded); transition: left 0.6s ease; }
|
||||
.menu-checkbox-label { width: 1.3rem; height: 0.8rem; cursor: pointer; position: absolute; top: 0.1rem; left: 0.1rem; z-index: 1; background: ${theme.checkboxOff};
|
||||
border-radius: var(--rounded); transition: left 0.6s ease; }
|
||||
|
||||
input[type=checkbox] { visibility: hidden; }
|
||||
input[type=checkbox]:checked + label { left: 1.4rem; background: ${theme.checkboxOn}; }
|
||||
|
||||
.menu-range { margin: 0 0.8rem 0 0; width: 5rem; background: transparent; color: ${theme.rangeBackground}; }
|
||||
.menu-range:before { content: attr(value); color: ${theme.rangeLabel}; margin: 0 0.4rem 0 0; font-weight: 800; font-size: 0.6rem; position: relative; top: 0.3rem; }
|
||||
.menu-range:before { color: ${theme.rangeLabel}; margin: 0 0.4rem 0 0; font-weight: 800; font-size: 0.6rem; position: relative; top: 0.3rem; content: attr(value); }
|
||||
|
||||
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]::-moz-range-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]::-moz-range-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; }
|
||||
|
|
16
package.json
16
package.json
|
@ -19,7 +19,9 @@
|
|||
"type": "git",
|
||||
"url": "git+https://github.com/vladmandic/human.git"
|
||||
},
|
||||
"dependencies": {},
|
||||
"dependencies": {
|
||||
"@tensorflow/tfjs-backend-wasm": "^2.7.0"
|
||||
},
|
||||
"peerDependencies": {},
|
||||
"devDependencies": {
|
||||
"@tensorflow/tfjs": "^2.7.0",
|
||||
|
@ -43,12 +45,12 @@
|
|||
"lint": "eslint src/*.js demo/*.js",
|
||||
"dev": "npm install && node --trace-warnings --unhandled-rejections=strict --trace-uncaught --no-deprecation dev-server/dev-server.js",
|
||||
"changelog": "node dev-server/changelog.js",
|
||||
"build-iife": "esbuild --bundle --minify --platform=browser --sourcemap --target=es2018 --format=iife --external:fs --global-name=Human --metafile=dist/human.json --outfile=dist/human.js src/human.js",
|
||||
"build-esm-bundle": "esbuild --bundle --minify --platform=browser --sourcemap --target=es2018 --format=esm --external:fs --metafile=dist/human.esm.json --outfile=dist/human.esm.js src/human.js",
|
||||
"build-esm-nobundle": "esbuild --bundle --minify --platform=browser --sourcemap --target=es2018 --format=esm --external:@tensorflow --external:fs --metafile=dist/human.esm-nobundle.json --outfile=dist/human.esm-nobundle.js src/human.js",
|
||||
"build-node": "esbuild --bundle --minify --platform=node --sourcemap --target=es2018 --format=cjs --metafile=dist/human.node.json --outfile=dist/human.node.js src/human.js",
|
||||
"build-node-nobundle": "esbuild --bundle --minify --platform=node --sourcemap --target=es2018 --format=cjs --external:@tensorflow --metafile=dist/human.node.json --outfile=dist/human.node-nobundle.js src/human.js",
|
||||
"build-demo": "esbuild --bundle --log-level=error --platform=browser --sourcemap --target=es2018 --format=esm --external:fs --metafile=dist/demo-browser-index.json --outfile=dist/demo-browser-index.js demo/browser.js",
|
||||
"build-iife": "esbuild --bundle --platform=browser --sourcemap --target=es2018 --format=iife --external:fs --external:buffer --external:util --global-name=Human --metafile=dist/human.json --outfile=dist/human.js src/human.js",
|
||||
"build-esm-bundle": "esbuild --bundle --platform=browser --sourcemap --target=es2018 --format=esm --external:fs --external:buffer --external:util --metafile=dist/human.esm.json --outfile=dist/human.esm.js src/human.js",
|
||||
"build-esm-nobundle": "esbuild --bundle --platform=browser --sourcemap --target=es2018 --format=esm --external:@tensorflow --external:fs --external:buffer --external:util --metafile=dist/human.esm-nobundle.json --outfile=dist/human.esm-nobundle.js src/human.js",
|
||||
"build-node": "esbuild --bundle --platform=node --sourcemap --target=es2018 --format=cjs --metafile=dist/human.node.json --outfile=dist/human.node.js src/human.js",
|
||||
"build-node-nobundle": "esbuild --bundle --platform=node --sourcemap --target=es2018 --format=cjs --external:@tensorflow --metafile=dist/human.node.json --outfile=dist/human.node-nobundle.js src/human.js",
|
||||
"build-demo": "esbuild --bundle --log-level=error --platform=browser --sourcemap --target=es2018 --format=esm --external:fs --external:buffer --external:util --metafile=dist/demo-browser-index.json --outfile=dist/demo-browser-index.js demo/browser.js",
|
||||
"build": "rimraf dist/* && npm run build-iife && npm run build-esm-bundle && npm run build-esm-nobundle && npm run build-node && npm run build-node-nobundle && npm run build-demo && npm run changelog",
|
||||
"update": "npm update --depth 20 --force && npm dedupe && npm prune && npm audit"
|
||||
},
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
const tf = require('@tensorflow/tfjs');
|
||||
const profile = require('../profile.js');
|
||||
import * as tf from '@tensorflow/tfjs/dist/tf.es2017.js';
|
||||
import * as profile from '../profile.js';
|
||||
|
||||
const models = {};
|
||||
let last = { age: 0 };
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
const tf = require('@tensorflow/tfjs');
|
||||
const profile = require('../profile.js');
|
||||
import * as tf from '@tensorflow/tfjs/dist/tf.es2017.js';
|
||||
import * as profile from '../profile.js';
|
||||
|
||||
const annotations = ['angry', 'disgust', 'fear', 'happy', 'sad', 'surpise', 'neutral'];
|
||||
const models = {};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
const tf = require('@tensorflow/tfjs');
|
||||
const profile = require('../profile.js');
|
||||
import * as tf from '@tensorflow/tfjs/dist/tf.es2017.js';
|
||||
import * as profile from '../profile.js';
|
||||
|
||||
const models = {};
|
||||
let last = { gender: '' };
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
* limitations under the License.
|
||||
* =============================================================================
|
||||
*/
|
||||
const tf = require('@tensorflow/tfjs');
|
||||
import * as tf from '@tensorflow/tfjs/dist/tf.es2017.js';
|
||||
|
||||
function getBoxSize(box) {
|
||||
return [
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
* =============================================================================
|
||||
*/
|
||||
|
||||
const tf = require('@tensorflow/tfjs');
|
||||
const box = require('./box');
|
||||
import * as tf from '@tensorflow/tfjs/dist/tf.es2017.js';
|
||||
import * as box from './box';
|
||||
|
||||
class HandDetector {
|
||||
constructor(model, inputSize, anchorsAnnotated) {
|
||||
|
|
|
@ -15,9 +15,9 @@
|
|||
* =============================================================================
|
||||
*/
|
||||
|
||||
const tf = require('@tensorflow/tfjs');
|
||||
const box = require('./box');
|
||||
const util = require('./util');
|
||||
import * as tf from '@tensorflow/tfjs/dist/tf.es2017.js';
|
||||
import * as box from './box';
|
||||
import * as util from './util';
|
||||
|
||||
const PALM_BOX_SHIFT_VECTOR = [0, -0.4];
|
||||
const PALM_BOX_ENLARGE_FACTOR = 3;
|
||||
|
|
|
@ -16,10 +16,10 @@
|
|||
*/
|
||||
// https://storage.googleapis.com/tfjs-models/demos/handpose/index.html
|
||||
|
||||
const tf = require('@tensorflow/tfjs');
|
||||
const handdetector = require('./handdetector');
|
||||
const pipeline = require('./handpipeline');
|
||||
const anchors = require('./anchors');
|
||||
import * as tf from '@tensorflow/tfjs/dist/tf.es2017.js';
|
||||
import * as handdetector from './handdetector';
|
||||
import * as pipeline from './handpipeline';
|
||||
import * as anchors from './anchors';
|
||||
|
||||
const MESH_ANNOTATIONS = {
|
||||
thumb: [1, 2, 3, 4],
|
||||
|
|
38
src/human.js
38
src/human.js
|
@ -1,15 +1,16 @@
|
|||
const tf = require('@tensorflow/tfjs');
|
||||
const facemesh = require('./face/facemesh.js');
|
||||
const age = require('./age/age.js');
|
||||
const gender = require('./gender/gender.js');
|
||||
const emotion = require('./emotion/emotion.js');
|
||||
const posenet = require('./body/posenet.js');
|
||||
const handpose = require('./hand/handpose.js');
|
||||
const gesture = require('./gesture.js');
|
||||
const image = require('./image.js');
|
||||
const profile = require('./profile.js');
|
||||
const defaults = require('../config.js').default;
|
||||
const app = require('../package.json');
|
||||
import * as tf from '@tensorflow/tfjs/dist/tf.es2017.js';
|
||||
import { setWasmPaths } from '@tensorflow/tfjs-backend-wasm/dist/index.js';
|
||||
import * as facemesh from './face/facemesh.js';
|
||||
import * as age from './age/age.js';
|
||||
import * as gender from './gender/gender.js';
|
||||
import * as emotion from './emotion/emotion.js';
|
||||
import * as posenet from './body/posenet.js';
|
||||
import * as handpose from './hand/handpose.js';
|
||||
import * as gesture from './gesture.js';
|
||||
import * as image from './image.js';
|
||||
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 = {
|
||||
|
@ -45,7 +46,7 @@ class Human {
|
|||
constructor(userConfig = {}) {
|
||||
this.tf = tf;
|
||||
this.version = app.version;
|
||||
this.config = mergeDeep(defaults, userConfig);
|
||||
this.config = mergeDeep(config.default, userConfig);
|
||||
this.fx = null;
|
||||
this.state = 'idle';
|
||||
this.numTensors = 0;
|
||||
|
@ -163,7 +164,16 @@ class Human {
|
|||
this.log('Backend not registred:', this.config.backend);
|
||||
}
|
||||
*/
|
||||
|
||||
this.log('setting backend:', this.config.backend);
|
||||
|
||||
if (this.config.backend === 'wasm') {
|
||||
this.log('settings wasm path:', this.config.wasmPath);
|
||||
setWasmPaths(this.config.wasmPath);
|
||||
const simd = await tf.env().getAsync('WASM_HAS_SIMD_SUPPORT');
|
||||
if (!simd) this.log('warning: wasm simd support is not enabled');
|
||||
}
|
||||
|
||||
await tf.setBackend(this.config.backend);
|
||||
tf.enableProdMode();
|
||||
/* debug mode is really too mcuh
|
||||
|
@ -171,7 +181,7 @@ class Human {
|
|||
*/
|
||||
if (this.config.backend === 'webgl') {
|
||||
if (this.config.deallocate) {
|
||||
this.log('Changing WebGL: WEBGL_DELETE_TEXTURE_THRESHOLD:', this.config.deallocate);
|
||||
this.log('changing webgl: WEBGL_DELETE_TEXTURE_THRESHOLD:', this.config.deallocate);
|
||||
tf.ENV.set('WEBGL_DELETE_TEXTURE_THRESHOLD', this.config.deallocate ? 0 : -1);
|
||||
}
|
||||
// tf.ENV.set('WEBGL_FORCE_F16_TEXTURES', true);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
const tf = require('@tensorflow/tfjs');
|
||||
const fxImage = require('./imagefx.js');
|
||||
import * as tf from '@tensorflow/tfjs/dist/tf.es2017.js';
|
||||
import * as fxImage from './imagefx.js';
|
||||
|
||||
// internal temp canvases
|
||||
let inCanvas = null;
|
||||
|
|
2
wiki
2
wiki
|
@ -1 +1 @@
|
|||
Subproject commit 17d21d19953ab16616c4a07423c0eada76577686
|
||||
Subproject commit 6674208a10ed65d0737bb5c2b05b67f2b70fab19
|
Loading…
Reference in New Issue