add wasm bundle

pull/293/head
Vladimir Mandic 2020-11-09 20:13:38 -05:00
parent 18da5913e9
commit bc1f987872
16 changed files with 72 additions and 55 deletions

View File

@ -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)

View File

@ -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

View File

@ -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);

View File

@ -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'); }

View File

@ -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; }

View File

@ -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"
},

View File

@ -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 };

View File

@ -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 = {};

View File

@ -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: '' };

View File

@ -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 [

View File

@ -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) {

View File

@ -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;

View File

@ -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],

View File

@ -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);

View File

@ -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

@ -1 +1 @@
Subproject commit 17d21d19953ab16616c4a07423c0eada76577686
Subproject commit 6674208a10ed65d0737bb5c2b05b67f2b70fab19