mirror of https://github.com/vladmandic/human
fix wasm detection
parent
554ed81f49
commit
6fc26e793c
|
@ -11,9 +11,8 @@
|
|||
|
||||
### **HEAD -> main** 2022/08/12 mandic00@live.com
|
||||
|
||||
|
||||
### **origin/main** 2022/08/10 mandic00@live.com
|
||||
|
||||
- enumerate additional models
|
||||
- release refresh
|
||||
|
||||
### **2.9.3** 2022/08/10 mandic00@live.com
|
||||
|
||||
|
|
7
TODO.md
7
TODO.md
|
@ -57,6 +57,8 @@ Model is supported using `WebGL` backend in browser
|
|||
Models can be downloaded from <https://github.com/vladmandic/insightface>
|
||||
- Add `human.check()` which validates all kernel ops for currently loaded models with currently selected backend
|
||||
Example: `console.error(human.check());`
|
||||
- Add underlying tensorflow library version detection to `human.env`
|
||||
Example: `console.log(human.env.tensorflow)`
|
||||
- Host models in <human-models>
|
||||
Models can be directly used without downloading to local storage
|
||||
Example: `modelPath: 'https://vladmandic.github.io/human-models/models/facemesh.json'`
|
||||
|
@ -69,10 +71,11 @@ Model is supported using `WebGL` backend in browser
|
|||
- Fix **NanoDet** module as alternative object detection
|
||||
- Fix `demo/multithread/node-multiprocess.js` demo
|
||||
- Fix `human.match` when using mixed descriptor lengths
|
||||
- Fix WASM feature detection issue in TFJS with Edge/Chromium
|
||||
- Increased test coverage
|
||||
Run using `npm run test`
|
||||
**NodeJS**: Run using `npm run test`
|
||||
**Browser**: Run using `demo/browser.html`
|
||||
- Increase availability of alternative models
|
||||
See `models/model.json` for full list
|
||||
- Update **NMS** methods resulting in some performance improvements
|
||||
- Update profiling methods in `human.profile()`
|
||||
- Update project dependencies
|
||||
|
|
|
@ -79,7 +79,7 @@
|
|||
"@tensorflow/tfjs-node": "^3.19.0",
|
||||
"@tensorflow/tfjs-node-gpu": "^3.19.0",
|
||||
"@tensorflow/tfjs-tflite": "0.0.1-alpha.8",
|
||||
"@types/node": "^18.7.2",
|
||||
"@types/node": "^18.7.4",
|
||||
"@types/offscreencanvas": "^2019.7.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.33.0",
|
||||
"@typescript-eslint/parser": "^5.33.0",
|
||||
|
@ -87,8 +87,8 @@
|
|||
"@vladmandic/pilogger": "^0.4.6",
|
||||
"@vladmandic/tfjs": "github:vladmandic/tfjs",
|
||||
"@webgpu/types": "^0.1.21",
|
||||
"esbuild": "^0.15.1",
|
||||
"eslint": "8.21.0",
|
||||
"esbuild": "^0.15.3",
|
||||
"eslint": "8.22.0",
|
||||
"eslint-config-airbnb-base": "^15.0.0",
|
||||
"eslint-plugin-html": "^7.1.0",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
|
|
|
@ -71,7 +71,7 @@ export async function decode(boxesTensor: Tensor, logitsTensor: Tensor, config:
|
|||
detected.push({ box, boxRaw, score: scores[i] });
|
||||
}
|
||||
/*
|
||||
t.nms = tf.image.nonMaxSuppression(t.boxes, t.scores, 1, config.body.detector?.minConfidence || 0.1, config.body.detector?.iouThreshold || 0.1);
|
||||
t.nms = await tf.image.nonMaxSuppressionAsync(t.boxes, t.scores, 1, config.body.detector?.minConfidence || 0.1, config.body.detector?.iouThreshold || 0.1);
|
||||
const boxes = t.boxes.arraySync();
|
||||
const scores = t.scores.dataSync();
|
||||
const nms = t.nms.dataSync();
|
||||
|
|
|
@ -75,7 +75,7 @@ export async function getBoxes(inputImage: Tensor, config: Config) {
|
|||
t.logits = tf.slice(t.batch, [0, 0], [-1, 1]);
|
||||
t.sigmoid = tf.sigmoid(t.logits);
|
||||
t.scores = tf.squeeze(t.sigmoid);
|
||||
t.nms = tf.image.nonMaxSuppression(t.boxes, t.scores, (config.face.detector?.maxDetected || 0), (config.face.detector?.iouThreshold || 0), (config.face.detector?.minConfidence || 0));
|
||||
t.nms = await tf.image.nonMaxSuppressionAsync(t.boxes, t.scores, (config.face.detector?.maxDetected || 0), (config.face.detector?.iouThreshold || 0), (config.face.detector?.minConfidence || 0));
|
||||
const nms = await t.nms.array() as number[];
|
||||
const boxes: Array<DetectBox> = [];
|
||||
const scores = await t.scores.data();
|
||||
|
|
|
@ -67,7 +67,7 @@ export class HandDetector {
|
|||
t.boxes = tf.slice(t.predictions, [0, 1], [-1, 4]);
|
||||
t.norm = this.normalizeBoxes(t.boxes);
|
||||
// box detection is flaky so we look for 3x boxes than we need results
|
||||
t.nms = tf.image.nonMaxSuppression(t.norm, t.scores, 3 * config.hand.maxDetected, config.hand.iouThreshold, config.hand.minConfidence);
|
||||
t.nms = await tf.image.nonMaxSuppressionAsync(t.norm, t.scores, 3 * config.hand.maxDetected, config.hand.iouThreshold, config.hand.minConfidence);
|
||||
const nms = await t.nms.array() as Array<number>;
|
||||
const hands: Array<{ startPoint: Point; endPoint: Point; palmLandmarks: Point[]; confidence: number }> = [];
|
||||
for (const index of nms) {
|
||||
|
|
|
@ -121,7 +121,7 @@ async function detectHands(input: Tensor, config: Config): Promise<HandDetectRes
|
|||
t.max = tf.max(t.filtered, 1); // max overall score
|
||||
t.argmax = tf.argMax(t.filtered, 1); // class index of max overall score
|
||||
let id = 0;
|
||||
t.nms = tf.image.nonMaxSuppression(t.boxes, t.max, (config.hand.maxDetected || 0) + 1, config.hand.iouThreshold || 0, config.hand.minConfidence || 1);
|
||||
t.nms = await tf.image.nonMaxSuppressionAsync(t.boxes, t.max, (config.hand.maxDetected || 0) + 1, config.hand.iouThreshold || 0, config.hand.minConfidence || 1);
|
||||
const nms = await t.nms.data();
|
||||
const scores = await t.max.data();
|
||||
const classNum = await t.argmax.data();
|
||||
|
|
|
@ -42,7 +42,7 @@ async function process(res: Tensor | null, outputShape: [number, number], config
|
|||
t.scores = tf.squeeze(arr[4]);
|
||||
t.classes = tf.squeeze(arr[5]);
|
||||
tf.dispose([res, ...arr]);
|
||||
t.nms = tf.image.nonMaxSuppression(t.boxes, t.scores, config.object.maxDetected, config.object.iouThreshold, (config.object.minConfidence || 0));
|
||||
t.nms = await tf.image.nonMaxSuppressionAsync(t.boxes, t.scores, config.object.maxDetected, config.object.iouThreshold, (config.object.minConfidence || 0));
|
||||
const nms = await t.nms.data();
|
||||
let i = 0;
|
||||
for (const id of Array.from(nms)) {
|
||||
|
|
|
@ -91,7 +91,7 @@ async function process(res: Tensor[], outputShape: [number, number], config: Con
|
|||
const nmsScores = results.map((a) => a.score);
|
||||
let nmsIdx: Array<number> = [];
|
||||
if (nmsBoxes && nmsBoxes.length > 0) {
|
||||
const nms = tf.image.nonMaxSuppression(nmsBoxes, nmsScores, config.object.maxDetected, config.object.iouThreshold, config.object.minConfidence);
|
||||
const nms = await tf.image.nonMaxSuppressionAsync(nmsBoxes, nmsScores, config.object.maxDetected, config.object.iouThreshold, config.object.minConfidence);
|
||||
nmsIdx = await nms.data();
|
||||
tf.dispose(nms);
|
||||
}
|
||||
|
|
|
@ -90,10 +90,16 @@ export async function check(instance: Human, force = false) {
|
|||
if (instance.config.debug) log('wasm path:', instance.config.wasmPath);
|
||||
if (typeof tf?.setWasmPaths !== 'undefined') await tf.setWasmPaths(instance.config.wasmPath, instance.config.wasmPlatformFetch);
|
||||
else throw new Error('backend error: attempting to use wasm backend but wasm path is not set');
|
||||
const simd = await tf.env().getAsync('WASM_HAS_SIMD_SUPPORT');
|
||||
const mt = await tf.env().getAsync('WASM_HAS_MULTITHREAD_SUPPORT');
|
||||
if (instance.config.debug) log(`wasm execution: ${simd ? 'SIMD' : 'no SIMD'} ${mt ? 'multithreaded' : 'singlethreaded'}`);
|
||||
if (instance.config.debug && !simd) log('warning: wasm simd support is not enabled');
|
||||
let mt = false;
|
||||
let simd = false;
|
||||
try {
|
||||
mt = await tf.env().getAsync('WASM_HAS_MULTITHREAD_SUPPORT');
|
||||
simd = await tf.env().getAsync('WASM_HAS_SIMD_SUPPORT');
|
||||
if (instance.config.debug) log(`wasm execution: ${simd ? 'simd' : 'no simd'} ${mt ? 'multithreaded' : 'singlethreaded'}`);
|
||||
if (instance.config.debug && !simd) log('warning: wasm simd support is not enabled');
|
||||
} catch {
|
||||
log('wasm detection failed');
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
|
@ -27,6 +27,10 @@ export class Env {
|
|||
offscreen: undefined | boolean;
|
||||
/** Are performance counter instant values or additive */
|
||||
perfadd: boolean = false;
|
||||
/** If using tfjs-node get version of underlying tensorflow shared library */
|
||||
tensorflow: {
|
||||
version: undefined | string,
|
||||
} = { version: undefined };
|
||||
/** WASM detected capabilities */
|
||||
wasm: {
|
||||
supported: undefined | boolean,
|
||||
|
@ -84,6 +88,7 @@ export class Env {
|
|||
this.tfjs = { version: tf.version['tfjs-core'] };
|
||||
this.offscreen = typeof OffscreenCanvas !== 'undefined';
|
||||
this.initial = true;
|
||||
|
||||
// @ts-ignore WorkerGlobalScope evaluated in browser only
|
||||
this.worker = this.browser && this.offscreen ? (typeof WorkerGlobalScope !== 'undefined') : undefined;
|
||||
if (typeof navigator !== 'undefined') {
|
||||
|
@ -114,6 +119,7 @@ export class Env {
|
|||
async updateBackend() {
|
||||
// analyze backends
|
||||
this.backends = Object.keys(tf.engine().registryFactory);
|
||||
this.tensorflow = { version: (tf.backend()['binding'] ? tf.backend()['binding']['TF_Version'] : undefined) };
|
||||
this.wasm.supported = typeof WebAssembly !== 'undefined';
|
||||
this.wasm.backend = this.backends.includes('wasm');
|
||||
if (this.wasm.supported && this.wasm.backend && tf.getBackend() === 'wasm') {
|
||||
|
|
|
@ -13,9 +13,9 @@
|
|||
<style>
|
||||
@font-face { font-family: 'Lato'; font-display: swap; font-style: normal; font-weight: 100; src: local('Lato'), url('../../assets/lato-light.woff2') }
|
||||
html { font-family: 'Lato', 'Segoe UI'; font-size: 14px; font-variant: small-caps; }
|
||||
body { margin: 0; background: black; color: white; }
|
||||
body { margin: 0; background: black; color: white; width: 100vw; overflow-x: hidden; }
|
||||
.canvas { position: absolute; bottom: 10px; right: 10px; width: 256px; height: 256px; z-index: 99; }
|
||||
.pre { line-height: 150%; }
|
||||
.pre { line-height: 150%; white-space: break-spaces; }
|
||||
.events { position: absolute; top: 10px; right: 10px; width: 12rem; height: 1.25rem; background-color: grey; padding: 8px; z-index: 99; }
|
||||
.state { position: absolute; top: 60px; right: 10px; width: 12rem; height: 1.25rem; background-color: grey; padding: 8px; z-index: 99; }
|
||||
</style>
|
||||
|
@ -36,16 +36,16 @@
|
|||
object: { enabled: true },
|
||||
};
|
||||
|
||||
const backends = ['wasm', 'webgl', 'humangl', 'webgpu'];
|
||||
const backends = ['wasm', 'humangl', 'webgl', 'webgpu'];
|
||||
|
||||
const start = performance.now();
|
||||
|
||||
function str(...msg) {
|
||||
function str(long, ...msg) {
|
||||
if (!Array.isArray(msg)) return msg;
|
||||
let line = '';
|
||||
for (const entry of msg) {
|
||||
if (typeof entry === 'object') line += JSON.stringify(entry).replace(/"/g, '').replace(/,/g, ', ').replace(/:/g, ': ');
|
||||
else line += entry;
|
||||
if (typeof entry === 'object') line += ' ' + JSON.stringify(entry, null, long ? 2 : 0).replace(/"/g, '').replace(/,/g, ', ').replace(/:/g, ': ');
|
||||
else line += ' ' + entry;
|
||||
}
|
||||
return line + '\n';
|
||||
}
|
||||
|
@ -55,9 +55,19 @@
|
|||
const dt = new Date();
|
||||
const ts = `${dt.getHours().toString().padStart(2, '0')}:${dt.getMinutes().toString().padStart(2, '0')}:${dt.getSeconds().toString().padStart(2, '0')}.${dt.getMilliseconds().toString().padStart(3, '0')}`;
|
||||
const elap = (dt - last).toString().padStart(5, '0');
|
||||
document.getElementById('log').innerHTML += ts + ' +' + elap + 'ms  ' + str(...msgs);
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(ts, elap, ...msgs);
|
||||
document.getElementById('log').innerHTML += ts + ' +' + elap + 'ms  ' + str(false, ...msgs);
|
||||
document.documentElement.scrollTop = document.documentElement.scrollHeight
|
||||
console.log(ts, elap, ...msgs); // eslint-disable-line no-console
|
||||
last = dt;
|
||||
}
|
||||
|
||||
async function detailed(...msgs) {
|
||||
const dt = new Date();
|
||||
const ts = `${dt.getHours().toString().padStart(2, '0')}:${dt.getMinutes().toString().padStart(2, '0')}:${dt.getSeconds().toString().padStart(2, '0')}.${dt.getMilliseconds().toString().padStart(3, '0')}`;
|
||||
const elap = (dt - last).toString().padStart(5, '0');
|
||||
document.getElementById('log').innerHTML += ts + ' +' + elap + 'ms  ' + str(true, ...msgs);
|
||||
document.documentElement.scrollTop = document.documentElement.scrollHeight
|
||||
console.log(ts, elap, ...msgs); // eslint-disable-line no-console
|
||||
last = dt;
|
||||
}
|
||||
|
||||
|
@ -95,37 +105,44 @@
|
|||
human.events.addEventListener('image', () => events('image'));
|
||||
human.events.addEventListener('detect', () => events('detect'));
|
||||
const timer = setInterval(() => { document.getElementById('state').innerText = `State: ${human.state}`; }, 10);
|
||||
log({ version: human.version });
|
||||
log({ tfjs: human.tf.version.tfjs });
|
||||
log({ environment: human.env });
|
||||
log({ config: human.config });
|
||||
log('version', human.version);
|
||||
log('tfjs', human.tf.version.tfjs);
|
||||
|
||||
const env = JSON.parse(JSON.stringify(human.env));
|
||||
env.kernels = human.env.kernels.length;
|
||||
detailed('environment', env);
|
||||
|
||||
detailed('config', human.config);
|
||||
await human.load();
|
||||
const models = Object.keys(human.models).map((model) => ({ name: model, loaded: (human.models[model] !== null) }));
|
||||
log({ models });
|
||||
log('models', models);
|
||||
for (const backend of backends) {
|
||||
log();
|
||||
log('test start:', backend);
|
||||
human.config.backend = backend;
|
||||
await human.init();
|
||||
log({ initialized: human.tf.getBackend() });
|
||||
log({ memory: human.tf.memory() });
|
||||
log('desired', backend, 'detected', human.tf.getBackend());
|
||||
if (human.tf.getBackend() !== backend) {
|
||||
continue;
|
||||
}
|
||||
log('memory', human.tf.memory());
|
||||
res = await human.validate();
|
||||
log({ validate: res });
|
||||
log('validate', res);
|
||||
res = await human.warmup({ warmup: 'face' });
|
||||
draw(res.canvas);
|
||||
log({ warmup: 'face' });
|
||||
log('warmup', 'face');
|
||||
let img = await image('../../samples/in/ai-body.jpg');
|
||||
const input = await human.image(img);
|
||||
log({ input: input.tensor.shape });
|
||||
log('input', input.tensor.shape);
|
||||
draw(res.canvas);
|
||||
res = await human.detect(input.tensor);
|
||||
log({ detect: true });
|
||||
log('detect');
|
||||
human.next();
|
||||
log({ interpolated: true });
|
||||
log('interpolate');
|
||||
const persons = res.persons;
|
||||
log({ persons: true });
|
||||
log({ summary: { persons: persons.length, face: res.face.length, body: res.body.length, hand: res.hand.length, object: res.object.length, gesture: res.gesture.length } });
|
||||
log({ performance: human.performance });
|
||||
log('persons');
|
||||
log('summary', { persons: persons.length, face: res.face.length, body: res.body.length, hand: res.hand.length, object: res.object.length, gesture: res.gesture.length });
|
||||
log('performance', human.performance);
|
||||
human.tf.dispose(input.tensor);
|
||||
draw();
|
||||
|
||||
|
@ -138,12 +155,12 @@
|
|||
draw(res.canvas);
|
||||
}
|
||||
const t1 = performance.now();
|
||||
log({ benchmark: { time: Math.round((t1 - t0) / 10), cacheSensitivity: val }, performance: human.performance });
|
||||
log('benchmark', { time: Math.round((t1 - t0) / 10), cacheSensitivity: val, performance: human.performance });
|
||||
await wait(10);
|
||||
}
|
||||
draw();
|
||||
|
||||
log({ memory: human.tf.memory() });
|
||||
log('memory', human.tf.memory());
|
||||
}
|
||||
clearInterval(timer);
|
||||
log();
|
||||
|
|
|
@ -1,39 +1,39 @@
|
|||
2022-08-12 09:50:24 [32mDATA: [39m Build {"name":"@vladmandic/human","version":"2.9.3"}
|
||||
2022-08-12 09:50:24 [36mINFO: [39m Application: {"name":"@vladmandic/human","version":"2.9.3"}
|
||||
2022-08-12 09:50:24 [36mINFO: [39m Environment: {"profile":"production","config":".build.json","package":"package.json","tsconfig":true,"eslintrc":true,"git":true}
|
||||
2022-08-12 09:50:24 [36mINFO: [39m Toolchain: {"build":"0.7.9","esbuild":"0.15.1","typescript":"4.7.4","typedoc":"0.23.10","eslint":"8.21.0"}
|
||||
2022-08-12 09:50:24 [36mINFO: [39m Build: {"profile":"production","steps":["clean","compile","typings","typedoc","lint","changelog"]}
|
||||
2022-08-12 09:50:24 [35mSTATE:[39m Clean: {"locations":["dist/*","types/lib/*","typedoc/*"]}
|
||||
2022-08-12 09:50:24 [35mSTATE:[39m Compile: {"name":"tfjs/nodejs/cpu","format":"cjs","platform":"node","input":"tfjs/tf-node.ts","output":"dist/tfjs.esm.js","files":1,"inputBytes":102,"outputBytes":608}
|
||||
2022-08-12 09:50:24 [35mSTATE:[39m Compile: {"name":"human/nodejs/cpu","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node.js","files":75,"inputBytes":654779,"outputBytes":307161}
|
||||
2022-08-12 09:50:24 [35mSTATE:[39m Compile: {"name":"tfjs/nodejs/gpu","format":"cjs","platform":"node","input":"tfjs/tf-node-gpu.ts","output":"dist/tfjs.esm.js","files":1,"inputBytes":110,"outputBytes":612}
|
||||
2022-08-12 09:50:24 [35mSTATE:[39m Compile: {"name":"human/nodejs/gpu","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node-gpu.js","files":75,"inputBytes":654783,"outputBytes":307165}
|
||||
2022-08-12 09:50:24 [35mSTATE:[39m Compile: {"name":"tfjs/nodejs/wasm","format":"cjs","platform":"node","input":"tfjs/tf-node-wasm.ts","output":"dist/tfjs.esm.js","files":1,"inputBytes":149,"outputBytes":664}
|
||||
2022-08-12 09:50:24 [35mSTATE:[39m Compile: {"name":"human/nodejs/wasm","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node-wasm.js","files":75,"inputBytes":654835,"outputBytes":307215}
|
||||
2022-08-12 09:50:24 [35mSTATE:[39m Compile: {"name":"tfjs/browser/version","format":"esm","platform":"browser","input":"tfjs/tf-version.ts","output":"dist/tfjs.version.js","files":1,"inputBytes":1069,"outputBytes":358}
|
||||
2022-08-12 09:50:24 [35mSTATE:[39m Compile: {"name":"tfjs/browser/esm/nobundle","format":"esm","platform":"browser","input":"tfjs/tf-browser.ts","output":"dist/tfjs.esm.js","files":2,"inputBytes":1032,"outputBytes":583}
|
||||
2022-08-12 09:50:24 [35mSTATE:[39m Compile: {"name":"human/browser/esm/nobundle","format":"esm","platform":"browser","input":"src/human.ts","output":"dist/human.esm-nobundle.js","files":75,"inputBytes":654754,"outputBytes":306014}
|
||||
2022-08-12 09:50:24 [35mSTATE:[39m Compile: {"name":"tfjs/browser/esm/custom","format":"esm","platform":"browser","input":"tfjs/tf-custom.ts","output":"dist/tfjs.esm.js","files":11,"inputBytes":1271,"outputBytes":2787569}
|
||||
2022-08-12 09:50:24 [35mSTATE:[39m Compile: {"name":"human/browser/iife/bundle","format":"iife","platform":"browser","input":"src/human.ts","output":"dist/human.js","files":75,"inputBytes":3441740,"outputBytes":1668900}
|
||||
2022-08-12 09:50:24 [35mSTATE:[39m Compile: {"name":"human/browser/esm/bundle","format":"esm","platform":"browser","input":"src/human.ts","output":"dist/human.esm.js","files":75,"inputBytes":3441740,"outputBytes":3072630}
|
||||
2022-08-12 09:50:31 [35mSTATE:[39m Typings: {"input":"src/human.ts","output":"types/lib","files":30}
|
||||
2022-08-12 09:50:33 [35mSTATE:[39m TypeDoc: {"input":"src/human.ts","output":"typedoc","objects":77,"generated":true}
|
||||
2022-08-12 09:50:33 [35mSTATE:[39m Compile: {"name":"demo/typescript","format":"esm","platform":"browser","input":"demo/typescript/index.ts","output":"demo/typescript/index.js","files":1,"inputBytes":6716,"outputBytes":3141}
|
||||
2022-08-12 09:50:33 [35mSTATE:[39m Compile: {"name":"demo/faceid","format":"esm","platform":"browser","input":"demo/faceid/index.ts","output":"demo/faceid/index.js","files":2,"inputBytes":15629,"outputBytes":7798}
|
||||
2022-08-12 09:50:42 [35mSTATE:[39m Lint: {"locations":["*.json","src/**/*.ts","test/**/*.js","demo/**/*.js"],"files":109,"errors":0,"warnings":0}
|
||||
2022-08-12 09:50:42 [35mSTATE:[39m ChangeLog: {"repository":"https://github.com/vladmandic/human","branch":"main","output":"CHANGELOG.md"}
|
||||
2022-08-12 09:50:42 [35mSTATE:[39m Copy: {"input":"tfjs/tfjs.esm.d.ts"}
|
||||
2022-08-12 09:50:42 [36mINFO: [39m Done...
|
||||
2022-08-12 09:50:42 [35mSTATE:[39m API-Extractor: {"succeeeded":true,"errors":0,"warnings":198}
|
||||
2022-08-12 09:50:42 [35mSTATE:[39m Copy: {"input":"types/human.d.ts"}
|
||||
2022-08-12 09:50:42 [36mINFO: [39m Analyze models: {"folders":8,"result":"models/models.json"}
|
||||
2022-08-12 09:50:42 [35mSTATE:[39m Models {"folder":"./models","models":13}
|
||||
2022-08-12 09:50:42 [35mSTATE:[39m Models {"folder":"../human-models/models","models":42}
|
||||
2022-08-12 09:50:42 [35mSTATE:[39m Models {"folder":"../blazepose/model/","models":4}
|
||||
2022-08-12 09:50:42 [35mSTATE:[39m Models {"folder":"../anti-spoofing/model","models":1}
|
||||
2022-08-12 09:50:42 [35mSTATE:[39m Models {"folder":"../efficientpose/models","models":3}
|
||||
2022-08-12 09:50:42 [35mSTATE:[39m Models {"folder":"../insightface/models","models":5}
|
||||
2022-08-12 09:50:42 [35mSTATE:[39m Models {"folder":"../movenet/models","models":3}
|
||||
2022-08-12 09:50:42 [35mSTATE:[39m Models {"folder":"../nanodet/models","models":4}
|
||||
2022-08-12 09:50:43 [35mSTATE:[39m Models: {"count":57,"totalSize":383017442}
|
||||
2022-08-12 09:50:43 [36mINFO: [39m Human Build complete... {"logFile":"test/build.log"}
|
||||
2022-08-15 11:28:08 [32mDATA: [39m Build {"name":"@vladmandic/human","version":"2.9.3"}
|
||||
2022-08-15 11:28:08 [36mINFO: [39m Application: {"name":"@vladmandic/human","version":"2.9.3"}
|
||||
2022-08-15 11:28:08 [36mINFO: [39m Environment: {"profile":"production","config":".build.json","package":"package.json","tsconfig":true,"eslintrc":true,"git":true}
|
||||
2022-08-15 11:28:08 [36mINFO: [39m Toolchain: {"build":"0.7.9","esbuild":"0.15.3","typescript":"4.7.4","typedoc":"0.23.10","eslint":"8.22.0"}
|
||||
2022-08-15 11:28:08 [36mINFO: [39m Build: {"profile":"production","steps":["clean","compile","typings","typedoc","lint","changelog"]}
|
||||
2022-08-15 11:28:08 [35mSTATE:[39m Clean: {"locations":["dist/*","types/lib/*","typedoc/*"]}
|
||||
2022-08-15 11:28:08 [35mSTATE:[39m Compile: {"name":"tfjs/nodejs/cpu","format":"cjs","platform":"node","input":"tfjs/tf-node.ts","output":"dist/tfjs.esm.js","files":1,"inputBytes":102,"outputBytes":608}
|
||||
2022-08-15 11:28:08 [35mSTATE:[39m Compile: {"name":"human/nodejs/cpu","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node.js","files":75,"inputBytes":655247,"outputBytes":307391}
|
||||
2022-08-15 11:28:08 [35mSTATE:[39m Compile: {"name":"tfjs/nodejs/gpu","format":"cjs","platform":"node","input":"tfjs/tf-node-gpu.ts","output":"dist/tfjs.esm.js","files":1,"inputBytes":110,"outputBytes":612}
|
||||
2022-08-15 11:28:08 [35mSTATE:[39m Compile: {"name":"human/nodejs/gpu","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node-gpu.js","files":75,"inputBytes":655251,"outputBytes":307395}
|
||||
2022-08-15 11:28:08 [35mSTATE:[39m Compile: {"name":"tfjs/nodejs/wasm","format":"cjs","platform":"node","input":"tfjs/tf-node-wasm.ts","output":"dist/tfjs.esm.js","files":1,"inputBytes":149,"outputBytes":664}
|
||||
2022-08-15 11:28:08 [35mSTATE:[39m Compile: {"name":"human/nodejs/wasm","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node-wasm.js","files":75,"inputBytes":655303,"outputBytes":307445}
|
||||
2022-08-15 11:28:08 [35mSTATE:[39m Compile: {"name":"tfjs/browser/version","format":"esm","platform":"browser","input":"tfjs/tf-version.ts","output":"dist/tfjs.version.js","files":1,"inputBytes":1069,"outputBytes":358}
|
||||
2022-08-15 11:28:08 [35mSTATE:[39m Compile: {"name":"tfjs/browser/esm/nobundle","format":"esm","platform":"browser","input":"tfjs/tf-browser.ts","output":"dist/tfjs.esm.js","files":2,"inputBytes":1032,"outputBytes":583}
|
||||
2022-08-15 11:28:08 [35mSTATE:[39m Compile: {"name":"human/browser/esm/nobundle","format":"esm","platform":"browser","input":"src/human.ts","output":"dist/human.esm-nobundle.js","files":75,"inputBytes":655222,"outputBytes":306242}
|
||||
2022-08-15 11:28:09 [35mSTATE:[39m Compile: {"name":"tfjs/browser/esm/custom","format":"esm","platform":"browser","input":"tfjs/tf-custom.ts","output":"dist/tfjs.esm.js","files":11,"inputBytes":1271,"outputBytes":2787569}
|
||||
2022-08-15 11:28:09 [35mSTATE:[39m Compile: {"name":"human/browser/iife/bundle","format":"iife","platform":"browser","input":"src/human.ts","output":"dist/human.js","files":75,"inputBytes":3442208,"outputBytes":1669116}
|
||||
2022-08-15 11:28:09 [35mSTATE:[39m Compile: {"name":"human/browser/esm/bundle","format":"esm","platform":"browser","input":"src/human.ts","output":"dist/human.esm.js","files":75,"inputBytes":3442208,"outputBytes":3072985}
|
||||
2022-08-15 11:28:14 [35mSTATE:[39m Typings: {"input":"src/human.ts","output":"types/lib","files":30}
|
||||
2022-08-15 11:28:15 [35mSTATE:[39m TypeDoc: {"input":"src/human.ts","output":"typedoc","objects":77,"generated":true}
|
||||
2022-08-15 11:28:15 [35mSTATE:[39m Compile: {"name":"demo/typescript","format":"esm","platform":"browser","input":"demo/typescript/index.ts","output":"demo/typescript/index.js","files":1,"inputBytes":6716,"outputBytes":3141}
|
||||
2022-08-15 11:28:15 [35mSTATE:[39m Compile: {"name":"demo/faceid","format":"esm","platform":"browser","input":"demo/faceid/index.ts","output":"demo/faceid/index.js","files":2,"inputBytes":15629,"outputBytes":7798}
|
||||
2022-08-15 11:28:24 [35mSTATE:[39m Lint: {"locations":["*.json","src/**/*.ts","test/**/*.js","demo/**/*.js"],"files":109,"errors":0,"warnings":0}
|
||||
2022-08-15 11:28:24 [35mSTATE:[39m ChangeLog: {"repository":"https://github.com/vladmandic/human","branch":"main","output":"CHANGELOG.md"}
|
||||
2022-08-15 11:28:24 [35mSTATE:[39m Copy: {"input":"tfjs/tfjs.esm.d.ts"}
|
||||
2022-08-15 11:28:24 [36mINFO: [39m Done...
|
||||
2022-08-15 11:28:24 [35mSTATE:[39m API-Extractor: {"succeeeded":true,"errors":0,"warnings":198}
|
||||
2022-08-15 11:28:24 [35mSTATE:[39m Copy: {"input":"types/human.d.ts"}
|
||||
2022-08-15 11:28:24 [36mINFO: [39m Analyze models: {"folders":8,"result":"models/models.json"}
|
||||
2022-08-15 11:28:24 [35mSTATE:[39m Models {"folder":"./models","models":13}
|
||||
2022-08-15 11:28:24 [35mSTATE:[39m Models {"folder":"../human-models/models","models":42}
|
||||
2022-08-15 11:28:24 [35mSTATE:[39m Models {"folder":"../blazepose/model/","models":4}
|
||||
2022-08-15 11:28:24 [35mSTATE:[39m Models {"folder":"../anti-spoofing/model","models":1}
|
||||
2022-08-15 11:28:24 [35mSTATE:[39m Models {"folder":"../efficientpose/models","models":3}
|
||||
2022-08-15 11:28:24 [35mSTATE:[39m Models {"folder":"../insightface/models","models":5}
|
||||
2022-08-15 11:28:24 [35mSTATE:[39m Models {"folder":"../movenet/models","models":3}
|
||||
2022-08-15 11:28:24 [35mSTATE:[39m Models {"folder":"../nanodet/models","models":4}
|
||||
2022-08-15 11:28:25 [35mSTATE:[39m Models: {"count":57,"totalSize":383017442}
|
||||
2022-08-15 11:28:25 [36mINFO: [39m Human Build complete... {"logFile":"test/build.log"}
|
||||
|
|
|
@ -5,7 +5,7 @@ const { fork } = require('child_process');
|
|||
const log = require('@vladmandic/pilogger');
|
||||
|
||||
let logFile = 'test.log';
|
||||
log.configure({ inspect: { breakLength: 500 } });
|
||||
log.configure({ inspect: { breakLength: 350 } });
|
||||
|
||||
const tests = [
|
||||
'test-node.js',
|
||||
|
|
|
@ -12,7 +12,8 @@ const log = (status, ...data) => {
|
|||
};
|
||||
|
||||
process.on('uncaughtException', (err) => {
|
||||
log('error', 'uncaughtException', lastOp, err);
|
||||
log('error', 'uncaughtException', lastOp, err); // abort immediately
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
async function testHTTP() {
|
||||
|
@ -74,12 +75,17 @@ async function testInstance(human) {
|
|||
log('info', 'human version:', human.version);
|
||||
log('info', 'platform:', human.env.platform, 'agent:', human.env.agent);
|
||||
log('info', 'tfjs version:', human.tf.version.tfjs);
|
||||
const bindingVer = human.tf.backend()['binding'] ? human.tf.backend()['binding']['TF_Version'] : null;
|
||||
if (bindingVer) log('info', 'tensorflow binding version:', bindingVer);
|
||||
const env = JSON.parse(JSON.stringify(human.env));
|
||||
env.kernels = human.env.kernels.length;
|
||||
log('info', 'env:', env);
|
||||
|
||||
await human.load();
|
||||
if (config.backend === human.tf.getBackend()) log('state', 'passed: set backend:', config.backend);
|
||||
else log('error', 'failed: set backend:', config.backend);
|
||||
if (config.backend === human.tf.getBackend()) {
|
||||
log('state', 'passed: set backend:', config.backend);
|
||||
} else {
|
||||
log('error', 'failed: set backend:', config.backend); // abort immediately
|
||||
return false;
|
||||
}
|
||||
log('state', 'tensors', human.tf.memory().numTensors);
|
||||
|
||||
if (human.models) {
|
||||
|
@ -296,7 +302,11 @@ async function test(Human, inputConfig) {
|
|||
|
||||
// test warmup sequences
|
||||
log('info', 'test: warmup');
|
||||
await testInstance(human);
|
||||
res = await testInstance(human);
|
||||
if (!res) {
|
||||
log('error', 'failed: instance backend:', human.tf.getBackend());
|
||||
return;
|
||||
}
|
||||
config.cacheSensitivity = 0;
|
||||
config.warmup = 'none';
|
||||
res = await testWarmup(human, 'default');
|
||||
|
@ -475,7 +485,7 @@ async function test(Human, inputConfig) {
|
|||
// test face attention
|
||||
log('info', 'test face attention');
|
||||
human.models.facemesh = null;
|
||||
config.face.attention = { enabled: true };
|
||||
config.face.attention = { enabled: true, modelPath: 'https://vladmandic.github.io/human-models/models/facemesh-attention.json' };
|
||||
res = await testDetect(human, 'samples/in/ai-face.jpg', 'face attention');
|
||||
if (!res || !res.face[0] || res.face[0].mesh.length !== 478 || Object.keys(res.face[0].annotations).length !== 36) log('error', 'failed: face attention', { mesh: res.face?.[0]?.mesh?.length, annotations: Object.keys(res.face?.[0]?.annotations | {}).length });
|
||||
else log('state', 'passed: face attention');
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
process.env.TF_CPP_MIN_LOG_LEVEL = '2';
|
||||
const Human = require('../dist/human.node-gpu.js').default;
|
||||
const H = require('../dist/human.node-gpu.js');
|
||||
const test = require('./test-main.js').test;
|
||||
|
||||
const config = {
|
||||
|
@ -25,4 +25,8 @@ const config = {
|
|||
filter: { enabled: false },
|
||||
};
|
||||
|
||||
test(Human, config);
|
||||
async function main() {
|
||||
test(H.Human, config);
|
||||
}
|
||||
|
||||
main();
|
||||
|
|
|
@ -1,20 +1,21 @@
|
|||
const log = require('@vladmandic/pilogger');
|
||||
const tf = require('@tensorflow/tfjs'); // wasm backend requires tfjs to be loaded first
|
||||
const wasm = require('@tensorflow/tfjs-backend-wasm'); // wasm backend does not get auto-loaded in nodejs
|
||||
const { Canvas, Image } = require('canvas');
|
||||
const Human = require('../dist/human.node-wasm.js');
|
||||
const H = require('../dist/human.node-wasm.js');
|
||||
const test = require('./test-main.js').test;
|
||||
|
||||
// @ts-ignore
|
||||
Human.env.Canvas = Canvas; // requires monkey-patch as wasm does not have tf.browser namespace
|
||||
H.env.Canvas = Canvas; // requires monkey-patch as wasm does not have tf.browser namespace
|
||||
// @ts-ignore
|
||||
Human.env.Image = Image; // requires monkey-patch as wasm does not have tf.browser namespace
|
||||
H.env.Image = Image; // requires monkey-patch as wasm does not have tf.browser namespace
|
||||
|
||||
const config = {
|
||||
cacheSensitivity: 0,
|
||||
modelBasePath: 'https://vladmandic.github.io/human/models/',
|
||||
backend: 'wasm',
|
||||
wasmPath: 'node_modules/@tensorflow/tfjs-backend-wasm/dist/',
|
||||
// wasmPath: `cdn.jsdelivr.net/npm/@tensorflow/tfjs-backend-wasm@${tf.version_core}/dist/`,
|
||||
// wasmPath: 'node_modules/@tensorflow/tfjs-backend-wasm/dist/',
|
||||
wasmPath: `https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-backend-wasm@${tf.version_core}/dist/`,
|
||||
debug: false,
|
||||
async: false,
|
||||
face: {
|
||||
|
@ -38,7 +39,9 @@ async function main() {
|
|||
wasm.setWasmPaths(config.wasmPath);
|
||||
await tf.setBackend('wasm');
|
||||
await tf.ready();
|
||||
test(Human.Human, config);
|
||||
H.env.updateBackend();
|
||||
log.info(H.env.wasm);
|
||||
test(H.Human, config);
|
||||
}
|
||||
|
||||
main();
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
process.env.TF_CPP_MIN_LOG_LEVEL = '2';
|
||||
const Human = require('../dist/human.node.js').default;
|
||||
|
||||
const H = require('../dist/human.node.js');
|
||||
const test = require('./test-main.js').test;
|
||||
|
||||
const config = {
|
||||
|
@ -25,4 +26,8 @@ const config = {
|
|||
filter: { enabled: false },
|
||||
};
|
||||
|
||||
test(Human, config);
|
||||
async function main() {
|
||||
test(H.Human, config);
|
||||
}
|
||||
|
||||
main();
|
||||
|
|
1752
test/test.log
1752
test/test.log
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue