diff --git a/.build.json b/.build.json index 5a9aa732..d45c6be5 100644 --- a/.build.json +++ b/.build.json @@ -91,8 +91,7 @@ "platform": "browser", "format": "esm", "input": "tfjs/tf-version.ts", - "output": "dist/tfjs.version.js", - "external": ["fs", "os", "buffer", "util"] + "output": "dist/tfjs.version.js" }, { "name": "tfjs/browser/esm/nobundle", @@ -100,7 +99,7 @@ "format": "esm", "input": "tfjs/tf-browser.ts", "output": "dist/tfjs.esm.js", - "external": ["@tensorflow", "fs", "os", "buffer", "util"] + "external": ["@tensorflow"] }, { "name": "human/browser/esm/nobundle", @@ -109,7 +108,7 @@ "input": "src/human.ts", "output": "dist/human.esm-nobundle.js", "sourcemap": true, - "external": ["@tensorflow", "fs", "os", "buffer", "util"] + "external": ["@tensorflow"] }, { "name": "tfjs/browser/esm/custom", @@ -117,8 +116,7 @@ "format": "esm", "input": "tfjs/tf-custom.ts", "output": "dist/tfjs.esm.js", - "sourcemap": false, - "external": ["fs", "os", "buffer", "util"] + "sourcemap": false }, { "name": "human/browser/iife/bundle", @@ -128,7 +126,7 @@ "output": "dist/human.js", "minify": true, "globalName": "Human", - "external": ["fs", "os", "buffer", "util"] + "external": ["@tensorflow"] }, { "name": "human/browser/esm/bundle", @@ -138,7 +136,7 @@ "output": "dist/human.esm.js", "sourcemap": true, "minify": false, - "external": ["fs", "os", "buffer", "util"], + "external": ["@tensorflow"], "typings": "types/lib", "typedoc": "typedoc" }, diff --git a/CHANGELOG.md b/CHANGELOG.md index 025b1728..be695ca6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,8 +9,12 @@ ## Changelog -### **HEAD -> main** 2021/11/17 mandic00@live.com +### **2.5.3** 2021/11/18 mandic00@live.com + +### **origin/main** 2021/11/17 mandic00@live.com + +- create typedef rollup - optimize centernet - cache frequent tf constants - add extra face rotation prior to mesh diff --git a/TODO.md b/TODO.md index fd9a3204..21e51d55 100644 --- a/TODO.md +++ b/TODO.md @@ -43,21 +43,21 @@ MoveNet MultiPose model does not work with WASM backend due to missing F32 broad ## Pending Release Notes New: -- New type definitions rollup -- New demo `demos/faceid` that utilizes multiple algorithm to validate input before triggering face recognition -- New optional model `liveness` +- Demo `demos/faceid` that utilizes multiple algorithm to validate input before triggering face recognition +- Type definitions rollup for `Human` and `TFJS` +- Optional module `liveness` checks if input appears to be a real-world live image or a recording - best used together with `antispoofing` that checks if input appears to have a realistic face -- New face masking option in `face.config.detector.mask` + best used together with module `antispoofing` that checks if input appears to have a realistic face +- Face masking option in `face.config.detector.mask` result is shading of face image outside of face area which is useful for increased sensitivity of other modules that rely on detected face as input -- New face crop option in `face.config.detector.cropFactor` +- Face crop option in `face.config.detector.cropFactor` result is user-definable fine-tuning for other modules that rely on detected face as input Other: +- Documentation overhaul - Improved **Safari** compatibility - Improved `similarity` and `match` score range normalization - Improved error handling - Improved VSCode out-of-the-box experience -- Documentation overhaul - Fix for optional `gear`, `ssrnet`, `mobilefacenet` modules - Fix for Firefox WebGPU compatibility issue diff --git a/api-extractor.json b/api-extractor.json index 75161b5e..037280f7 100644 --- a/api-extractor.json +++ b/api-extractor.json @@ -1,7 +1,7 @@ { "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json", "mainEntryPointFilePath": "types/lib/src/human.d.ts", - "bundledPackages": ["@tensorflow/tfjs-core", "@tensorflow/tfjs-converter", "long", "@types/offscreencanvas"], + "bundledPackages": ["@tensorflow/tfjs-core", "@tensorflow/tfjs-converter"], "compiler": { "skipLibCheck": false }, diff --git a/demo/faceid/index.js b/demo/faceid/index.js index 49f4cafe..9184b9bb 100644 --- a/demo/faceid/index.js +++ b/demo/faceid/index.js @@ -313,7 +313,7 @@ async function main() { } } async function init() { - log2("human version:", human.version, "| tfjs version:", human.tf.version_core); + log2("human version:", human.version, "| tfjs version:", human.tf.version["tfjs-core"]); log2("options:", JSON.stringify(options).replace(/{|}|"|\[|\]/g, "").replace(/,/g, " ")); printFPS("loading..."); log2("known face records:", await count()); diff --git a/demo/faceid/index.ts b/demo/faceid/index.ts index f897eb23..0445d29a 100644 --- a/demo/faceid/index.ts +++ b/demo/faceid/index.ts @@ -257,7 +257,7 @@ async function main() { // main entry point } async function init() { - log('human version:', human.version, '| tfjs version:', human.tf.version_core); + log('human version:', human.version, '| tfjs version:', human.tf.version['tfjs-core']); log('options:', JSON.stringify(options).replace(/{|}|"|\[|\]/g, '').replace(/,/g, ' ')); printFPS('loading...'); log('known face records:', await indexDb.count()); diff --git a/demo/multithread/node-multiprocess-worker.js b/demo/multithread/node-multiprocess-worker.js index 2ad5af08..c8f16a99 100644 --- a/demo/multithread/node-multiprocess-worker.js +++ b/demo/multithread/node-multiprocess-worker.js @@ -16,7 +16,7 @@ const Human = require('../../dist/human.node.js').default; // or const Human = r let human = null; const myConfig = { - backend: 'tensorflow', + // backend: 'tensorflow', modelBasePath: 'file://models/', debug: false, async: true, @@ -78,7 +78,7 @@ async function main() { // wait until tf is ready await human.tf.ready(); // pre-load models - log.state('Worker: PID:', process.pid, `TensorFlow/JS ${human.tf.version_core} Human ${human.version} Backend: ${human.tf.getBackend()}`); + log.state('Worker: PID:', process.pid, `TensorFlow/JS ${human.tf.version['tfjs-core']} Human ${human.version} Backend: ${human.tf.getBackend()}`); await human.load(); // now we're ready, so send message back to main that it knows it can use this worker diff --git a/demo/nodejs/node-simple.js b/demo/nodejs/node-simple.js new file mode 100644 index 00000000..9c56a96b --- /dev/null +++ b/demo/nodejs/node-simple.js @@ -0,0 +1,13 @@ +const fs = require('fs'); +const Human = require('../../dist/human.node.js').default; // this is same as `@vladmandic/human` but using relative paths + +async function main(inputFile) { + const human = new Human(); // create instance of human using default configuration + const buffer = fs.readFileSync(inputFile); // read file data into buffer + const tensor = human.tf.node.decodeImage(buffer); // decode jpg data + const result = await human.detect(tensor); // run detection; will initialize backend and on-demand load models + // eslint-disable-next-line no-console + console.log(result); +} + +main('samples/in/ai-body.jpg'); diff --git a/demo/nodejs/node.js b/demo/nodejs/node.js index a01c191e..f187ba04 100644 --- a/demo/nodejs/node.js +++ b/demo/nodejs/node.js @@ -19,7 +19,7 @@ const Human = require('../../dist/human.node.js').default; // or const Human = r let human = null; const myConfig = { - backend: 'tensorflow', + // backend: 'tensorflow', modelBasePath: 'file://models/', debug: true, async: false, diff --git a/demo/typescript/index.js b/demo/typescript/index.js index 7185752d..5f46142c 100644 --- a/demo/typescript/index.js +++ b/demo/typescript/index.js @@ -8,7 +8,12 @@ import { Human } from "../../dist/human.esm.js"; var humanConfig = { modelBasePath: "../../models", - filter: { equalization: true } + filter: { enabled: true, equalization: false }, + face: { enabled: true, detector: { rotation: false }, mesh: { enabled: true }, iris: { enabled: true }, description: { enabled: true }, emotion: { enabled: true } }, + body: { enabled: true }, + hand: { enabled: true }, + object: { enabled: false }, + gesture: { enabled: true } }; var human = new Human(humanConfig); human.env["perfadd"] = false; @@ -80,7 +85,7 @@ async function drawLoop() { setTimeout(drawLoop, 30); } async function main() { - log("human version:", human.version, "| tfjs version:", human.tf.version_core); + log("human version:", human.version, "| tfjs version:", human.tf.version["tfjs-core"]); log("platform:", human.env.platform, "| agent:", human.env.agent); status("loading..."); await human.load(); diff --git a/demo/typescript/index.ts b/demo/typescript/index.ts index 494f3acf..68369f4d 100644 --- a/demo/typescript/index.ts +++ b/demo/typescript/index.ts @@ -10,15 +10,15 @@ import { Human } from '../../dist/human.esm.js'; // equivalent of @vladmandic/Human const humanConfig = { // user configuration for human, used to fine-tune behavior - modelBasePath: '../../models', - filter: { equalization: true }, // backend: 'webgpu' as 'webgpu, // async: true, - // face: { enabled: false, detector: { rotation: true }, iris: { enabled: false }, description: { enabled: false }, emotion: { enabled: false } }, - // body: { enabled: false }, - // hand: { enabled: false }, - // object: { enabled: true }, - // gesture: { enabled: true }, + modelBasePath: '../../models', + filter: { enabled: true, equalization: false }, + face: { enabled: true, detector: { rotation: false }, mesh: { enabled: true }, iris: { enabled: true }, description: { enabled: true }, emotion: { enabled: true } }, + body: { enabled: true }, + hand: { enabled: true }, + object: { enabled: false }, + gesture: { enabled: true }, }; const human = new Human(humanConfig); // create instance of human with overrides from user configuration @@ -97,7 +97,7 @@ async function drawLoop() { // main screen refresh loop } async function main() { // main entry point - log('human version:', human.version, '| tfjs version:', human.tf.version_core); + log('human version:', human.version, '| tfjs version:', human.tf.version['tfjs-core']); log('platform:', human.env.platform, '| agent:', human.env.agent); status('loading...'); await human.load(); // preload all models diff --git a/src/human.ts b/src/human.ts index 8853b862..ebf23c84 100644 --- a/src/human.ts +++ b/src/human.ts @@ -124,7 +124,7 @@ export class Human { */ constructor(userConfig?: Partial) { this.env = env; - defaults.wasmPath = tf.version_core.includes('-') // custom build or official build + defaults.wasmPath = tf.version['tfjs-core'].includes('-') // custom build or official build ? 'https://vladmandic.github.io/tfjs/dist/' : `https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-backend-wasm@${tf.version_core}/dist/`; defaults.modelBasePath = env.browser ? '../models/' : 'file://models/'; @@ -283,7 +283,7 @@ export class Human { if (this.env.initial) { // print version info on first run and check for correct backend setup if (this.config.debug) log(`version: ${this.version}`); - if (this.config.debug) log(`tfjs version: ${this.tf.version_core}`); + if (this.config.debug) log(`tfjs version: ${this.tf.version['tfjs-core']}`); if (!await backend.check(this)) log('error: backend check failed'); await tf.ready(); if (this.env.browser) { diff --git a/src/tfjs/types.ts b/src/tfjs/types.ts index 955ff924..93631e41 100644 --- a/src/tfjs/types.ts +++ b/src/tfjs/types.ts @@ -16,4 +16,4 @@ export type { GraphModel } from '@tensorflow/tfjs-converter/dist/index'; * @external long */ // eslint-disable-next-line node/no-missing-import -export type { Long } from 'long'; +// export type { Long } from 'long'; diff --git a/src/util/env.ts b/src/util/env.ts index 80fde5d8..34989312 100644 --- a/src/util/env.ts +++ b/src/util/env.ts @@ -81,7 +81,7 @@ export class Env { constructor() { this.browser = typeof navigator !== 'undefined'; this.node = typeof process !== 'undefined'; - this.tfjs = { version: tf.version_core }; + this.tfjs = { version: tf.version['tfjs-core'] }; this.offscreen = typeof OffscreenCanvas !== 'undefined'; this.initial = true; // @ts-ignore WorkerGlobalScope evaluated in browser only @@ -148,8 +148,8 @@ export class Env { async updateCPU() { const cpu = { model: '', flags: [] }; if (this.node && this.platform.startsWith('linux')) { - // eslint-disable-next-line global-require /* + // eslint-disable-next-line global-require const fs = require('fs'); try { const data = fs.readFileSync('/proc/cpuinfo').toString(); diff --git a/test/test-main.js b/test/test-main.js index 35915943..737a8096 100644 --- a/test/test-main.js +++ b/test/test-main.js @@ -266,7 +266,7 @@ async function test(Human, inputConfig) { config.cacheSensitivity = 0; config.warmup = 'none'; res = await testWarmup(human, 'default'); - if (res.error !== 'null') log('error', 'failed: warmup none result mismatch'); + if (res.error !== null) log('error', 'failed: warmup none result mismatch'); else log('state', 'passed: warmup none result match'); config.warmup = 'face'; res = await testWarmup(human, 'default');