mirror of https://github.com/vladmandic/human
changed demo build process
parent
7773d23aa1
commit
a5f8ea7f86
|
@ -161,7 +161,9 @@ If your application resides in a different folder, modify `modelPath` property i
|
|||
Demos are included in `/demo`:
|
||||
|
||||
**Browser**:
|
||||
- `index.html`, `browser.js`, `worker.js`: Full demo using Browser with ESM module, includes selectable backends and webworkers
|
||||
- `index.html`: Full demo using Browser with ESM module, includes selectable backends and webworkers
|
||||
it loads `dist/demo-browser-index.js` which is built from sources in `demo`, starting with `demo/browser`
|
||||
alternatively you can load `demo/browser.js` directly
|
||||
|
||||
*If you want to test `wasm` or `webgpu` backends, enable loading in `index.html`*
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ export default {
|
|||
// as face probably hasn't moved much in short time (10 * 1/25 = 0.25 sec)
|
||||
minConfidence: 0.5, // threshold for discarding a prediction
|
||||
iouThreshold: 0.3, // threshold for deciding whether boxes overlap too much in non-maximum suppression
|
||||
scoreThreshold: 0.7, // threshold for deciding when to remove boxes based on score in non-maximum suppression
|
||||
scoreThreshold: 0.5, // threshold for deciding when to remove boxes based on score in non-maximum suppression
|
||||
},
|
||||
mesh: {
|
||||
enabled: true,
|
||||
|
@ -97,7 +97,7 @@ export default {
|
|||
inputResolution: 257, // fixed value
|
||||
outputStride: 16, // fixed value
|
||||
maxDetections: 10, // maximum number of people detected in the input, should be set to the minimum number for performance
|
||||
scoreThreshold: 0.7, // threshold for deciding when to remove boxes based on score in non-maximum suppression
|
||||
scoreThreshold: 0.5, // threshold for deciding when to remove boxes based on score in non-maximum suppression
|
||||
nmsRadius: 20, // radius for deciding points are too close in non-maximum suppression
|
||||
},
|
||||
hand: {
|
||||
|
@ -108,7 +108,7 @@ export default {
|
|||
// as the hand probably hasn't moved much in short time (10 * 1/25 = 0.25 sec)
|
||||
minConfidence: 0.5, // threshold for discarding a prediction
|
||||
iouThreshold: 0.3, // threshold for deciding whether boxes overlap too much in non-maximum suppression
|
||||
scoreThreshold: 0.7, // threshold for deciding when to remove boxes based on score in non-maximum suppression
|
||||
scoreThreshold: 0.5, // threshold for deciding when to remove boxes based on score in non-maximum suppression
|
||||
enlargeFactor: 1.65, // empiric tuning as skeleton prediction prefers hand box with some whitespace
|
||||
maxHands: 10, // maximum number of hands detected in the input, should be set to the minimum number for performance
|
||||
detector: {
|
||||
|
|
|
@ -55,15 +55,15 @@ const config = {
|
|||
videoOptimized: true,
|
||||
face: {
|
||||
enabled: true,
|
||||
detector: { maxFaces: 10, skipFrames: 10, minConfidence: 0.5, iouThreshold: 0.3, scoreThreshold: 0.7 },
|
||||
detector: { maxFaces: 10, skipFrames: 10, minConfidence: 0.5, iouThreshold: 0.3, scoreThreshold: 0.5 },
|
||||
mesh: { enabled: true },
|
||||
iris: { enabled: true },
|
||||
age: { enabled: true, skipFrames: 10 },
|
||||
gender: { enabled: true },
|
||||
emotion: { enabled: true, minConfidence: 0.5, useGrayscale: true },
|
||||
},
|
||||
body: { enabled: true, maxDetections: 10, scoreThreshold: 0.7, nmsRadius: 20 },
|
||||
hand: { enabled: true, skipFrames: 10, minConfidence: 0.5, iouThreshold: 0.3, scoreThreshold: 0.7 },
|
||||
body: { enabled: true, maxDetections: 10, scoreThreshold: 0.5, nmsRadius: 20 },
|
||||
hand: { enabled: true, skipFrames: 10, minConfidence: 0.5, iouThreshold: 0.3, scoreThreshold: 0.5 },
|
||||
gesture: { enabled: true },
|
||||
};
|
||||
|
||||
|
@ -148,10 +148,8 @@ async function setupCamera() {
|
|||
const canvas = document.getElementById('canvas');
|
||||
const output = document.getElementById('log');
|
||||
const live = video.srcObject ? ((video.srcObject.getVideoTracks()[0].readyState === 'live') && (video.readyState > 2) && (!video.paused)) : false;
|
||||
let msg = `Setting up camera: live: ${live} facing: ${ui.facing ? 'front' : 'back'}`;
|
||||
let msg = '';
|
||||
status('starting camera');
|
||||
output.innerText += `\n${msg}`;
|
||||
log(msg);
|
||||
// setup webcam. note that navigator.mediaDevices requires that page is accessed via https
|
||||
if (!navigator.mediaDevices) {
|
||||
msg = 'camera access not supported';
|
||||
|
@ -182,6 +180,7 @@ async function setupCamera() {
|
|||
const track = stream.getVideoTracks()[0];
|
||||
const settings = track.getSettings();
|
||||
log('camera settings:', settings);
|
||||
log('camera track:', track);
|
||||
camera = { name: track.label, width: settings.width, height: settings.height, facing: settings.facingMode === 'user' ? 'front' : 'back' };
|
||||
return new Promise((resolve) => {
|
||||
video.onloadeddata = async () => {
|
||||
|
|
|
@ -13,10 +13,14 @@
|
|||
<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">
|
||||
<!-- <script src="../assets/tf.es2017.js"></script> -->
|
||||
<!-- <script src="../assets/tf-backend-wasm.es2017.js"></script> -->
|
||||
<!-- <script src="../assets/tf-backend-webgpu.js"></script> -->
|
||||
<script src="./browser.js" type="module"></script>
|
||||
<!-- 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.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 -->
|
||||
<!-- <script src="browser.js" type="module"></script> -->
|
||||
<style>
|
||||
body { margin: 0; background: black; color: white; font-family: 'Segoe UI'; font-size: 16px; font-variant: small-caps; overflow-x: hidden; scrollbar-width: none; }
|
||||
body::-webkit-scrollbar { display: none; }
|
||||
|
@ -39,6 +43,14 @@
|
|||
from { transform: rotate(0deg); }
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
.wave { position: fixed; top: 0; left: -90%; width: 100vw; height: 100vh; border-radius: 10%; opacity: .3; z-index: -1; }
|
||||
.wave.one { animation: rotate 10000ms infinite linear; background: #2F4F4F; }
|
||||
.wave.two { animation: rotate 15000ms infinite linear; background: #1F3F3F; }
|
||||
.wave.three { animation: rotate 20000ms infinite linear; background: #0F1F1F; }
|
||||
@keyframes rotate {
|
||||
from { transform: rotate(0deg); }
|
||||
from { transform: rotate(360deg); }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
@ -48,10 +60,17 @@
|
|||
<path d="M371.7 280l-176 101c-15.8 8.8-35.7-2.5-35.7-21V152c0-18.4 19.8-29.8 35.7-21l176 107c16.4 9.2 16.4 32.9 0 42z" class="play-foreground"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div id="background">
|
||||
<div class='wave one'></div>
|
||||
<div class='wave two'></div>
|
||||
<div class='wave three'></div>
|
||||
</div>
|
||||
<div id="loader" class="loader"></div>
|
||||
<div id="status" class="status"></div>
|
||||
<canvas id="canvas" class="canvas"></canvas>
|
||||
<video id="video" playsinline class="video"></video>
|
||||
<div id="media">
|
||||
<canvas id="canvas" class="canvas"></canvas>
|
||||
<video id="video" playsinline class="video"></video>
|
||||
</div>
|
||||
<div id="samples-container" class="samples-container"></div>
|
||||
<div id="log" class="log"></div>
|
||||
</body>
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,58 @@
|
|||
{
|
||||
"inputs": {
|
||||
"demo/browser.js": {
|
||||
"bytes": 17175,
|
||||
"imports": [
|
||||
{
|
||||
"path": "dist/human.esm.js"
|
||||
},
|
||||
{
|
||||
"path": "demo/draw.js"
|
||||
},
|
||||
{
|
||||
"path": "demo/menu.js"
|
||||
}
|
||||
]
|
||||
},
|
||||
"demo/draw.js": {
|
||||
"bytes": 7389,
|
||||
"imports": []
|
||||
},
|
||||
"demo/menu.js": {
|
||||
"bytes": 12354,
|
||||
"imports": []
|
||||
},
|
||||
"dist/human.esm.js": {
|
||||
"bytes": 1274644,
|
||||
"imports": []
|
||||
}
|
||||
},
|
||||
"outputs": {
|
||||
"dist/demo-browser-index.js.map": {
|
||||
"imports": [],
|
||||
"inputs": {},
|
||||
"bytes": 5506901
|
||||
},
|
||||
"dist/demo-browser-index.js": {
|
||||
"imports": [],
|
||||
"inputs": {
|
||||
"dist/human.esm.js": {
|
||||
"bytesInOutput": 1284484
|
||||
},
|
||||
"dist/human.esm.js": {
|
||||
"bytesInOutput": 0
|
||||
},
|
||||
"demo/draw.js": {
|
||||
"bytesInOutput": 4622
|
||||
},
|
||||
"demo/menu.js": {
|
||||
"bytesInOutput": 9476
|
||||
},
|
||||
"demo/browser.js": {
|
||||
"bytesInOutput": 10896
|
||||
}
|
||||
},
|
||||
"bytes": 1318242
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -5,7 +5,7 @@
|
|||
"imports": []
|
||||
},
|
||||
"package.json": {
|
||||
"bytes": 2989,
|
||||
"bytes": 3225,
|
||||
"imports": []
|
||||
},
|
||||
"src/emotion/emotion.js": {
|
||||
|
@ -106,7 +106,7 @@
|
|||
]
|
||||
},
|
||||
"src/handpose/handpose.js": {
|
||||
"bytes": 2772,
|
||||
"bytes": 2667,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/handpose/handdetector.js"
|
||||
|
@ -290,7 +290,7 @@
|
|||
"dist/human.esm-nobundle.js.map": {
|
||||
"imports": [],
|
||||
"inputs": {},
|
||||
"bytes": 610990
|
||||
"bytes": 610884
|
||||
},
|
||||
"dist/human.esm-nobundle.js": {
|
||||
"imports": [],
|
||||
|
@ -392,7 +392,7 @@
|
|||
"bytesInOutput": 1293
|
||||
},
|
||||
"package.json": {
|
||||
"bytesInOutput": 2641
|
||||
"bytesInOutput": 2871
|
||||
},
|
||||
"src/human.js": {
|
||||
"bytesInOutput": 5570
|
||||
|
@ -401,7 +401,7 @@
|
|||
"bytesInOutput": 0
|
||||
}
|
||||
},
|
||||
"bytes": 212868
|
||||
"bytes": 213098
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -149,7 +149,7 @@
|
|||
]
|
||||
},
|
||||
"package.json": {
|
||||
"bytes": 2989,
|
||||
"bytes": 3225,
|
||||
"imports": []
|
||||
},
|
||||
"src/emotion/emotion.js": {
|
||||
|
@ -277,7 +277,7 @@
|
|||
]
|
||||
},
|
||||
"src/handpose/handpose.js": {
|
||||
"bytes": 2772,
|
||||
"bytes": 2667,
|
||||
"imports": [
|
||||
{
|
||||
"path": "node_modules/@tensorflow/tfjs/dist/tf.node.js"
|
||||
|
@ -499,7 +499,7 @@
|
|||
"dist/human.esm.js.map": {
|
||||
"imports": [],
|
||||
"inputs": {},
|
||||
"bytes": 5406771
|
||||
"bytes": 5406665
|
||||
},
|
||||
"dist/human.esm.js": {
|
||||
"imports": [],
|
||||
|
@ -658,7 +658,7 @@
|
|||
"bytesInOutput": 1294
|
||||
},
|
||||
"package.json": {
|
||||
"bytesInOutput": 2642
|
||||
"bytesInOutput": 2872
|
||||
},
|
||||
"src/human.js": {
|
||||
"bytesInOutput": 5583
|
||||
|
@ -667,7 +667,7 @@
|
|||
"bytesInOutput": 0
|
||||
}
|
||||
},
|
||||
"bytes": 1274414
|
||||
"bytes": 1274644
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -149,7 +149,7 @@
|
|||
]
|
||||
},
|
||||
"package.json": {
|
||||
"bytes": 2989,
|
||||
"bytes": 3225,
|
||||
"imports": []
|
||||
},
|
||||
"src/emotion/emotion.js": {
|
||||
|
@ -277,7 +277,7 @@
|
|||
]
|
||||
},
|
||||
"src/handpose/handpose.js": {
|
||||
"bytes": 2772,
|
||||
"bytes": 2667,
|
||||
"imports": [
|
||||
{
|
||||
"path": "node_modules/@tensorflow/tfjs/dist/tf.node.js"
|
||||
|
@ -499,7 +499,7 @@
|
|||
"dist/human.js.map": {
|
||||
"imports": [],
|
||||
"inputs": {},
|
||||
"bytes": 5406767
|
||||
"bytes": 5406661
|
||||
},
|
||||
"dist/human.js": {
|
||||
"imports": [],
|
||||
|
@ -658,13 +658,13 @@
|
|||
"bytesInOutput": 1294
|
||||
},
|
||||
"package.json": {
|
||||
"bytesInOutput": 2641
|
||||
"bytesInOutput": 2871
|
||||
},
|
||||
"src/human.js": {
|
||||
"bytesInOutput": 5621
|
||||
}
|
||||
},
|
||||
"bytes": 1274459
|
||||
"bytes": 1274689
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -5,7 +5,7 @@
|
|||
"imports": []
|
||||
},
|
||||
"package.json": {
|
||||
"bytes": 2989,
|
||||
"bytes": 3225,
|
||||
"imports": []
|
||||
},
|
||||
"src/emotion/emotion.js": {
|
||||
|
@ -106,7 +106,7 @@
|
|||
]
|
||||
},
|
||||
"src/handpose/handpose.js": {
|
||||
"bytes": 2772,
|
||||
"bytes": 2667,
|
||||
"imports": [
|
||||
{
|
||||
"path": "src/handpose/handdetector.js"
|
||||
|
@ -290,7 +290,7 @@
|
|||
"dist/human.node-nobundle.js.map": {
|
||||
"imports": [],
|
||||
"inputs": {},
|
||||
"bytes": 622505
|
||||
"bytes": 622399
|
||||
},
|
||||
"dist/human.node-nobundle.js": {
|
||||
"imports": [],
|
||||
|
@ -392,7 +392,7 @@
|
|||
"bytesInOutput": 1292
|
||||
},
|
||||
"package.json": {
|
||||
"bytesInOutput": 2641
|
||||
"bytesInOutput": 2871
|
||||
},
|
||||
"src/human.js": {
|
||||
"bytesInOutput": 28
|
||||
|
@ -401,7 +401,7 @@
|
|||
"bytesInOutput": 5570
|
||||
}
|
||||
},
|
||||
"bytes": 212875
|
||||
"bytes": 213105
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@vladmandic/human",
|
||||
"version": "0.6.7",
|
||||
"version": "0.7.0",
|
||||
"description": "human: 3D Face Detection, Body Pose, Hand & Finger Tracking, Iris Tracking, Age & Gender Prediction, Emotion Prediction & Gesture Recognition",
|
||||
"sideEffects": false,
|
||||
"main": "dist/human.node.js",
|
||||
|
@ -45,7 +45,8 @@
|
|||
"build-esm-nobundle": "esbuild --bundle --minify --platform=browser --sourcemap --target=esnext --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=esnext --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=esnext --format=cjs --external:@tensorflow --metafile=dist/human.node.json --outfile=dist/human.node-nobundle.js src/human.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 && ls -l dist/",
|
||||
"build-demo": "esbuild --bundle --minify --platform=browser --sourcemap --target=esnext --format=esm --external:fs --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 && ls -l dist/",
|
||||
"update": "npm update --depth 20 --force && npm dedupe && npm prune && npm audit",
|
||||
"changelog": "node changelog.js"
|
||||
},
|
||||
|
|
|
@ -59,7 +59,6 @@ class HandPose {
|
|||
exports.HandPose = HandPose;
|
||||
|
||||
async function load(config) {
|
||||
// maxContinuousChecks = Infinity, detectionConfidence = 0.8, iouThreshold = 0.3, scoreThreshold = 0.5
|
||||
const [handDetectorModel, handPoseModel] = await Promise.all([
|
||||
tf.loadGraphModel(config.detector.modelPath, { fromTFHub: config.detector.modelPath.includes('tfhub.dev') }),
|
||||
tf.loadGraphModel(config.skeleton.modelPath, { fromTFHub: config.skeleton.modelPath.includes('tfhub.dev') }),
|
||||
|
|
Loading…
Reference in New Issue