diff --git a/.build.json b/.build.json
index 01eb0702..e3017ab8 100644
--- a/.build.json
+++ b/.build.json
@@ -111,34 +111,13 @@
"sourcemap": true,
"external": ["@tensorflow", "fs", "os", "buffer", "util"]
},
-
- {
- "name": "tfjs/browser/esm/custom",
- "platform": "browser",
- "format": "esm",
- "input": "tfjs/tf-custom.ts",
- "output": "dist/tfjs.esm.js",
- "sourcemap": true,
- "external": ["fs", "os", "buffer", "util"]
- },
- {
- "name": "human/browser/esm/custom",
- "platform": "browser",
- "format": "esm",
- "input": "src/human.ts",
- "output": "dist/human.custom.esm.js",
- "sourcemap": true,
- "minify": true,
- "external": ["fs", "os", "buffer", "util"]
- },
-
{
"name": "tfjs/browser/esm/bundle",
"platform": "browser",
"format": "esm",
"input": "tfjs/tf-browser.ts",
"output": "dist/tfjs.esm.js",
- "minify": true,
+ "minify": false,
"sourcemap": true,
"external": ["fs", "os", "buffer", "util"]
},
@@ -158,7 +137,28 @@
"format": "esm",
"input": "src/human.ts",
"output": "dist/human.esm.js",
+ "minify": true,
"sourcemap": true,
+ "external": ["fs", "os", "buffer", "util"]
+ },
+
+ {
+ "name": "tfjs/browser/esm/custom",
+ "platform": "browser",
+ "format": "esm",
+ "input": "tfjs/tf-custom.ts",
+ "output": "dist/tfjs.esm.js",
+ "sourcemap": false,
+ "external": ["fs", "os", "buffer", "util"]
+ },
+ {
+ "name": "human/browser/esm/custom",
+ "platform": "browser",
+ "format": "esm",
+ "input": "src/human.ts",
+ "output": "dist/human.custom.esm.js",
+ "sourcemap": true,
+ "minify": false,
"external": ["fs", "os", "buffer", "util"],
"typings": "types",
"typedoc": "typedoc"
diff --git a/.eslintrc.json b/.eslintrc.json
index a4132990..570d374e 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -11,7 +11,8 @@
"ecmaVersion": 2021
},
"plugins": [
- "@typescript-eslint"
+ "@typescript-eslint",
+ "html"
],
"extends": [
"airbnb-base",
diff --git a/.hintrc b/.hintrc
index 7f9ab14b..2e63bba3 100644
--- a/.hintrc
+++ b/.hintrc
@@ -5,7 +5,7 @@
"browserslist": [
"chrome >= 90",
"edge >= 90",
- "firefox >= 90",
+ "firefox >= 100",
"android >= 90",
"safari >= 15"
],
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f0a8340a..05b946e5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,11 +9,15 @@
## Changelog
+### **HEAD -> main** 2021/10/25 mandic00@live.com
+
+
+### **release: 2.4.1** 2021/10/25 mandic00@live.com
+
+
### **2.4.1** 2021/10/25 mandic00@live.com
-
-### **origin/main** 2021/10/25 mandic00@live.com
-
+- refactoring plus jsdoc comments
- increase face similarity match resolution
- time based caching
- turn on minification
diff --git a/TODO.md b/TODO.md
index 50ee9b4e..a7db2256 100644
--- a/TODO.md
+++ b/TODO.md
@@ -2,11 +2,12 @@
## Work in Progress
+- Switch to custom `tfjs` for main `human` ESM bundle
+
### Exploring
-- Switch to custom `tfjs` for main `human` ESM bundle
- Optical Flow:
- Histogram Equalization: Regular, Adaptive, Contrast Limited
- TFLite Models:
@@ -22,6 +23,9 @@ Experimental support only until support is officially added in Chromium
## Known Issues
+- `tfjs.esm.d.ts` missing namespace `OptimizerConstructors`
+- exports from `match` are marked as private
+
### Face Detection
diff --git a/demo/facematch/facematch.js b/demo/facematch/facematch.js
index ba5280e7..a308c4fd 100644
--- a/demo/facematch/facematch.js
+++ b/demo/facematch/facematch.js
@@ -1,12 +1,12 @@
-// @ts-nocheck // typescript checks disabled as this is pure javascript
-
+// @ts-nocheck
/**
* Human demo for browsers
*
* Demo for face descriptor analysis and face simmilarity analysis
*/
-import Human from '../../dist/human.esm.js';
+/** @type {Human} */
+import Human from '../../dist/human.custom.esm.js';
const userConfig = {
backend: 'wasm',
@@ -15,7 +15,6 @@ const userConfig = {
cacheSensitivity: 0,
debug: true,
modelBasePath: '../../models/',
- // wasmPath: 'https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-backend-wasm@3.9.0/dist/',
face: {
enabled: true,
detector: { rotation: true, return: true, maxDetected: 50 },
@@ -165,6 +164,7 @@ async function AddFaceCanvas(index, res, fileName) {
await human.tf.browser.toPixels(res.face[i].tensor, canvas);
document.getElementById('faces').appendChild(canvas);
const ctx = canvas.getContext('2d');
+ if (!ctx) return false;
ctx.font = 'small-caps 0.8rem "Lato"';
ctx.fillStyle = 'rgba(255, 255, 255, 1)';
ctx.fillText(`${res.face[i].age}y ${(100 * (res.face[i].genderScore || 0)).toFixed(1)}% ${res.face[i].gender}`, 4, canvas.height - 6);
@@ -258,6 +258,8 @@ async function main() {
title('');
log('Ready');
+ human.validate(userConfig);
+ human.similarity([], []);
}
window.onload = main;
diff --git a/demo/helpers/gl-bench.js b/demo/helpers/gl-bench.js
index 3f6de570..223d3f14 100644
--- a/demo/helpers/gl-bench.js
+++ b/demo/helpers/gl-bench.js
@@ -37,7 +37,7 @@ const UISVG = `
class GLBench {
/** GLBench constructor
- * @param { WebGLRenderingContext | WebGL2RenderingContext } gl context
+ * @param { WebGLRenderingContext | WebGL2RenderingContext | null } gl context
* @param { Object | undefined } settings additional settings
*/
constructor(gl, settings = {}) {
diff --git a/demo/helpers/menu.js b/demo/helpers/menu.js
index cd891cdc..6406a1c5 100644
--- a/demo/helpers/menu.js
+++ b/demo/helpers/menu.js
@@ -1,5 +1,3 @@
-//@ts-nocheck
-
let instance = 0;
let CSScreated = false;
@@ -86,6 +84,7 @@ class Menu {
}
createMenu(parent, title = '', position = { top: null, left: null, bottom: null, right: null }) {
+ /** @type {HTMLDivElement} */
this.menu = document.createElement('div');
this.menu.id = `menu-${instance}`;
this.menu.className = 'menu';
@@ -120,6 +119,7 @@ class Menu {
this.menu.appendChild(this.container);
if (typeof parent === 'object') parent.appendChild(this.menu);
+ // @ts-ignore undefined
else document.getElementById(parent).appendChild(this.menu);
}
@@ -133,11 +133,11 @@ class Menu {
}
get width() {
- return this.menu.offsetWidth || 0;
+ return this.menu ? this.menu.offsetWidth : 0;
}
get height() {
- return this.menu.offsetHeight || 0;
+ return this.menu ? this.menu.offsetHeight : 0;
}
hide() {
@@ -184,6 +184,7 @@ class Menu {
this.hidden = !this.hidden;
const all = document.getElementsByClassName('menu');
for (const item of all) {
+ // @ts-ignore
item.style.display = this.hidden ? 'none' : 'block';
}
});
@@ -205,8 +206,10 @@ class Menu {
el.innerHTML = `${title}`;
if (this.container) this.container.appendChild(el);
el.addEventListener('change', (evt) => {
- object[variable] = evt.target.checked;
- if (callback) callback(evt.target.checked);
+ if (evt.target) {
+ object[variable] = evt.target['checked'];
+ if (callback) callback(evt.target['checked']);
+ }
});
return el;
}
@@ -225,7 +228,7 @@ class Menu {
el.style.fontVariant = document.body.style.fontVariant;
if (this.container) this.container.appendChild(el);
el.addEventListener('change', (evt) => {
- if (callback) callback(items[evt.target.selectedIndex]);
+ if (callback && evt.target) callback(items[evt.target['selectedIndex']]);
});
return el;
}
@@ -237,12 +240,13 @@ class Menu {
if (this.container) this.container.appendChild(el);
el.addEventListener('change', (evt) => {
if (evt.target) {
- object[variable] = parseInt(evt.target.value) === parseFloat(evt.target.value) ? parseInt(evt.target.value) : parseFloat(evt.target.value);
- evt.target.setAttribute('value', evt.target.value);
- if (callback) callback(evt.target.value);
+ object[variable] = parseInt(evt.target['value']) === parseFloat(evt.target['value']) ? parseInt(evt.target['value']) : parseFloat(evt.target['value']);
+ // @ts-ignore
+ evt.target.setAttribute('value', evt.target['value']);
+ if (callback) callback(evt.target['value']);
}
});
- el.input = el.children[0];
+ el['input'] = el.children[0];
return el;
}
@@ -302,9 +306,12 @@ class Menu {
// eslint-disable-next-line class-methods-use-this
async updateChart(id, values) {
if (!values || (values.length === 0)) return;
+ /** @type {HTMLCanvasElement} */
+ // @ts-ignore undefined
const canvas = document.getElementById(`menu-canvas-${id}`);
if (!canvas) return;
const ctx = canvas.getContext('2d');
+ if (!ctx) return;
ctx.fillStyle = theme.background;
ctx.fillRect(0, 0, canvas.width, canvas.height);
const width = canvas.width / values.length;
@@ -318,7 +325,7 @@ class Menu {
ctx.fillRect(i * width, 0, width - 4, canvas.height);
ctx.fillStyle = theme.background;
ctx.font = `${width / 1.5}px "Segoe UI"`;
- ctx.fillText(Math.round(values[i]), i * width + 1, canvas.height - 1, width - 1);
+ ctx.fillText(Math.round(values[i]).toString(), i * width + 1, canvas.height - 1, width - 1);
}
}
}
diff --git a/demo/index-worker.js b/demo/index-worker.js
index 1d8ca2b8..d416e4fc 100644
--- a/demo/index-worker.js
+++ b/demo/index-worker.js
@@ -1,12 +1,17 @@
-///
+/**
+ * Web worker used by main demo app
+ * Loaded from index.js
+ */
+
+///
// load Human using IIFE script as Chome Mobile does not support Modules as Workers
-// import Human from '../dist/human.esm.js';
+/** @type {Human} */
+const Human = {};
self.importScripts('../dist/human.js');
let busy = false;
-// @ts-ignore // Human is registered as global namespace using IIFE script
-// eslint-disable-next-line no-undef, new-cap
+// eslint-disable-next-line new-cap
const human = new Human.default();
onmessage = async (msg) => { // receive message from main thread
diff --git a/demo/multithread/index.js b/demo/multithread/index.js
index 8bd5220e..e26acd2d 100644
--- a/demo/multithread/index.js
+++ b/demo/multithread/index.js
@@ -4,9 +4,8 @@
* @description Demo app that enables all Human modules and runs them in separate worker threads
*
*/
-// @ts-nocheck // typescript checks disabled as this is pure javascript
-import Human from '../../dist/human.esm.js'; // equivalent of @vladmandic/human
+import Human from '../../dist/human.custom.esm.js'; // equivalent of @vladmandic/human
import GLBench from '../helpers/gl-bench.js';
const workerJS = './worker.js';
@@ -92,9 +91,13 @@ const busy = {
};
const workers = {
+ /** @type {Worker | null} */
face: null,
+ /** @type {Worker | null} */
body: null,
+ /** @type {Worker | null} */
hand: null,
+ /** @type {Worker | null} */
object: null,
};
@@ -138,7 +141,8 @@ async function drawResults() {
time.draw = Math.round(1 + human.now() - start.draw);
const fps = Math.round(10 * 1000 / time.main) / 10;
const draw = Math.round(10 * 1000 / time.draw) / 10;
- document.getElementById('log').innerText = `Human: version ${human.version} | Performance: Main ${time.main}ms Face: ${time.face}ms Body: ${time.body}ms Hand: ${time.hand}ms Object ${time.object}ms | FPS: ${fps} / ${draw}`;
+ const div = document.getElementById('log');
+ if (div) div.innerText = `Human: version ${human.version} | Performance: Main ${time.main}ms Face: ${time.face}ms Body: ${time.body}ms Hand: ${time.hand}ms Object ${time.object}ms | FPS: ${fps} / ${draw}`;
requestAnimationFrame(drawResults);
}
@@ -152,7 +156,7 @@ async function runDetection() {
start.main = human.now();
if (!bench) {
bench = new GLBench(null, { trackGPU: false, chartHz: 20, chartLen: 20 });
- bench.begin();
+ bench.begin('human');
}
const ctx = canvas.getContext('2d');
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
@@ -160,22 +164,22 @@ async function runDetection() {
if (!busy.face) {
busy.face = true;
start.face = human.now();
- workers.face.postMessage({ image: imageData.data.buffer, width: canvas.width, height: canvas.height, config: config.face, type: 'face' }, [imageData.data.buffer.slice(0)]);
+ if (workers.face) workers.face.postMessage({ image: imageData.data.buffer, width: canvas.width, height: canvas.height, config: config.face, type: 'face' }, [imageData.data.buffer.slice(0)]);
}
if (!busy.body) {
busy.body = true;
start.body = human.now();
- workers.body.postMessage({ image: imageData.data.buffer, width: canvas.width, height: canvas.height, config: config.body, type: 'body' }, [imageData.data.buffer.slice(0)]);
+ if (workers.body) workers.body.postMessage({ image: imageData.data.buffer, width: canvas.width, height: canvas.height, config: config.body, type: 'body' }, [imageData.data.buffer.slice(0)]);
}
if (!busy.hand) {
busy.hand = true;
start.hand = human.now();
- workers.hand.postMessage({ image: imageData.data.buffer, width: canvas.width, height: canvas.height, config: config.hand, type: 'hand' }, [imageData.data.buffer.slice(0)]);
+ if (workers.hand) workers.hand.postMessage({ image: imageData.data.buffer, width: canvas.width, height: canvas.height, config: config.hand, type: 'hand' }, [imageData.data.buffer.slice(0)]);
}
if (!busy.object) {
busy.object = true;
start.object = human.now();
- workers.object.postMessage({ image: imageData.data.buffer, width: canvas.width, height: canvas.height, config: config.object, type: 'object' }, [imageData.data.buffer.slice(0)]);
+ if (workers.object) workers.object.postMessage({ image: imageData.data.buffer, width: canvas.width, height: canvas.height, config: config.object, type: 'object' }, [imageData.data.buffer.slice(0)]);
}
time.main = Math.round(human.now() - start.main);
@@ -204,27 +208,29 @@ async function setupCamera() {
try {
stream = await navigator.mediaDevices.getUserMedia(constraints);
} catch (err) {
- output.innerText += `\n${err.name}: ${err.message}`;
- status(err.name);
+ if (output) output.innerText += `\n${err.name}: ${err.message}`;
log('camera error:', err);
}
- const tracks = stream.getVideoTracks();
- log('enumerated viable tracks:', tracks);
- const track = stream.getVideoTracks()[0];
- const settings = track.getSettings();
- log('selected video source:', track, settings);
+ if (stream) {
+ const tracks = stream.getVideoTracks();
+ log('enumerated viable tracks:', tracks);
+ const track = stream.getVideoTracks()[0];
+ const settings = track.getSettings();
+ log('selected video source:', track, settings);
+ } else {
+ log('missing video stream');
+ }
const promise = !stream || new Promise((resolve) => {
video.onloadeddata = () => {
- if (settings.width > settings.height) canvas.style.width = '100vw';
- else canvas.style.height = '100vh';
+ canvas.style.height = '100vh';
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
video.play();
- resolve();
+ resolve(true);
};
});
// attach input to video element
- if (stream) video.srcObject = stream;
+ if (stream && video) video['srcObject'] = stream;
return promise;
}
@@ -240,21 +246,13 @@ async function startWorkers() {
}
async function main() {
- window.addEventListener('unhandledrejection', (evt) => {
- // eslint-disable-next-line no-console
- console.error(evt.reason || evt);
- document.getElementById('log').innerHTML = evt.reason.message || evt.reason || evt;
- status('exception error');
- evt.preventDefault();
- });
-
if (typeof Worker === 'undefined' || typeof OffscreenCanvas === 'undefined') {
- status('workers are not supported');
return;
}
human = new Human(config.main);
- document.getElementById('log').innerText = `Human: version ${human.version}`;
+ const div = document.getElementById('log');
+ if (div) div.innerText = `Human: version ${human.version}`;
await startWorkers();
await setupCamera();
diff --git a/demo/multithread/worker.js b/demo/multithread/worker.js
index 3314ae64..79ddf65c 100644
--- a/demo/multithread/worker.js
+++ b/demo/multithread/worker.js
@@ -1,8 +1,6 @@
-// load Human using IIFE script as Chome Mobile does not support Modules as Workers
-
///
-// import Human from '../dist/human.esm.js';
+// load Human using IIFE script as Chome Mobile does not support Modules as Workers
self.importScripts('../../dist/human.js');
let human;
diff --git a/package.json b/package.json
index 82267f1e..ebfa963e 100644
--- a/package.json
+++ b/package.json
@@ -66,16 +66,18 @@
"@tensorflow/tfjs-layers": "^3.10.0",
"@tensorflow/tfjs-node": "^3.10.0",
"@tensorflow/tfjs-node-gpu": "^3.10.0",
- "@types/node": "^16.11.5",
+ "@types/node": "^16.11.6",
"@typescript-eslint/eslint-plugin": "^5.2.0",
"@typescript-eslint/parser": "^5.2.0",
"@vladmandic/build": "^0.6.3",
"@vladmandic/pilogger": "^0.3.3",
"canvas": "^2.8.0",
"dayjs": "^1.10.7",
+ "long": "^4.0.0",
"esbuild": "^0.13.9",
"eslint": "8.1.0",
"eslint-config-airbnb-base": "^14.2.1",
+ "eslint-plugin-html": "^6.2.0",
"eslint-plugin-import": "^2.25.2",
"eslint-plugin-json": "^3.1.0",
"eslint-plugin-node": "^11.1.0",
@@ -88,6 +90,5 @@
"typescript": "4.4.4"
},
"dependencies": {
- "long": "^4.0.0"
}
}
diff --git a/src/face/match.ts b/src/face/match.ts
index 63692217..40d6d090 100644
--- a/src/face/match.ts
+++ b/src/face/match.ts
@@ -1,5 +1,6 @@
/** Face descriptor type as number array */
export type Descriptor = Array
+export type Options = { order?: number, threshold?: number, multiplier?: number } | undefined;
/** Calculates distance between two descriptors
* @param {object} options
@@ -9,12 +10,12 @@ export type Descriptor = Array
* - default is 20 which normalizes results to similarity above 0.5 can be considered a match
* @returns {number}
*/
-export function distance(descriptor1: Descriptor, descriptor2: Descriptor, options = { order: 2, multiplier: 20 }) {
+export function distance(descriptor1: Descriptor, descriptor2: Descriptor, options: Options = { order: 2, multiplier: 20 }) {
// general minkowski distance, euclidean distance is limited case where order is 2
let sum = 0;
for (let i = 0; i < descriptor1.length; i++) {
- const diff = (options.order === 2) ? (descriptor1[i] - descriptor2[i]) : (Math.abs(descriptor1[i] - descriptor2[i]));
- sum += (options.order === 2) ? (diff * diff) : (diff ** options.order);
+ const diff = (!options.order || options.order === 2) ? (descriptor1[i] - descriptor2[i]) : (Math.abs(descriptor1[i] - descriptor2[i]));
+ sum += (!options.order || options.order === 2) ? (diff * diff) : (diff ** options.order);
}
return (options.multiplier || 20) * sum;
}
@@ -27,9 +28,9 @@ export function distance(descriptor1: Descriptor, descriptor2: Descriptor, optio
* - default is 20 which normalizes results to similarity above 0.5 can be considered a match
* @returns {number} similarity between two face descriptors normalized to 0..1 range where 0 is no similarity and 1 is perfect similarity
*/
-export function similarity(descriptor1: Descriptor, descriptor2: Descriptor, options = { order: 2, multiplier: 20 }) {
+export function similarity(descriptor1: Descriptor, descriptor2: Descriptor, options: Options = { order: 2, multiplier: 20 }) {
const dist = distance(descriptor1, descriptor2, options);
- const root = (options.order === 2) ? Math.sqrt(dist) : dist ** (1 / options.order);
+ const root = (!options.order || options.order === 2) ? Math.sqrt(dist) : dist ** (1 / options.order);
const invert = Math.max(0, 100 - root) / 100.0;
return invert;
}
@@ -45,7 +46,7 @@ export function similarity(descriptor1: Descriptor, descriptor2: Descriptor, opt
* - {@link distance} calculated `distance` of given descriptor to the best match
* - {@link similarity} calculated normalized `similarity` of given descriptor to the best match
*/
-export function match(descriptor: Descriptor, descriptors: Array, options = { order: 2, threshold: 0, multiplier: 20 }) {
+export function match(descriptor: Descriptor, descriptors: Array, options: Options = { order: 2, multiplier: 20, threshold: 0 }) {
if (!Array.isArray(descriptor) || !Array.isArray(descriptors) || descriptor.length < 64 || descriptors.length === 0 || descriptor.length !== descriptors[0].length) { // validate input
return { index: -1, distance: Number.POSITIVE_INFINITY, similarity: 0 };
}
@@ -57,8 +58,8 @@ export function match(descriptor: Descriptor, descriptors: Array, op
best = res;
index = i;
}
- if (best < options.threshold) break;
+ if (best < (options.threshold || 0)) break;
}
- best = (options.order === 2) ? Math.sqrt(best) : best ** (1 / options.order);
+ best = (!options.order || options.order === 2) ? Math.sqrt(best) : best ** (1 / options.order);
return { index, distance: best, similarity: Math.max(0, 100 - best) / 100.0 };
}
diff --git a/src/human.ts b/src/human.ts
index 1338aa42..4bfaf576 100644
--- a/src/human.ts
+++ b/src/human.ts
@@ -212,7 +212,7 @@ export class Human {
}
/** Validate current configuration schema */
- public validate(userConfig?: Partial) {
+ validate(userConfig?: Partial) {
return validate(defaults, userConfig || this.config);
}
@@ -294,7 +294,7 @@ export class Human {
await tf.ready();
if (this.env.browser) {
if (this.config.debug) log('configuration:', this.config);
- if (this.config.debug) log('tf flags:', this.tf.ENV.flags);
+ if (this.config.debug) log('tf flags:', this.tf.ENV['flags']);
}
}
diff --git a/test/browser.html b/test/browser.html
index 77f2a482..94457126 100644
--- a/test/browser.html
+++ b/test/browser.html
@@ -34,7 +34,7 @@
debug: true,
cacheSensitivity: 0,
object: { enabled: true },
- }
+ };
const backends = ['wasm', 'webgl', 'humangl', 'webgpu'];
@@ -55,7 +55,8 @@
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);
+ document.getElementById('log').innerHTML += ts + ' +' + elap + 'ms  ' + str(...msgs);
+ // eslint-disable-next-line no-console
console.log(ts, elap, ...msgs);
last = dt;
}
@@ -63,7 +64,7 @@
async function image(url) {
const el = document.createElement('img');
el.id = 'image';
- const loaded = new Promise((resolve) => { el.onload = () => resolve(true) });
+ const loaded = new Promise((resolve) => { el.onload = () => resolve(true); });
el.src = url;
await loaded;
return el;
@@ -88,7 +89,7 @@
async function main() {
log('human tests');
let res;
- let human = new Human(config);
+ const human = new Human(config);
await human.init();
human.events.addEventListener('warmup', () => events('warmup'));
human.events.addEventListener('image', () => events('image'));
@@ -110,7 +111,7 @@
log({ memory: human.tf.memory() });
res = await human.validate();
log({ validate: res });
- res = await human.warmup({ warmup: 'face'});
+ res = await human.warmup({ warmup: 'face' });
draw(res.canvas);
log({ warmup: 'face' });
let img = await image('../../samples/in/ai-body.jpg');
@@ -119,11 +120,11 @@
draw(res.canvas);
res = await human.detect(input.tensor);
log({ detect: true });
- const interpolated = human.next();
+ human.next();
log({ interpolated: true });
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({ 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();
diff --git a/tsconfig.json b/tsconfig.json
index aa352137..f4daaa72 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -6,6 +6,7 @@
"outDir": "types",
"baseUrl": "./",
"paths": { "tslib": ["./node_modules/tslib/tslib.d.ts"] },
+ "lib": ["es2020", "dom", "webworker"],
"allowJs": true,
"allowSyntheticDefaultImports": false,
"allowUnreachableCode": false,
@@ -50,7 +51,7 @@
"tabSize": 2
},
"exclude": ["node_modules/", "types/", "tfjs/", "dist/"],
- "include": ["src"],
+ "include": ["src", "types/human.d.ts"],
"typedocOptions": {
"externalPattern": ["node_modules/", "tfjs/"]
}
diff --git a/wiki b/wiki
index 82ade650..20389b97 160000
--- a/wiki
+++ b/wiki
@@ -1 +1 @@
-Subproject commit 82ade650a7cd593e29a98a8b8a1cba893e14c2f0
+Subproject commit 20389b9779834324acbbcf2b25041a489a688d18