mirror of https://github.com/vladmandic/human
update tests
parent
a222ce933f
commit
55a6398d95
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
### **HEAD -> main** 2022/08/31 mandic00@live.com
|
### **HEAD -> main** 2022/08/31 mandic00@live.com
|
||||||
|
|
||||||
|
- minor bug fixes and increased test coverage
|
||||||
- extend release tests
|
- extend release tests
|
||||||
- add model load exception handling
|
- add model load exception handling
|
||||||
- add softwarekernels config option
|
- add softwarekernels config option
|
||||||
|
|
10
TODO.md
10
TODO.md
|
@ -78,9 +78,13 @@ Enable via `about:config` -> `gfx.offscreencanvas.enabled`
|
||||||
- Fix `human.match` when using mixed descriptor lengths
|
- Fix `human.match` when using mixed descriptor lengths
|
||||||
- Fix **WASM** feature detection issue in TFJS with Edge/Chromium
|
- Fix **WASM** feature detection issue in TFJS with Edge/Chromium
|
||||||
Example: `console.log(human.env.wasm)`
|
Example: `console.log(human.env.wasm)`
|
||||||
- Increased test coverage
|
- Increased **NodeJS** test coverage
|
||||||
**NodeJS**: Run using: `npm run test`
|
Run using: `npm run test`
|
||||||
**Browser**: Run using: `demo/browser.html`
|
Runs tests for `tfjs-node`, `tfjs-node-gpu` and `wasm`
|
||||||
|
- Increased **Browser** test coverage
|
||||||
|
Run using: `demo/browser.html`
|
||||||
|
Runs tests for `webgl`, `humangl`, `webgpu` and `wasm`
|
||||||
|
Runs tests for ESM and IIFE versions of library
|
||||||
- Increase availability of alternative models
|
- Increase availability of alternative models
|
||||||
See `models/model.json` for full list
|
See `models/model.json` for full list
|
||||||
- Update profiling methods in `human.profile()`
|
- Update profiling methods in `human.profile()`
|
||||||
|
|
|
@ -97,7 +97,7 @@
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"seedrandom": "^3.0.5",
|
"seedrandom": "^3.0.5",
|
||||||
"tslib": "^2.4.0",
|
"tslib": "^2.4.0",
|
||||||
"typedoc": "0.23.12",
|
"typedoc": "0.23.13",
|
||||||
"typescript": "4.8.2"
|
"typescript": "4.8.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,39 +1,39 @@
|
||||||
2022-08-31 18:30:05 [32mDATA: [39m Build {"name":"@vladmandic/human","version":"2.9.4"}
|
2022-09-01 09:05:06 [32mDATA: [39m Build {"name":"@vladmandic/human","version":"2.9.4"}
|
||||||
2022-08-31 18:30:05 [36mINFO: [39m Application: {"name":"@vladmandic/human","version":"2.9.4"}
|
2022-09-01 09:05:06 [36mINFO: [39m Application: {"name":"@vladmandic/human","version":"2.9.4"}
|
||||||
2022-08-31 18:30:05 [36mINFO: [39m Environment: {"profile":"production","config":".build.json","package":"package.json","tsconfig":true,"eslintrc":true,"git":true}
|
2022-09-01 09:05:06 [36mINFO: [39m Environment: {"profile":"production","config":".build.json","package":"package.json","tsconfig":true,"eslintrc":true,"git":true}
|
||||||
2022-08-31 18:30:05 [36mINFO: [39m Toolchain: {"build":"0.7.11","esbuild":"0.15.6","typescript":"4.8.2","typedoc":"0.23.12","eslint":"8.23.0"}
|
2022-09-01 09:05:06 [36mINFO: [39m Toolchain: {"build":"0.7.11","esbuild":"0.15.6","typescript":"4.8.2","typedoc":"0.23.13","eslint":"8.23.0"}
|
||||||
2022-08-31 18:30:05 [36mINFO: [39m Build: {"profile":"production","steps":["clean","compile","typings","typedoc","lint","changelog"]}
|
2022-09-01 09:05:06 [36mINFO: [39m Build: {"profile":"production","steps":["clean","compile","typings","typedoc","lint","changelog"]}
|
||||||
2022-08-31 18:30:05 [35mSTATE:[39m Clean: {"locations":["dist/*","types/lib/*","typedoc/*"]}
|
2022-09-01 09:05:06 [35mSTATE:[39m Clean: {"locations":["dist/*","types/lib/*","typedoc/*"]}
|
||||||
2022-08-31 18:30:05 [35mSTATE:[39m Compile: {"name":"tfjs/nodejs/cpu","format":"cjs","platform":"node","input":"tfjs/tf-node.ts","output":"dist/tfjs.esm.js","files":1,"inputBytes":159,"outputBytes":608}
|
2022-09-01 09:05:06 [35mSTATE:[39m Compile: {"name":"tfjs/nodejs/cpu","format":"cjs","platform":"node","input":"tfjs/tf-node.ts","output":"dist/tfjs.esm.js","files":1,"inputBytes":159,"outputBytes":608}
|
||||||
2022-08-31 18:30:06 [35mSTATE:[39m Compile: {"name":"human/nodejs/cpu","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node.js","files":75,"inputBytes":655767,"outputBytes":308629}
|
2022-09-01 09:05:06 [35mSTATE:[39m Compile: {"name":"human/nodejs/cpu","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node.js","files":75,"inputBytes":655767,"outputBytes":308629}
|
||||||
2022-08-31 18:30:06 [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":167,"outputBytes":612}
|
2022-09-01 09:05:06 [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":167,"outputBytes":612}
|
||||||
2022-08-31 18:30:06 [35mSTATE:[39m Compile: {"name":"human/nodejs/gpu","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node-gpu.js","files":75,"inputBytes":655771,"outputBytes":308633}
|
2022-09-01 09:05:06 [35mSTATE:[39m Compile: {"name":"human/nodejs/gpu","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node-gpu.js","files":75,"inputBytes":655771,"outputBytes":308633}
|
||||||
2022-08-31 18:30:06 [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":206,"outputBytes":664}
|
2022-09-01 09:05:06 [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":206,"outputBytes":664}
|
||||||
2022-08-31 18:30:06 [35mSTATE:[39m Compile: {"name":"human/nodejs/wasm","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node-wasm.js","files":75,"inputBytes":655823,"outputBytes":308683}
|
2022-09-01 09:05:06 [35mSTATE:[39m Compile: {"name":"human/nodejs/wasm","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node-wasm.js","files":75,"inputBytes":655823,"outputBytes":308683}
|
||||||
2022-08-31 18:30:06 [35mSTATE:[39m Compile: {"name":"tfjs/browser/version","format":"esm","platform":"browser","input":"tfjs/tf-version.ts","output":"dist/tfjs.version.js","files":1,"inputBytes":1125,"outputBytes":358}
|
2022-09-01 09:05:06 [35mSTATE:[39m Compile: {"name":"tfjs/browser/version","format":"esm","platform":"browser","input":"tfjs/tf-version.ts","output":"dist/tfjs.version.js","files":1,"inputBytes":1125,"outputBytes":358}
|
||||||
2022-08-31 18:30:06 [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":1088,"outputBytes":583}
|
2022-09-01 09:05:06 [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":1088,"outputBytes":583}
|
||||||
2022-08-31 18:30:06 [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":655742,"outputBytes":307503}
|
2022-09-01 09:05:06 [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":655742,"outputBytes":307503}
|
||||||
2022-08-31 18:30:06 [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":1344,"outputBytes":2821914}
|
2022-09-01 09:05:07 [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":1344,"outputBytes":2821914}
|
||||||
2022-08-31 18:30:06 [35mSTATE:[39m Compile: {"name":"human/browser/iife/bundle","format":"iife","platform":"browser","input":"src/human.ts","output":"dist/human.js","files":75,"inputBytes":3477073,"outputBytes":1687675}
|
2022-09-01 09:05:07 [35mSTATE:[39m Compile: {"name":"human/browser/iife/bundle","format":"iife","platform":"browser","input":"src/human.ts","output":"dist/human.js","files":75,"inputBytes":3477073,"outputBytes":1687675}
|
||||||
2022-08-31 18:30:06 [35mSTATE:[39m Compile: {"name":"human/browser/esm/bundle","format":"esm","platform":"browser","input":"src/human.ts","output":"dist/human.esm.js","files":75,"inputBytes":3477073,"outputBytes":3108312}
|
2022-09-01 09:05:07 [35mSTATE:[39m Compile: {"name":"human/browser/esm/bundle","format":"esm","platform":"browser","input":"src/human.ts","output":"dist/human.esm.js","files":75,"inputBytes":3477073,"outputBytes":3108312}
|
||||||
2022-08-31 18:30:10 [35mSTATE:[39m Typings: {"input":"src/human.ts","output":"types/lib","files":30}
|
2022-09-01 09:05:11 [35mSTATE:[39m Typings: {"input":"src/human.ts","output":"types/lib","files":30}
|
||||||
2022-08-31 18:30:12 [35mSTATE:[39m TypeDoc: {"input":"src/human.ts","output":"typedoc","objects":77,"generated":true}
|
2022-09-01 09:05:13 [35mSTATE:[39m TypeDoc: {"input":"src/human.ts","output":"typedoc","objects":77,"generated":true}
|
||||||
2022-08-31 18:30:12 [35mSTATE:[39m Compile: {"name":"demo/typescript","format":"esm","platform":"browser","input":"demo/typescript/index.ts","output":"demo/typescript/index.js","files":1,"inputBytes":6714,"outputBytes":3134}
|
2022-09-01 09:05:13 [35mSTATE:[39m Compile: {"name":"demo/typescript","format":"esm","platform":"browser","input":"demo/typescript/index.ts","output":"demo/typescript/index.js","files":1,"inputBytes":6714,"outputBytes":3134}
|
||||||
2022-08-31 18:30:12 [35mSTATE:[39m Compile: {"name":"demo/faceid","format":"esm","platform":"browser","input":"demo/faceid/index.ts","output":"demo/faceid/index.js","files":2,"inputBytes":15488,"outputBytes":7788}
|
2022-09-01 09:05:13 [35mSTATE:[39m Compile: {"name":"demo/faceid","format":"esm","platform":"browser","input":"demo/faceid/index.ts","output":"demo/faceid/index.js","files":2,"inputBytes":15488,"outputBytes":7788}
|
||||||
2022-08-31 18:30:23 [35mSTATE:[39m Lint: {"locations":["*.json","src/**/*.ts","test/**/*.js","demo/**/*.js"],"files":112,"errors":0,"warnings":0}
|
2022-09-01 09:05:24 [35mSTATE:[39m Lint: {"locations":["*.json","src/**/*.ts","test/**/*.js","demo/**/*.js"],"files":113,"errors":0,"warnings":0}
|
||||||
2022-08-31 18:30:23 [35mSTATE:[39m ChangeLog: {"repository":"https://github.com/vladmandic/human","branch":"main","output":"CHANGELOG.md"}
|
2022-09-01 09:05:24 [35mSTATE:[39m ChangeLog: {"repository":"https://github.com/vladmandic/human","branch":"main","output":"CHANGELOG.md"}
|
||||||
2022-08-31 18:30:23 [35mSTATE:[39m Copy: {"input":"tfjs/tfjs.esm.d.ts"}
|
2022-09-01 09:05:24 [35mSTATE:[39m Copy: {"input":"tfjs/tfjs.esm.d.ts"}
|
||||||
2022-08-31 18:30:23 [36mINFO: [39m Done...
|
2022-09-01 09:05:24 [36mINFO: [39m Done...
|
||||||
2022-08-31 18:30:24 [35mSTATE:[39m API-Extractor: {"succeeeded":true,"errors":0,"warnings":198}
|
2022-09-01 09:05:24 [35mSTATE:[39m API-Extractor: {"succeeeded":true,"errors":0,"warnings":198}
|
||||||
2022-08-31 18:30:24 [35mSTATE:[39m Copy: {"input":"types/human.d.ts"}
|
2022-09-01 09:05:24 [35mSTATE:[39m Copy: {"input":"types/human.d.ts"}
|
||||||
2022-08-31 18:30:24 [36mINFO: [39m Analyze models: {"folders":8,"result":"models/models.json"}
|
2022-09-01 09:05:24 [36mINFO: [39m Analyze models: {"folders":8,"result":"models/models.json"}
|
||||||
2022-08-31 18:30:24 [35mSTATE:[39m Models {"folder":"./models","models":13}
|
2022-09-01 09:05:24 [35mSTATE:[39m Models {"folder":"./models","models":13}
|
||||||
2022-08-31 18:30:24 [35mSTATE:[39m Models {"folder":"../human-models/models","models":42}
|
2022-09-01 09:05:24 [35mSTATE:[39m Models {"folder":"../human-models/models","models":42}
|
||||||
2022-08-31 18:30:24 [35mSTATE:[39m Models {"folder":"../blazepose/model/","models":4}
|
2022-09-01 09:05:24 [35mSTATE:[39m Models {"folder":"../blazepose/model/","models":4}
|
||||||
2022-08-31 18:30:24 [35mSTATE:[39m Models {"folder":"../anti-spoofing/model","models":1}
|
2022-09-01 09:05:24 [35mSTATE:[39m Models {"folder":"../anti-spoofing/model","models":1}
|
||||||
2022-08-31 18:30:24 [35mSTATE:[39m Models {"folder":"../efficientpose/models","models":3}
|
2022-09-01 09:05:24 [35mSTATE:[39m Models {"folder":"../efficientpose/models","models":3}
|
||||||
2022-08-31 18:30:24 [35mSTATE:[39m Models {"folder":"../insightface/models","models":5}
|
2022-09-01 09:05:24 [35mSTATE:[39m Models {"folder":"../insightface/models","models":5}
|
||||||
2022-08-31 18:30:24 [35mSTATE:[39m Models {"folder":"../movenet/models","models":3}
|
2022-09-01 09:05:24 [35mSTATE:[39m Models {"folder":"../movenet/models","models":3}
|
||||||
2022-08-31 18:30:24 [35mSTATE:[39m Models {"folder":"../nanodet/models","models":4}
|
2022-09-01 09:05:24 [35mSTATE:[39m Models {"folder":"../nanodet/models","models":4}
|
||||||
2022-08-31 18:30:24 [35mSTATE:[39m Models: {"count":57,"totalSize":383017442}
|
2022-09-01 09:05:25 [35mSTATE:[39m Models: {"count":57,"totalSize":383017442}
|
||||||
2022-08-31 18:30:24 [36mINFO: [39m Human Build complete... {"logFile":"test/build.log"}
|
2022-09-01 09:05:25 [36mINFO: [39m Human Build complete... {"logFile":"test/build.log"}
|
||||||
|
|
|
@ -71,7 +71,7 @@ async function testDefault(title, testConfig = {}) {
|
||||||
human.reset();
|
human.reset();
|
||||||
res = human.validate(testConfig); // validate
|
res = human.validate(testConfig); // validate
|
||||||
if (res && res.length > 0) log(' invalid configuration', res);
|
if (res && res.length > 0) log(' invalid configuration', res);
|
||||||
log(`test ${title}/${human.tf.getBackend()}`, human.config);
|
log(`test ${title}/${human.tf.getBackend()}`);
|
||||||
await human.load();
|
await human.load();
|
||||||
const models = Object.keys(human.models).map((model) => ({ name: model, loaded: (human.models[model] !== null) }));
|
const models = Object.keys(human.models).map((model) => ({ name: model, loaded: (human.models[model] !== null) }));
|
||||||
log(' models', models);
|
log(' models', models);
|
||||||
|
@ -93,6 +93,54 @@ async function testDefault(title, testConfig = {}) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function testMatch() {
|
||||||
|
human.reset();
|
||||||
|
await human.warmup({ warmup: 'face' });
|
||||||
|
const img1 = await image('../../samples/in/ai-body.jpg');
|
||||||
|
const input1 = await human.image(img1);
|
||||||
|
const img2 = await image('../../samples/in/ai-face.jpg');
|
||||||
|
const input2 = await human.image(img2);
|
||||||
|
const res1 = await human.detect(input1.tensor);
|
||||||
|
const res2 = await human.detect(input2.tensor);
|
||||||
|
const desc1 = res1?.face?.[0]?.embedding;
|
||||||
|
const desc2 = res2?.face?.[0]?.embedding;
|
||||||
|
const similarity = await human.similarity(desc1, desc2);
|
||||||
|
const descArray = [];
|
||||||
|
for (let i = 0; i < 100; i++) descArray.push(desc2);
|
||||||
|
const match = await human.match(desc1, descArray);
|
||||||
|
log(`test similarity/${human.tf.getBackend()}`, match, similarity);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function testWorker() {
|
||||||
|
log(`test webworker/${human.tf.getBackend()}`);
|
||||||
|
const img = await image('../../samples/in/ai-body.jpg');
|
||||||
|
const canvas = document.createElement('canvas');
|
||||||
|
canvas.width = img.naturalWidth;
|
||||||
|
canvas.height = img.naturalHeight;
|
||||||
|
const ctx = canvas.getContext('2d');
|
||||||
|
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
|
||||||
|
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
||||||
|
const worker = new Worker('test-browser-worker.js');
|
||||||
|
let res;
|
||||||
|
const userConfig = {
|
||||||
|
backend: human.tf.getBackend(),
|
||||||
|
debug: true,
|
||||||
|
face: { enabled: false },
|
||||||
|
hand: { enabled: false },
|
||||||
|
body: { enabled: true },
|
||||||
|
object: { enabled: false },
|
||||||
|
};
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
worker.addEventListener('message', (msg) => {
|
||||||
|
res = msg.data.result;
|
||||||
|
log(' summary', { face: res.face.length, body: res.body.length, hand: res.hand.length, object: res.object.length, gesture: res.gesture.length });
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
// pass image data as arraybuffer to worker by reference to avoid copy
|
||||||
|
worker.postMessage({ image: imageData.data.buffer, width: canvas.width, height: canvas.height, userConfig }, [imageData.data.buffer]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
async function runBenchmark() {
|
async function runBenchmark() {
|
||||||
const img = await image('../../samples/in/ai-face.jpg');
|
const img = await image('../../samples/in/ai-face.jpg');
|
||||||
human.reset();
|
human.reset();
|
||||||
|
@ -142,12 +190,11 @@ async function main() {
|
||||||
await testDefault('sync', { debug: true, async: false });
|
await testDefault('sync', { debug: true, async: false });
|
||||||
await testDefault('none', { debug: true, async: true, face: { enabled: false }, body: { enabled: false }, hand: { enabled: false }, gesture: { enabled: false }, segmentation: { enabled: false }, object: { enabled: false } });
|
await testDefault('none', { debug: true, async: true, face: { enabled: false }, body: { enabled: false }, hand: { enabled: false }, gesture: { enabled: false }, segmentation: { enabled: false }, object: { enabled: false } });
|
||||||
await testDefault('object', { debug: true, async: true, face: { enabled: false }, body: { enabled: false }, hand: { enabled: false }, gesture: { enabled: false }, segmentation: { enabled: false }, object: { enabled: true } });
|
await testDefault('object', { debug: true, async: true, face: { enabled: false }, body: { enabled: false }, hand: { enabled: false }, gesture: { enabled: false }, segmentation: { enabled: false }, object: { enabled: true } });
|
||||||
|
await testMatch();
|
||||||
|
await testWorker();
|
||||||
// TBD detectors only
|
// TBD detectors only
|
||||||
// TBD segmentation
|
// TBD segmentation
|
||||||
// TBD face match
|
|
||||||
// TBD non-default models
|
// TBD non-default models
|
||||||
// TBD web workers
|
|
||||||
// TBD multiple instances
|
|
||||||
}
|
}
|
||||||
log('tests complete');
|
log('tests complete');
|
||||||
for (const backend of backends) {
|
for (const backend of backends) {
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
/// <reference lib="webworker"/>
|
||||||
|
|
||||||
|
// load Human using IIFE script as Chome Mobile does not support Modules as Workers
|
||||||
|
self.importScripts('../dist/human.js'); // eslint-disable-line no-restricted-globals
|
||||||
|
|
||||||
|
// eslint-disable-next-line new-cap, no-undef
|
||||||
|
const human = new Human.default();
|
||||||
|
|
||||||
|
onmessage = async (msg) => { // receive message from main thread
|
||||||
|
console.log('worker onmessage', msg.data); // eslint-disable-line no-console
|
||||||
|
const image = new ImageData(new Uint8ClampedArray(msg.data.image), msg.data.width, msg.data.height);
|
||||||
|
const result = await human.detect(image, msg.data.userConfig);
|
||||||
|
result.tensors = human.tf.engine().state.numTensors; // append to result object so main thread get info
|
||||||
|
result.backend = human.tf.getBackend(); // append to result object so main thread get info
|
||||||
|
result.canvas = null; // must strip original canvas from return value as it cannot be transfered from worker thread
|
||||||
|
console.log('worker result', result); // eslint-disable-line no-console
|
||||||
|
postMessage({ result }); // send message back to main thread without canvas
|
||||||
|
};
|
Loading…
Reference in New Issue