Compare commits

..

No commits in common. "main" and "3.2.1" have entirely different histories.
main ... 3.2.1

176 changed files with 24680 additions and 19364 deletions

View File

@ -1,8 +1,9 @@
{
"$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-data", "@tensorflow/tfjs-layers", "@tensorflow/tfjs-converter"],
"compiler": {
"skipLibCheck": true
"skipLibCheck": false
},
"newlineKind": "lf",
"dtsRollup": {

View File

@ -1,9 +1,5 @@
{
"globals": {
},
"rules": {
"@typescript-eslint/no-require-imports":"off"
},
"globals": {},
"overrides": [
{
"files": ["**/*.ts"],
@ -19,10 +15,10 @@
"extends": [
"airbnb-base",
"eslint:recommended",
"plugin:@typescript-eslint/strict",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"plugin:@typescript-eslint/recommended-requiring-type-checking",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/strict",
"plugin:import/recommended",
"plugin:promise/recommended"
],
@ -30,12 +26,9 @@
"@typescript-eslint/ban-ts-comment":"off",
"@typescript-eslint/dot-notation":"off",
"@typescript-eslint/no-empty-interface":"off",
"@typescript-eslint/no-empty-object-type":"off",
"@typescript-eslint/no-inferrable-types":"off",
"@typescript-eslint/no-misused-promises":"off",
"@typescript-eslint/no-require-imports":"off",
"@typescript-eslint/no-unnecessary-condition":"off",
"@typescript-eslint/no-unnecessary-type-assertion":"off",
"@typescript-eslint/no-unsafe-argument":"off",
"@typescript-eslint/no-unsafe-assignment":"off",
"@typescript-eslint/no-unsafe-call":"off",
@ -162,7 +155,26 @@
"node": false,
"es2021": false
},
"extends": []
"extends": [
"plugin:json/recommended"
]
},
{
"files": ["**/*.html"],
"parserOptions": { "sourceType": "module", "ecmaVersion": "latest" },
"parser": "@html-eslint/parser",
"plugins": ["html", "@html-eslint"],
"env": {
"browser": true,
"commonjs": false,
"node": false,
"es2021": false
},
"extends": ["plugin:@html-eslint/recommended"],
"rules": {
"@html-eslint/element-newline":"off",
"@html-eslint/indent": ["error", 2]
}
},
{
"files": ["**/*.md"],

2
.gitignore vendored
View File

@ -5,5 +5,3 @@ package-lock.json
*.swp
samples/**/*.mp4
samples/**/*.webm
temp
tmp

1
.npmrc
View File

@ -2,4 +2,3 @@ force=true
omit=dev
legacy-peer-deps=true
strict-peer-dependencies=false
node-options='--no-deprecation'

View File

@ -1,6 +1,6 @@
# @vladmandic/human
Version: **3.3.6**
Version: **3.2.1**
Description: **Human: AI-powered 3D Face Detection & Rotation Tracking, Face Description & Recognition, Body Pose Tracking, 3D Hand & Finger Tracking, Iris Analysis, Age & Gender & Emotion Prediction, Gesture Recognition**
Author: **Vladimir Mandic <mandic00@live.com>**
@ -9,47 +9,12 @@
## Changelog
### **3.3.6** 2025/08/26 mandic00@live.com
### **origin/main** 2025/02/05 mandic00@live.com
- full rebuild
### **3.3.5** 2025/02/05 mandic00@live.com
- rebuild
- add human.draw.tensor method
### **3.3.4** 2024/10/24 mandic00@live.com
### **3.3.3** 2024/10/14 mandic00@live.com
- add loaded property to model stats and mark models not loaded correctly.
- release build
### **3.3.2** 2024/09/11 mandic00@live.com
- full rebuild
### **3.3.1** 2024/09/11 mandic00@live.com
- add config.face.detector.square option
- human 3.3 alpha test run
- human 3.3 alpha with new build environment
- release rebuild
- fix flazeface tensor scale and update build platform
### **3.2.2** 2024/04/17 mandic00@live.com
### **release: 3.2.1** 2024/02/15 mandic00@live.com
### **3.2.1** 2024/02/15 mandic00@live.com
### **origin/main** 2023/12/06 mandic00@live.com
### **3.2.0** 2023/12/06 mandic00@live.com
- set browser false when navigator object is empty

View File

@ -4,6 +4,7 @@
![Last Commit](https://img.shields.io/github/last-commit/vladmandic/human?style=flat-square&svg=true)
![License](https://img.shields.io/github/license/vladmandic/human?style=flat-square&svg=true)
![GitHub Status Checks](https://img.shields.io/github/checks-status/vladmandic/human/main?style=flat-square&svg=true)
![Vulnerabilities](https://img.shields.io/snyk/vulnerabilities/github/vladmandic/human?style=flat-square&svg=true)
# Human Library
@ -30,20 +31,15 @@
## Compatibility
**Browser**:
- Compatible with both desktop and mobile platforms
- Compatible with *WebGPU*, *WebGL*, *WASM*, *CPU* backends
- Compatible with *WebWorker* execution
- Compatible with *WebView*
- Primary platform: *Chromium*-based browsers
- Secondary platform: *Firefox*, *Safari*
**NodeJS**:
- Compatibile with *WASM* backend for executions on architectures where *tensorflow* binaries are not available
- Compatible with *tfjs-node* using software execution via *tensorflow* shared libraries
- Compatible with *tfjs-node* using GPU-accelerated execution via *tensorflow* shared libraries and nVidia CUDA
- Supported versions are from **14.x** to **22.x**
- NodeJS version **23.x** is not supported due to breaking changes and issues with `@tensorflow/tfjs`
- **Browser**:
Compatible with both desktop and mobile platforms
Compatible with *CPU*, *WebGL*, *WASM* backends
Compatible with *WebWorker* execution
Compatible with *WebView*
- **NodeJS**:
Compatibile with *WASM* backend for executions on architectures where *tensorflow* binaries are not available
Compatible with *tfjs-node* using software execution via *tensorflow* shared libraries
Compatible with *tfjs-node* using GPU-accelerated execution via *tensorflow* shared libraries and nVidia CUDA
<br>

View File

@ -10,13 +10,12 @@ import { Human } from '../../dist/human.esm.js';
let loader;
const humanConfig = { // user configuration for human, used to fine-tune behavior
cacheSensitivity: 0,
debug: true,
modelBasePath: 'https://vladmandic.github.io/human-models/models/',
filter: { enabled: true, equalization: false, flip: false },
face: {
enabled: true,
detector: { rotation: false, maxDetected: 100, minConfidence: 0.2, return: true, square: false },
detector: { rotation: false, maxDetected: 100, minConfidence: 0.2, return: true },
iris: { enabled: true },
description: { enabled: true },
emotion: { enabled: true },
@ -94,7 +93,7 @@ function addFace(face, source) {
e.preventDefault();
document.getElementById('description').innerHTML = canvas.title;
};
human.draw.tensor(face.tensor, canvas);
human.tf.browser.draw(face.tensor, canvas);
human.tf.dispose(face.tensor);
return canvas;
}
@ -150,7 +149,7 @@ async function main() {
showLoader('compiling models');
await human.warmup();
showLoader('loading images');
const images = ['group-1.jpg', 'group-2.jpg', 'group-3.jpg', 'group-4.jpg', 'group-5.jpg', 'group-6.jpg', 'group-7.jpg', 'solvay1927.jpg', 'stock-group-1.jpg', 'stock-group-2.jpg', 'stock-models-6.jpg', 'stock-models-7.jpg'];
const images = ['group-1.jpg', 'group-2.jpg', 'group-3.jpg', 'group-4.jpg', 'group-5.jpg', 'group-6.jpg', 'group-7.jpg', 'solvay1927.jpg', 'stock-group-1.jpg', 'stock-group-2.jpg'];
const imageUris = images.map((a) => `../../samples/in/${a}`);
for (let i = 0; i < imageUris.length; i++) addImage(imageUris[i]);
initDragAndDrop();

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -11,7 +11,7 @@ import * as H from '../../dist/human.esm.js'; // equivalent of @vladmandic/Human
import * as indexDb from './indexdb'; // methods to deal with indexdb
const humanConfig = { // user configuration for human, used to fine-tune behavior
cacheSensitivity: 0.01,
cacheSensitivity: 0,
modelBasePath: '../../models',
filter: { enabled: true, equalization: true }, // lets run with histogram equilizer
debug: true,
@ -240,7 +240,7 @@ async function detectFace() {
if (!current?.face?.tensor || !current?.face?.embedding) return false;
console.log('face record:', current.face); // eslint-disable-line no-console
log(`detected face: ${current.face.gender} ${current.face.age || 0}y distance ${100 * (current.face.distance || 0)}cm/${Math.round(100 * (current.face.distance || 0) / 2.54)}in`);
await human.draw.tensor(current.face.tensor, dom.canvas);
await human.tf.browser.draw(current.face.tensor, dom.canvas);
if (await indexDb.count() === 0) {
log('face database is empty: nothing to compare face with');
document.body.style.background = 'black';

View File

@ -11,7 +11,7 @@ const userConfig = {
backend: 'humangl',
async: true,
warmup: 'none',
cacheSensitivity: 0.01,
cacheSensitivity: 0,
debug: true,
modelBasePath: '../../models/',
deallocate: true,
@ -70,7 +70,7 @@ async function selectFaceCanvas(face) {
if (face.tensor) {
title('Sorting Faces by Similarity');
const c = document.getElementById('orig');
await human.draw.tensor(face.tensor, c);
await human.tf.browser.draw(face.tensor, c);
const arr = db.map((rec) => rec.embedding);
const res = await human.match.find(face.embedding, arr);
log('Match:', db[res.index].name);
@ -97,7 +97,7 @@ async function selectFaceCanvas(face) {
canvas.tag.similarity = similarity;
// get best match
// draw the canvas
await human.draw.tensor(current.tensor, canvas);
await human.tf.browser.draw(current.tensor, canvas);
const ctx = canvas.getContext('2d');
ctx.font = 'small-caps 1rem "Lato"';
ctx.fillStyle = 'rgba(0, 0, 0, 1)';
@ -144,7 +144,7 @@ async function addFaceCanvas(index, res, fileName) {
gender: ${Math.round(100 * res.face[i].genderScore)}% ${res.face[i].gender}
emotion: ${emotion}
`.replace(/ /g, ' ');
await human.draw.tensor(res.face[i].tensor, canvas);
await human.tf.browser.draw(res.face[i].tensor, canvas);
const ctx = canvas.getContext('2d');
if (!ctx) return;
ctx.font = 'small-caps 0.8rem "Lato"';

View File

@ -223,7 +223,7 @@ async function calcSimmilarity(result) {
log('setting face compare baseline:', result.face[0]);
if (result.face[0].tensor) {
const c = document.getElementById('orig');
human.draw.tensor(result.face[0].tensor, c);
human.tf.browser.draw(result.face[0].tensor, c);
} else {
document.getElementById('compare-canvas').getContext('2d').drawImage(compare.original.canvas, 0, 0, 200, 200);
}

View File

@ -1,70 +0,0 @@
const fs = require('fs');
const process = require('process');
const log = require('@vladmandic/pilogger'); // eslint-disable-line node/no-unpublished-require
const tf = require('@tensorflow/tfjs-node'); // eslint-disable-line node/no-unpublished-require
const Human = require('../../dist/human.node.js');
const humanConfig = {
debug: false,
face: {
enabled: true,
detector: { enabled: true, modelPath: 'blazeface.json' },
description: { enabled: true, modelPath: 'faceres.json' },
// gear: { enabled: true, modelPath: '/home/vlado/dev/human-models/models/gear.json' },
// ssrnet: { enabled: true, modelPathAge: '/home/vlado/dev/human-models/models/age.json', modelPathGender: '/home/vlado/dev/human-models/models/gender.json' },
emotion: { enabled: false },
mesh: { enabled: false },
iris: { enabled: false },
antispoof: { enabled: false },
liveness: { enabled: false },
},
body: { enabled: false },
hand: { enabled: false },
gesture: { enabled: false },
};
const human = new Human.Human(humanConfig);
const ageThreshold = 18;
async function detect(inputFile) {
try {
const buffer = fs.readFileSync(inputFile);
const tensor = human.tf.node.decodeImage(buffer);
const result = await human.detect(tensor);
human.tf.dispose(tensor);
if (!result || !result.face || result.face.length === 0) return false;
let msg = ` file=${inputFile} resolution=${tensor.shape}`;
for (const face of result.face) {
msg = ` file=${inputFile} resolution=${tensor.shape} age=${face.age} gender=${face.gender} confidence=${face.genderScore}`;
if (face.age < ageThreshold) {
log.warn('fail:' + msg);
return true;
}
}
log.info('pass: ' + msg);
return false;
} catch (err) {
log.error(`error: file=${inputFile}: ${err}`);
}
return false;
}
async function main() {
log.info(`Human: version=${human.version} tf=${tf.version_core}`);
process.noDeprecation = true;
if (process.argv.length < 3) return;
await human.load();
await human.warmup();
const t0 = performance.now();
const args = process.argv.slice(2);
let pass = 0;
let fail = 0;
for (const arg of args) {
const ok = await detect(arg);
if (ok) pass++;
else fail++;
}
const t1 = performance.now();
log.info(`Human: files=${args.length} pass=${pass} fail=${fail} time=${Math.round(t1 - t0)} fps=${Math.round(10000 * args.length / (t1 - t0)) / 10}`);
}
main();

View File

@ -7,7 +7,7 @@ const log = require('@vladmandic/pilogger'); // eslint-disable-line node/no-unpu
const canvas = require('canvas'); // eslint-disable-line node/no-unpublished-require
const config = {
cacheSensitivity: 0.01,
cacheSensitivity: 0,
wasmPlatformFetch: true,
modelBasePath: 'https://vladmandic.github.io/human-models/models/',
};

View File

@ -24,7 +24,6 @@ const config = { // just enable all and leave default settings
async function main() {
log.header();
process.noDeprecation = true;
globalThis.Canvas = canvas.Canvas; // patch global namespace with canvas library
globalThis.ImageData = canvas.ImageData; // patch global namespace with canvas library

View File

@ -45,7 +45,6 @@ async function detect(input) {
}
async function main() {
process.noDeprecation = true;
log.configure({ inspect: { breakLength: 265 } });
log.header();
if (process.argv.length !== 4) {

View File

@ -17,7 +17,6 @@ const humanConfig = {
};
async function detect(inputFile) {
process.noDeprecation = true;
const human = new Human.Human(humanConfig); // create instance of human using default configuration
console.log('Human:', human.version, 'TF:', tf.version_core); // eslint-disable-line no-console
await human.load(); // optional as models would be loaded on-demand first time they are required

View File

@ -76,7 +76,6 @@ async function detect(jpegBuffer) {
async function main() {
log.header();
process.noDeprecation = true;
await human.tf.ready();
// pre-load models
log.info({ human: human.version, tf: human.tf.version_core });

View File

@ -92,7 +92,7 @@ async function detect(input) {
try {
result = await human.detect(tensor, myConfig);
} catch (err) {
log.error('caught', err);
log.error('caught');
}
// dispose image tensor as we no longer need it
@ -187,7 +187,6 @@ async function test() {
async function main() {
log.configure({ inspect: { breakLength: 265 } });
log.header();
process.noDeprecation = true;
log.info('Current folder:', process.env.PWD);
await init();
const f = process.argv[2];

View File

@ -20,7 +20,7 @@ const config = { // just enable all and leave default settings
modelBasePath: 'file://models',
debug: true,
softwareKernels: true, // slower but enhanced precision since face rotation can work in software mode in nodejs environments
cacheSensitivity: 0.01,
cacheSensitivity: 0,
face: { enabled: true, detector: { maxDetected: 100, minConfidence: 0.1 } },
object: { enabled: true, maxDetected: 100, minConfidence: 0.1 },
gesture: { enabled: true },
@ -77,7 +77,6 @@ async function main() {
globalThis.ImageData = canvas.ImageData; // patch global namespace with canvas library
log.info('Human:', human.version, 'TF:', tf.version_core);
process.noDeprecation = true;
const configErrors = await human.validate();
if (configErrors.length > 0) log.error('Configuration errors:', configErrors);
await human.load(); // pre-load models

View File

@ -20,7 +20,7 @@
body { font-size: 1rem; font-family: "CenturyGothic", "Segoe UI", sans-serif; font-variant: small-caps; width: -webkit-fill-available; height: 100%; background: black; color: white; overflow: hidden; margin: 0; }
select { font-size: 1rem; font-family: "CenturyGothic", "Segoe UI", sans-serif; font-variant: small-caps; background: gray; color: white; border: none; }
</style>
<script src="../segmentation/index.js" type="module"></script>
<script src="../segmentation/index.js" type="module"></script>
</head>
<body>
<noscript><h1>javascript is required</h1></noscript>

View File

@ -85,7 +85,7 @@ async function main() {
return;
}
dom.fps.innerText = `fps: ${Math.round(10000 / (t1 - t0)) / 10}`; // mark performance
human.draw.tensor(rgba, dom.output); // draw raw output
human.tf.browser.draw(rgba, dom.output); // draw raw output
human.tf.dispose(rgba); // dispose tensors
ctxMerge.globalCompositeOperation = 'source-over';
ctxMerge.drawImage(dom.background, 0, 0); // draw original video to first stacked canvas

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

32286
dist/human.esm.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

1438
dist/human.js vendored

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

22
dist/human.node.js vendored

File diff suppressed because one or more lines are too long

1450
dist/tfjs.esm.js vendored

File diff suppressed because one or more lines are too long

View File

@ -4,4 +4,4 @@
author: <https://github.com/vladmandic>'
*/
var e="4.22.0";var s="4.22.0";var t="4.22.0";var n="4.22.0";var r="4.22.0";var i="4.22.0";var h={tfjs:e,"tfjs-core":e,"tfjs-converter":s,"tfjs-backend-cpu":t,"tfjs-backend-webgl":n,"tfjs-backend-wasm":r,"tfjs-backend-webgpu":i};export{h as version};
var e="4.17.0";var s="4.17.0";var t="4.17.0";var n="4.17.0";var r="4.17.0";var i="4.14.0";var h={tfjs:e,"tfjs-core":e,"tfjs-converter":s,"tfjs-backend-cpu":t,"tfjs-backend-webgl":n,"tfjs-backend-wasm":r,"tfjs-backend-webgpu":i};export{h as version};

View File

@ -1,6 +1,6 @@
{
"name": "@vladmandic/human",
"version": "3.3.6",
"version": "3.2.1",
"description": "Human: AI-powered 3D Face Detection & Rotation Tracking, Face Description & Recognition, Body Pose Tracking, 3D Hand & Finger Tracking, Iris Analysis, Age & Gender & Emotion Prediction, Gesture Recognition",
"sideEffects": false,
"main": "dist/human.node.js",
@ -8,7 +8,13 @@
"browser": "dist/human.esm.js",
"types": "types/human.d.ts",
"exports": {
"node": "./dist/human.node.js",
"node": {
"require": "./dist/human.node.js",
"import": "./dist/human.node.js",
"module": "./dist/human.node.js"
},
"require": "./dist/human.node.js",
"import": "./dist/human.esm.js",
"script": "./dist/human.js",
"module": "./dist/human.esm.js",
"types": "./types/human.d.ts",
@ -23,9 +29,7 @@
"dist/human.node-wasm": "./dist/human.node-wasm.js",
"dist/human.node-wasm.js": "./dist/human.node-wasm.js",
"dist/human.node-gpu": "./dist/human.node-gpu.js",
"dist/human.node-gpu.js": "./dist/human.node-gpu.js",
"require": "./dist/human.node.js",
"import": "./dist/human.esm.js"
"dist/human.node-gpu.js": "./dist/human.node-gpu.js"
},
"author": "Vladimir Mandic <mandic00@live.com>",
"bugs": {
@ -74,40 +78,39 @@
"tensorflow"
],
"devDependencies": {
"@html-eslint/eslint-plugin": "^0.46.1",
"@html-eslint/parser": "^0.46.0",
"@microsoft/api-extractor": "^7.52.11",
"@tensorflow/tfjs-backend-cpu": "^4.22.0",
"@tensorflow/tfjs-backend-wasm": "^4.22.0",
"@tensorflow/tfjs-backend-webgl": "^4.22.0",
"@tensorflow/tfjs-backend-webgpu": "4.22.0",
"@tensorflow/tfjs-converter": "^4.22.0",
"@tensorflow/tfjs-core": "^4.22.0",
"@tensorflow/tfjs-data": "^4.22.0",
"@tensorflow/tfjs-layers": "^4.22.0",
"@tensorflow/tfjs-node": "^4.22.0",
"@tensorflow/tfjs-node-gpu": "^4.22.0",
"@types/emscripten": "^1.40.1",
"@types/node": "^24.3.0",
"@html-eslint/eslint-plugin": "^0.21.0",
"@html-eslint/parser": "^0.21.0",
"@microsoft/api-extractor": "^7.40.1",
"@tensorflow/tfjs-backend-cpu": "^4.17.0",
"@tensorflow/tfjs-backend-wasm": "^4.17.0",
"@tensorflow/tfjs-backend-webgl": "^4.17.0",
"@tensorflow/tfjs-backend-webgpu": "4.14.0",
"@tensorflow/tfjs-converter": "^4.17.0",
"@tensorflow/tfjs-core": "^4.17.0",
"@tensorflow/tfjs-data": "^4.17.0",
"@tensorflow/tfjs-layers": "^4.17.0",
"@tensorflow/tfjs-node": "^4.17.0",
"@tensorflow/tfjs-node-gpu": "^4.17.0",
"@types/node": "^20.11.19",
"@types/offscreencanvas": "^2019.7.3",
"@typescript-eslint/eslint-plugin": "^8.41.0",
"@typescript-eslint/parser": "^8.41.0",
"@vladmandic/build": "^0.10.3",
"@vladmandic/pilogger": "^0.5.2",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"@typescript-eslint/parser": "^6.21.0",
"@vladmandic/build": "^0.9.3",
"@vladmandic/pilogger": "^0.4.9",
"@vladmandic/tfjs": "github:vladmandic/tfjs",
"canvas": "^3.2.0",
"esbuild": "^0.25.9",
"eslint": "8.57.0",
"canvas": "^2.11.2",
"esbuild": "^0.19.12",
"eslint": "8.55.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-plugin-html": "^8.1.3",
"eslint-plugin-import": "^2.32.0",
"eslint-plugin-json": "^4.0.1",
"eslint-plugin-markdown": "^5.1.0",
"eslint-plugin-html": "^7.1.0",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-json": "^3.1.0",
"eslint-plugin-markdown": "^3.0.1",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^7.2.1",
"rimraf": "^6.0.1",
"tslib": "^2.8.1",
"typedoc": "0.28.11",
"typescript": "5.9.2"
"eslint-plugin-promise": "^6.1.1",
"rimraf": "^5.0.5",
"tslib": "^2.6.2",
"typedoc": "0.25.4",
"typescript": "~5.3.3"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 164 KiB

After

Width:  |  Height:  |  Size: 178 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 150 KiB

After

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 59 KiB

View File

@ -1,7 +1,7 @@
/* eslint-disable no-multi-spaces */
/** Possible TensorFlow backends */
export type BackendEnum = '' | 'cpu' | 'wasm' | 'webgl' | 'humangl' | 'tensorflow' | 'webgpu' | 'none';
export type BackendEnum = '' | 'cpu' | 'wasm' | 'webgl' | 'humangl' | 'tensorflow' | 'webgpu';
/** Possible values for `human.warmup` */
export type WarmupEnum = '' | 'none' | 'face' | 'full' | 'body';
@ -39,8 +39,6 @@ export interface FaceDetectorConfig extends GenericConfig {
iouThreshold: number,
/** how much should face box be enlarged over the min/max facial coordinates */
scale: number,
/** automatically pad image to square */
square: boolean,
/** should child models perform on masked image of a face */
mask: boolean,
/** should face detection return processed and cropped face tensor that can with an external model for addtional processing?

View File

@ -2,7 +2,6 @@
* Module that implements helper draw functions, exposed as human.draw
*/
import * as tf from 'dist/tfjs.esm.js';
import { mergeDeep, now } from '../util/util';
import { env } from '../util/env';
import { getCanvasContext, rect } from './primitives';
@ -15,7 +14,6 @@ import { gesture } from './gesture';
import { defaultLabels } from './labels';
import type { Result, PersonResult } from '../result';
import type { AnyCanvas, DrawOptions } from '../exports';
import type { Tensor2D } from '../tfjs/types';
let drawTime = 0;
@ -62,22 +60,6 @@ export function canvas(input: AnyCanvas | HTMLImageElement | HTMLVideoElement, o
ctx.drawImage(input, 0, 0);
}
/** draw processed canvas */
export async function tensor(input: Tensor2D, output: HTMLCanvasElement) {
if (!input || !output) return;
if (!env.browser) return;
// const backend = tf.getBackend();
// if (backend === 'webgpu') tf.browser.draw(input, output);
// else await tf.browser.toPixels(input, output);
await tf.browser.toPixels(input, output);
// const ctx = getCanvasContext(output) as CanvasRenderingContext2D;
// if (!ctx) return;
// const image = await process(input);
// result.canvas = image.canvas;
// human.tf.dispose(image.tensor);
// ctx.drawImage(image.canvas, 0, 0);
}
/** meta-function that performs draw for: canvas, face, body, hand */
export async function all(inCanvas: AnyCanvas, result: Result, drawOptions?: Partial<DrawOptions>) {
if (!result?.performance || !inCanvas) return null;

View File

@ -60,9 +60,7 @@ export const calculateFaceAngle = (face: FaceResult, imageSize: [number, number]
let thetaZ: number;
if (r10 < 1) { // YZX calculation
if (r10 > -1) {
// thetaZ = Math.asin(r10);
const cosThetaZ = Math.sqrt(r00 * r00 + r20 * r20); // <https://github.com/vladmandic/human/issues/464>
thetaZ = Math.atan2(r10, cosThetaZ);
thetaZ = Math.asin(r10);
thetaY = Math.atan2(-r20, r00);
thetaX = Math.atan2(-r12, r11);
} else {
@ -78,9 +76,9 @@ export const calculateFaceAngle = (face: FaceResult, imageSize: [number, number]
if (Number.isNaN(thetaX)) thetaX = 0;
if (Number.isNaN(thetaY)) thetaY = 0;
if (Number.isNaN(thetaZ)) thetaZ = 0;
// return { pitch: 2 * -thetaX, yaw: 2 * -thetaY, roll: 2 * -thetaZ };
return { pitch: -thetaX, yaw: -thetaY, roll: -thetaZ };
return { pitch: 2 * -thetaX, yaw: 2 * -thetaY, roll: 2 * -thetaZ };
};
/*
const meshToEulerAngle = (mesh) => { // simple Euler angle calculation based existing 3D mesh
const radians = (a1, a2, b1, b2) => Math.atan2(b2 - a2, b1 - a1);

View File

@ -55,20 +55,9 @@ export async function getBoxes(inputImage: Tensor4D, config: Config): Promise<De
// sanity check on input
if ((!inputImage) || (inputImage['isDisposedInternal']) || (inputImage.shape.length !== 4) || (inputImage.shape[1] < 1) || (inputImage.shape[2] < 1)) return [];
const t: Record<string, Tensor> = {};
let pad = [0, 0];
let scale = [1, 1];
if (config?.face?.detector?.square) {
const xy = Math.max(inputImage.shape[2], inputImage.shape[1]);
pad = [Math.floor((xy - inputImage.shape[2]) / 2), Math.floor((xy - inputImage.shape[1]) / 2)];
t.padded = tf.pad(inputImage, [[0, 0], [pad[1], pad[1]], [pad[0], pad[0]], [0, 0]]);
scale = [inputImage.shape[2] / xy, inputImage.shape[1] / xy];
pad = [pad[0] / inputSize, pad[1] / inputSize];
} else {
t.padded = inputImage.clone();
}
t.resized = tf.image.resizeBilinear(t.padded as Tensor4D, [inputSize, inputSize]);
t.resized = tf.image.resizeBilinear(inputImage, [inputSize, inputSize]);
t.div = tf.div(t.resized, constants.tf127);
t.normalized = tf.sub(t.div, constants.tf1);
t.normalized = tf.sub(t.div, constants.tf05);
const res = model?.execute(t.normalized) as Tensor[];
if (Array.isArray(res) && res.length > 2) { // pinto converted model?
const sorted = res.sort((a, b) => a.size - b.size);
@ -92,6 +81,7 @@ export async function getBoxes(inputImage: Tensor4D, config: Config): Promise<De
const scores = await t.scores.data();
for (let i = 0; i < nms.length; i++) {
const confidence = scores[nms[i]];
if (confidence > (config.face.detector?.minConfidence || 0)) {
const b: Record<string, Tensor> = {};
b.bbox = tf.slice(t.boxes, [nms[i], 0], [1, -1]);
@ -99,15 +89,9 @@ export async function getBoxes(inputImage: Tensor4D, config: Config): Promise<De
b.squeeze = tf.squeeze(b.slice);
b.landmarks = tf.reshape(b.squeeze, [keypointsCount, -1]);
const points = await b.bbox.data();
const unpadded = [ // TODO fix this math
points[0] * scale[0] - pad[0],
points[1] * scale[1] - pad[1],
points[2] * scale[0] - pad[0],
points[3] * scale[1] - pad[1],
];
const rawBox = {
startPoint: [unpadded[0], unpadded[1]] as Point,
endPoint: [unpadded[2], unpadded[3]] as Point,
startPoint: [points[0], points[1]] as Point,
endPoint: [points[2], points[3]] as Point,
landmarks: (await b.landmarks.array()) as Point[],
confidence,
};

View File

@ -113,7 +113,7 @@ export const detectFace = async (instance: Human /* instance of human */, input:
}
instance.analyze('End GEAR:');
// run ssrnet, inherits face from blazeface
// run gear, inherits face from blazeface
instance.analyze('Start SSRNet:');
if (instance.config.async) {
ageRes = instance.config.face['ssrnet']?.enabled ? ssrnetAge.predict(faces[i].tensor as Tensor4D || tf.tensor([]), instance.config, i, faces.length) : null;

View File

@ -17,8 +17,7 @@ export function distance(descriptor1: Descriptor, descriptor2: Descriptor, optio
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);
}
const dist = Math.round(100 * (options.multiplier || 20) * sum) / 100;
return dist;
return (options.multiplier || 20) * sum;
}
// invert distance to similarity, normalize to given range and clamp
@ -26,7 +25,7 @@ const normalizeDistance = (dist, order, min, max) => {
if (dist === 0) return 1; // short circuit for identical inputs
const root = order === 2 ? Math.sqrt(dist) : dist ** (1 / order); // take root of distance
const norm = (1 - (root / 100) - min) / (max - min); // normalize to range
const clamp = Math.round(100 * Math.max(Math.min(norm, 1), 0)) / 100; // clamp to 0..1
const clamp = Math.max(Math.min(norm, 1), 0); // clamp to 0..1
return clamp;
};

View File

@ -290,6 +290,7 @@ const checksum = async (input: Tensor): Promise<number> => { // use tf sum or js
export async function skip(config: Partial<Config>, input: Tensor) {
let skipFrame = false;
if (config.cacheSensitivity === 0 || !input.shape || input.shape.length !== 4 || input.shape[1] > 3840 || input.shape[2] > 2160) return skipFrame; // cache disabled or input is invalid or too large for cache analysis
/*
const checkSum = await checksum(input);
const diff = 100 * (Math.max(checkSum, last.inputSum) / Math.min(checkSum, last.inputSum) - 1);

View File

@ -100,13 +100,13 @@ export class Models {
let totalSizeWeights = 0;
let totalSizeLoading = 0;
for (const m of Object.values(modelStats)) {
totalSizeFromManifest += Number.isNaN(+m.sizeFromManifest) ? 0 : m.sizeFromManifest;
totalSizeWeights += Number.isNaN(+m.sizeLoadedWeights) ? 0 : m.sizeLoadedWeights;
totalSizeLoading += Number.isNaN(+m.sizeDesired) ? 0 : m.sizeDesired;
totalSizeFromManifest += m.sizeFromManifest;
totalSizeWeights += m.sizeLoadedWeights;
totalSizeLoading += m.sizeDesired;
}
const percentageLoaded = totalSizeLoading > 0 ? totalSizeWeights / totalSizeLoading : 0;
return {
numLoadedModels: Object.values(modelStats).filter((m) => m?.loaded).length,
numLoadedModels: Object.values(modelStats).length,
numDefinedModels: Object.keys(this.models).length,
percentageLoaded,
totalSizeFromManifest,
@ -178,7 +178,7 @@ export class Models {
return models;
}
loaded(): string[] {
loaded() {
const list = this.list();
const loaded = list.filter((model) => model.loaded).map((model) => model.name);
return loaded;

View File

@ -3,7 +3,7 @@
*/
// data:image/jpeg;base64,
export const face: string = `
export const face = `
/9j/4AAQSkZJRgABAQEAYABgAAD/4QBoRXhpZgAATU0AKgAAAAgABAEaAAUAAAABAAAAPgEbAAUA
AAABAAAARgEoAAMAAAABAAIAAAExAAIAAAARAAAATgAAAAAAAABgAAAAAQAAAGAAAAABcGFpbnQu
bmV0IDQuMi4xMwAA/9sAQwAGBAUGBQQGBgUGBwcGCAoQCgoJCQoUDg8MEBcUGBgXFBYWGh0lHxob

View File

@ -121,17 +121,14 @@ export async function check(instance: Human, force = false) {
log('override: backend set to webgpu but browser does not support webgpu');
instance.config.backend = 'webgl';
} else {
const adapter: GPUAdapter = await navigator.gpu.requestAdapter() as GPUAdapter;
const adapter = await navigator.gpu.requestAdapter();
if (instance.config.debug) log('enumerated webgpu adapter:', adapter);
if (!adapter) {
log('override: backend set to webgpu but browser reports no available gpu');
instance.config.backend = 'webgl';
} else {
let adapterInfo;
// @ts-ignore gpu adapter info
if ('requestAdapterInfo' in adapter) adapterInfo = await adapter?.requestAdapterInfo();
// @ts-ignore gpu adapter info
else adapterInfo = adapter.info;
// @ts-ignore requestAdapterInfo is not in tslib
const adapterInfo = 'requestAdapterInfo' in adapter ? await adapter.requestAdapterInfo() : undefined;
// if (adapter.features) adapter.features.forEach((feature) => log('webgpu features:', feature));
log('webgpu adapter info:', adapterInfo);
}

View File

@ -14,7 +14,6 @@ const options = {
export interface ModelInfo {
name: string,
loaded: boolean,
inCache: boolean,
sizeDesired: number,
sizeFromManifest: number,
@ -43,7 +42,6 @@ export async function loadModel(modelPath: string | undefined): Promise<GraphMod
const cachedModelName = 'indexeddb://' + shortModelName; // generate short model name for cache
modelStats[shortModelName] = {
name: shortModelName,
loaded: false,
sizeFromManifest: 0,
sizeLoadedWeights: 0,
sizeDesired: modelsDefs[shortModelName],
@ -61,7 +59,7 @@ export async function loadModel(modelPath: string | undefined): Promise<GraphMod
modelStats[shortModelName].url = modelStats[shortModelName].inCache ? cachedModelName : modelUrl;
const tfLoadOptions = typeof fetch === 'undefined' ? {} : { fetchFunc: (url: string, init?: RequestInit) => httpHandler(url, init) };
let model: GraphModel = new tf.GraphModel(modelStats[shortModelName].url, tfLoadOptions) as unknown as GraphModel; // create model prototype and decide if load from cache or from original modelurl
modelStats[shortModelName].loaded = false;
let loaded = false;
try {
// @ts-ignore private function
model.findIOHandler(); // decide how to actually load a model
@ -76,13 +74,13 @@ export async function loadModel(modelPath: string | undefined): Promise<GraphMod
if (artifacts) model.loadSync(artifacts); // load weights
else model = await tf.loadGraphModel(modelStats[shortModelName].inCache ? cachedModelName : modelUrl, tfLoadOptions) as unknown as GraphModel;
// @ts-ignore private property
modelStats[shortModelName].sizeLoadedWeights = model.artifacts?.weightData?.byteLength || model.artifacts?.weightData?.[0].byteLength || 0;
modelStats[shortModelName].sizeLoadedWeights = model.artifacts?.weightData?.byteLength || 0;
if (options.verbose) log('load:', { model: shortModelName, url: model['modelUrl'], bytes: modelStats[shortModelName].sizeLoadedWeights });
modelStats[shortModelName].loaded = true;
loaded = true;
} catch (err) {
log('error loading model:', modelUrl, err);
}
if (modelStats[shortModelName].loaded && options.cacheModels && options.cacheSupported && !modelStats[shortModelName].inCache) { // save model to cache
if (loaded && options.cacheModels && options.cacheSupported && !modelStats[shortModelName].inCache) { // save model to cache
try {
const saveResult = await model.save(cachedModelName);
if (options.debug) log('model saved:', cachedModelName, saveResult);

View File

@ -154,12 +154,7 @@ export class Env {
try {
if (this.webgpu.supported) {
const adapter = await navigator.gpu.requestAdapter();
if (adapter) {
// @ts-ignore requestAdapterInfo is not in tslib
if ('requestAdapterInfo' in adapter) this.webgpu.adapter = await adapter.requestAdapterInfo();
// @ts-ignore adapter.info is not in tslib
else this.webgpu.adapter = await adapter.info;
}
this.webgpu.adapter = await adapter?.requestAdapterInfo();
}
} catch {
this.webgpu.supported = false;

View File

@ -166,7 +166,6 @@ export async function warmup(instance: Human, userConfig?: Partial<Config>): Pro
}
return new Promise(async (resolve) => {
await instance.models.load();
await tf.ready();
await runCompile(instance);
const res = await runInference(instance);
const t1 = now();

View File

@ -1,51 +1,51 @@
2025-08-26 11:39:08 DATA:  Build {"name":"@vladmandic/human","version":"3.3.6"}
2025-08-26 11:39:08 INFO:  Application: {"name":"@vladmandic/human","version":"3.3.6"}
2025-08-26 11:39:08 INFO:  Environment: {"profile":"production","config":".build.json","package":"package.json","tsconfig":true,"eslintrc":true,"git":true}
2025-08-26 11:39:08 INFO:  Toolchain: {"build":"0.10.3","esbuild":"0.25.9","typescript":"5.9.2","typedoc":"0.28.11","eslint":"8.57.0"}
2025-08-26 11:39:08 INFO:  Build: {"profile":"production","steps":["clean","compile","typings","typedoc","lint","changelog"]}
2025-08-26 11:39:08 STATE: Clean: {"locations":["dist/*","types/*","typedoc/*"]}
2025-08-26 11:39:08 STATE: Compile: {"name":"tfjs/browser/version","format":"esm","platform":"browser","input":"tfjs/tf-version.ts","output":"dist/tfjs.version.js","files":1,"inputBytes":1289,"outputBytes":358}
2025-08-26 11:39:08 STATE: Compile: {"name":"tfjs/nodejs/cpu","format":"cjs","platform":"node","input":"tfjs/tf-node.ts","output":"dist/tfjs.esm.js","files":2,"inputBytes":566,"outputBytes":957}
2025-08-26 11:39:09 STATE: Compile: {"name":"human/nodejs/cpu","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node.js","files":80,"inputBytes":678685,"outputBytes":321804}
2025-08-26 11:39:09 STATE: Compile: {"name":"tfjs/nodejs/gpu","format":"cjs","platform":"node","input":"tfjs/tf-node-gpu.ts","output":"dist/tfjs.esm.js","files":2,"inputBytes":574,"outputBytes":965}
2025-08-26 11:39:09 STATE: Compile: {"name":"human/nodejs/gpu","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node-gpu.js","files":80,"inputBytes":678693,"outputBytes":321808}
2025-08-26 11:39:09 STATE: Compile: {"name":"tfjs/nodejs/wasm","format":"cjs","platform":"node","input":"tfjs/tf-node-wasm.ts","output":"dist/tfjs.esm.js","files":2,"inputBytes":662,"outputBytes":2003}
2025-08-26 11:39:09 STATE: Compile: {"name":"human/nodejs/wasm","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node-wasm.js","files":80,"inputBytes":679731,"outputBytes":321919}
2025-08-26 11:39:09 STATE: Compile: {"name":"tfjs/browser/esm/nobundle","format":"esm","platform":"browser","input":"tfjs/tf-browser.ts","output":"dist/tfjs.esm.js","files":2,"inputBytes":1403,"outputBytes":690}
2025-08-26 11:39:09 STATE: Compile: {"name":"human/browser/esm/nobundle","format":"esm","platform":"browser","input":"src/human.ts","output":"dist/human.esm-nobundle.js","files":80,"inputBytes":678418,"outputBytes":320365}
2025-08-26 11:39:09 STATE: Compile: {"name":"tfjs/browser/esm/bundle","format":"esm","platform":"browser","input":"tfjs/tf-browser.ts","output":"dist/tfjs.esm.js","files":10,"inputBytes":1403,"outputBytes":1267682}
2025-08-26 11:39:09 STATE: Compile: {"name":"human/browser/iife/bundle","format":"iife","platform":"browser","input":"src/human.ts","output":"dist/human.js","files":80,"inputBytes":1945410,"outputBytes":1583774}
2025-08-26 11:39:09 STATE: Compile: {"name":"human/browser/esm/bundle","format":"esm","platform":"browser","input":"src/human.ts","output":"dist/human.esm.js","files":80,"inputBytes":1945410,"outputBytes":2067875}
2025-08-26 11:39:10 STATE: Typings: {"input":"src/human.ts","output":"types/lib","files":78}
2025-08-26 11:39:12 STATE: TypeDoc: {"input":"src/human.ts","output":"typedoc","objects":81,"generated":true}
2025-08-26 11:39:12 STATE: Compile: {"name":"demo/typescript","format":"esm","platform":"browser","input":"demo/typescript/index.ts","output":"demo/typescript/index.js","files":1,"inputBytes":6318,"outputBytes":2970}
2025-08-26 11:39:12 STATE: Compile: {"name":"demo/faceid","format":"esm","platform":"browser","input":"demo/faceid/index.ts","output":"demo/faceid/index.js","files":2,"inputBytes":17498,"outputBytes":9397}
2025-08-26 11:39:12 STATE: Compile: {"name":"demo/tracker","format":"esm","platform":"browser","input":"demo/tracker/index.ts","output":"demo/tracker/index.js","files":2,"inputBytes":54375,"outputBytes":22797}
2025-08-26 11:39:20 STATE: Lint: {"locations":["**/*.json","src/**/*.ts","test/**/*.js","demo/**/*.js","**/*.md"],"files":172,"errors":0,"warnings":0}
2025-08-26 11:39:20 STATE: ChangeLog: {"repository":"https://github.com/vladmandic/human","branch":"main","output":"CHANGELOG.md"}
2025-08-26 11:39:20 STATE: Copy: {"input":"node_modules/@vladmandic/tfjs/types/tfjs-core.d.ts","output":"types/tfjs-core.d.ts"}
2025-08-26 11:39:20 INFO:  Done...
2025-08-26 11:39:20 STATE: Copy: {"input":"node_modules/@vladmandic/tfjs/types/tfjs.d.ts","output":"types/tfjs.esm.d.ts"}
2025-08-26 11:39:20 STATE: Copy: {"input":"src/types/tsconfig.json","output":"types/tsconfig.json"}
2025-08-26 11:39:20 STATE: Copy: {"input":"src/types/eslint.json","output":"types/.eslintrc.json"}
2025-08-26 11:39:20 STATE: Copy: {"input":"src/types/tfjs.esm.d.ts","output":"dist/tfjs.esm.d.ts"}
2025-08-26 11:39:20 STATE: Filter: {"input":"types/tfjs-core.d.ts"}
2025-08-26 11:39:21 STATE: API-Extractor: {"succeeeded":true,"errors":0,"warnings":0}
2025-08-26 11:39:21 STATE: Filter: {"input":"types/human.d.ts"}
2025-08-26 11:39:21 STATE: Write: {"output":"dist/human.esm-nobundle.d.ts"}
2025-08-26 11:39:21 STATE: Write: {"output":"dist/human.esm.d.ts"}
2025-08-26 11:39:21 STATE: Write: {"output":"dist/human.d.ts"}
2025-08-26 11:39:21 STATE: Write: {"output":"dist/human.node-gpu.d.ts"}
2025-08-26 11:39:21 STATE: Write: {"output":"dist/human.node.d.ts"}
2025-08-26 11:39:21 STATE: Write: {"output":"dist/human.node-wasm.d.ts"}
2025-08-26 11:39:21 INFO:  Analyze models: {"folders":8,"result":"models/models.json"}
2025-08-26 11:39:21 STATE: Models {"folder":"./models","models":12}
2025-08-26 11:39:21 STATE: Models {"folder":"../human-models/models","models":44}
2025-08-26 11:39:21 STATE: Models {"folder":"../blazepose/model/","models":4}
2025-08-26 11:39:21 STATE: Models {"folder":"../anti-spoofing/model","models":1}
2025-08-26 11:39:21 STATE: Models {"folder":"../efficientpose/models","models":3}
2025-08-26 11:39:21 STATE: Models {"folder":"../insightface/models","models":5}
2025-08-26 11:39:21 STATE: Models {"folder":"../movenet/models","models":3}
2025-08-26 11:39:21 STATE: Models {"folder":"../nanodet/models","models":4}
2025-08-26 11:39:22 STATE: Models: {"count":58,"totalSize":380063249}
2025-08-26 11:39:22 INFO:  Human Build complete... {"logFile":"test/build.log"}
2024-02-15 12:49:25 DATA:  Build {"name":"@vladmandic/human","version":"3.2.1"}
2024-02-15 12:49:25 INFO:  Application: {"name":"@vladmandic/human","version":"3.2.1"}
2024-02-15 12:49:25 INFO:  Environment: {"profile":"production","config":".build.json","package":"package.json","tsconfig":true,"eslintrc":true,"git":true}
2024-02-15 12:49:25 INFO:  Toolchain: {"build":"0.9.2","esbuild":"0.19.12","typescript":"5.3.3","typedoc":"0.25.4","eslint":"8.55.0"}
2024-02-15 12:49:25 INFO:  Build: {"profile":"production","steps":["clean","compile","typings","typedoc","lint","changelog"]}
2024-02-15 12:49:25 STATE: Clean: {"locations":["dist/*","types/*","typedoc/*"]}
2024-02-15 12:49:25 STATE: Compile: {"name":"tfjs/browser/version","format":"esm","platform":"browser","input":"tfjs/tf-version.ts","output":"dist/tfjs.version.js","files":1,"inputBytes":1289,"outputBytes":358}
2024-02-15 12:49:25 STATE: Compile: {"name":"tfjs/nodejs/cpu","format":"cjs","platform":"node","input":"tfjs/tf-node.ts","output":"dist/tfjs.esm.js","files":2,"inputBytes":566,"outputBytes":957}
2024-02-15 12:49:25 STATE: Compile: {"name":"human/nodejs/cpu","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node.js","files":80,"inputBytes":676266,"outputBytes":320934}
2024-02-15 12:49:25 STATE: Compile: {"name":"tfjs/nodejs/gpu","format":"cjs","platform":"node","input":"tfjs/tf-node-gpu.ts","output":"dist/tfjs.esm.js","files":2,"inputBytes":574,"outputBytes":965}
2024-02-15 12:49:25 STATE: Compile: {"name":"human/nodejs/gpu","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node-gpu.js","files":80,"inputBytes":676274,"outputBytes":320938}
2024-02-15 12:49:25 STATE: Compile: {"name":"tfjs/nodejs/wasm","format":"cjs","platform":"node","input":"tfjs/tf-node-wasm.ts","output":"dist/tfjs.esm.js","files":2,"inputBytes":662,"outputBytes":2003}
2024-02-15 12:49:25 STATE: Compile: {"name":"human/nodejs/wasm","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node-wasm.js","files":80,"inputBytes":677312,"outputBytes":321049}
2024-02-15 12:49:25 STATE: Compile: {"name":"tfjs/browser/esm/nobundle","format":"esm","platform":"browser","input":"tfjs/tf-browser.ts","output":"dist/tfjs.esm.js","files":2,"inputBytes":1403,"outputBytes":690}
2024-02-15 12:49:25 STATE: Compile: {"name":"human/browser/esm/nobundle","format":"esm","platform":"browser","input":"src/human.ts","output":"dist/human.esm-nobundle.js","files":80,"inputBytes":675999,"outputBytes":319515}
2024-02-15 12:49:25 STATE: Compile: {"name":"tfjs/browser/esm/bundle","format":"esm","platform":"browser","input":"tfjs/tf-browser.ts","output":"dist/tfjs.esm.js","files":10,"inputBytes":1403,"outputBytes":1294474}
2024-02-15 12:49:25 STATE: Compile: {"name":"human/browser/iife/bundle","format":"iife","platform":"browser","input":"src/human.ts","output":"dist/human.js","files":80,"inputBytes":1969783,"outputBytes":1609692}
2024-02-15 12:49:25 STATE: Compile: {"name":"human/browser/esm/bundle","format":"esm","platform":"browser","input":"src/human.ts","output":"dist/human.esm.js","files":80,"inputBytes":1969783,"outputBytes":2120081}
2024-02-15 12:49:26 STATE: Typings: {"input":"src/human.ts","output":"types/lib","files":14}
2024-02-15 12:49:28 STATE: TypeDoc: {"input":"src/human.ts","output":"typedoc","objects":81,"generated":true}
2024-02-15 12:49:28 STATE: Compile: {"name":"demo/typescript","format":"esm","platform":"browser","input":"demo/typescript/index.ts","output":"demo/typescript/index.js","files":1,"inputBytes":6318,"outputBytes":2970}
2024-02-15 12:49:28 STATE: Compile: {"name":"demo/faceid","format":"esm","platform":"browser","input":"demo/faceid/index.ts","output":"demo/faceid/index.js","files":2,"inputBytes":17499,"outputBytes":9399}
2024-02-15 12:49:28 STATE: Compile: {"name":"demo/tracker","format":"esm","platform":"browser","input":"demo/tracker/index.ts","output":"demo/tracker/index.js","files":2,"inputBytes":54375,"outputBytes":22791}
2024-02-15 12:49:35 STATE: Lint: {"locations":["**/*.json","src/**/*.ts","test/**/*.js","demo/**/*.js","**/*.md"],"files":172,"errors":0,"warnings":0}
2024-02-15 12:49:35 STATE: ChangeLog: {"repository":"https://github.com/vladmandic/human","branch":"main","output":"CHANGELOG.md"}
2024-02-15 12:49:35 STATE: Copy: {"input":"node_modules/@vladmandic/tfjs/types/tfjs-core.d.ts","output":"types/tfjs-core.d.ts"}
2024-02-15 12:49:35 INFO:  Done...
2024-02-15 12:49:35 STATE: Copy: {"input":"node_modules/@vladmandic/tfjs/types/tfjs.d.ts","output":"types/tfjs.esm.d.ts"}
2024-02-15 12:49:35 STATE: Copy: {"input":"src/types/tsconfig.json","output":"types/tsconfig.json"}
2024-02-15 12:49:35 STATE: Copy: {"input":"src/types/eslint.json","output":"types/.eslintrc.json"}
2024-02-15 12:49:35 STATE: Copy: {"input":"src/types/tfjs.esm.d.ts","output":"dist/tfjs.esm.d.ts"}
2024-02-15 12:49:35 STATE: Filter: {"input":"types/tfjs-core.d.ts"}
2024-02-15 12:49:36 ERROR: API-Extractor: {}
2024-02-15 12:49:36 STATE: Filter: {"input":"types/human.d.ts"}
2024-02-15 12:49:36 STATE: Write: {"output":"dist/human.esm-nobundle.d.ts"}
2024-02-15 12:49:36 STATE: Write: {"output":"dist/human.esm.d.ts"}
2024-02-15 12:49:36 STATE: Write: {"output":"dist/human.d.ts"}
2024-02-15 12:49:36 STATE: Write: {"output":"dist/human.node-gpu.d.ts"}
2024-02-15 12:49:36 STATE: Write: {"output":"dist/human.node.d.ts"}
2024-02-15 12:49:36 STATE: Write: {"output":"dist/human.node-wasm.d.ts"}
2024-02-15 12:49:36 INFO:  Analyze models: {"folders":8,"result":"models/models.json"}
2024-02-15 12:49:36 STATE: Models {"folder":"./models","models":12}
2024-02-15 12:49:36 STATE: Models {"folder":"../human-models/models","models":44}
2024-02-15 12:49:36 STATE: Models {"folder":"../blazepose/model/","models":4}
2024-02-15 12:49:36 STATE: Models {"folder":"../anti-spoofing/model","models":1}
2024-02-15 12:49:36 STATE: Models {"folder":"../efficientpose/models","models":3}
2024-02-15 12:49:36 STATE: Models {"folder":"../insightface/models","models":5}
2024-02-15 12:49:36 STATE: Models {"folder":"../movenet/models","models":3}
2024-02-15 12:49:36 STATE: Models {"folder":"../nanodet/models","models":4}
2024-02-15 12:49:36 STATE: Models: {"count":58,"totalSize":380063249}
2024-02-15 12:49:36 INFO:  Human Build complete... {"logFile":"test/build.log"}

View File

@ -3,7 +3,7 @@ const H = require('../dist/human.node.js');
const test = require('./test-node-main.js').test;
const config = {
cacheSensitivity: 0.01,
cacheSensitivity: 0,
modelBasePath: 'file://models/',
backend: 'cpu',
debug: false,

View File

@ -3,7 +3,7 @@ const H = require('../dist/human.node-gpu.js');
const test = require('./test-node-main.js').test;
const config = {
cacheSensitivity: 0.01,
cacheSensitivity: 0,
modelBasePath: 'file://models/',
backend: 'tensorflow',
debug: false,

View File

@ -10,7 +10,7 @@ H.env.Canvas = Canvas; // requires monkey-patch as wasm does not have tf.browser
H.env.Image = Image; // requires monkey-patch as wasm does not have tf.browser namespace
const config = {
cacheSensitivity: 0.01,
cacheSensitivity: 0,
modelBasePath: 'https://vladmandic.github.io/human-models/models/',
backend: 'wasm',
// wasmPath: 'node_modules/@tensorflow/tfjs-backend-wasm/dist/',

View File

@ -4,7 +4,7 @@ const H = require('../dist/human.node.js');
const test = require('./test-node-main.js').test;
const config = {
cacheSensitivity: 0.01,
cacheSensitivity: 0,
modelBasePath: 'file://models/',
backend: 'tensorflow',
debug: false,

View File

@ -6,7 +6,7 @@ const H = require('../dist/human.node.js');
const models = ['emotion.json', 'gear-e1.json', 'gear-e2.json', 'affectnet-mobilenet.json'];
const humanConfig = {
debug: false,
cacheSensitivity: 0.01,
cacheSensitivity: 0,
modelBasePath: 'https://vladmandic.github.io/human-models/models/',
face: {
scale: 1.4,

View File

@ -12,7 +12,7 @@ process.env.TF_CPP_MIN_LOG_LEVEL = '2';
const humanConfig = {
backend: 'tensorflow',
debug: false,
cacheSensitivity: 0.01,
cacheSensitivity: 0,
modelBasePath: 'https://vladmandic.github.io/human-models/models/',
face: {
detector: { enabled: true, modelPath: 'blazeface-back.json' },

View File

@ -107,7 +107,7 @@ async function testWarmup(human, title) {
try {
warmup = await human.warmup(config);
} catch (err) {
log('error', 'error warmup', err);
log('error', 'error warmup');
}
if (warmup) {
log('state', 'passed: warmup:', config.warmup, title);

File diff suppressed because it is too large Load Diff

View File

@ -51,9 +51,9 @@
"tabSize": 2
},
"exclude": ["node_modules/", "types/", "dist/**/*.js"],
"include": ["src", "tfjs/*.ts", "types/human.d.ts", "test/**/*.ts"],
"include": ["src", "tfjs/*.ts", "types/human.d.ts", "test/**/*.ts", "demo/**/*.ts", "demo/facedetect/loader.js"],
"typedocOptions": {
"excludeExternals": true,
"externalPattern": ["**/node_modules/**", "tfjs/", "demo/"]
"externalPattern": ["**/node_modules/**", "tfjs/"]
}
}

View File

@ -1 +0,0 @@
window.hierarchyData = "eJyV1D1PwzAQBuD/cvMVcs5H02x8FiQQQ0fEEJJra0jtyjZIqOp/R2EgqbNcpwx5Xz1nx84BnLXBQ/VKSfqG4HjdcRO0NR6qA1CS9g9T7xgqWLJhp5sba9Z6Awif2rRQqbxA+HIdVKBNYLeuG/aXJ9mLbdh1gNB0tfdQQfDtrC/P/gv9y63uWsfmb5YSSSkkVSKlGVK6QMpypJyQ8gKpIKRijlQSUlmiSjJUpN6OCJSUo4nv64ZvOXATrBONPS0IZu9ZpSL2mf1WTA5hKRev8tFpL+aGsJBLs4i7CoFNf0zEZtSQwovJ1/SN0/uz6ElHiGd5hN/t7FnwSV6I5hRvtQl6tbd2Ld/q04YULiL4SX+zYS8/VqcFIVvE611yLb+rQ1jKzSNOTJ3FlONVXdv2R8QMQSkz/g081KYVMUNQxqhkfP1f3j+4CSJoHBVSNP6PrnizYxNq8aWbFiTs8fgLDRRRDg=="

View File

@ -15,6 +15,8 @@
--dark-hl-6: #DCDCAA;
--light-hl-7: #098658;
--dark-hl-7: #B5CEA8;
--light-hl-8: #000000;
--dark-hl-8: #C8C8C8;
--light-code-background: #FFFFFF;
--dark-code-background: #1E1E1E;
}
@ -28,6 +30,7 @@
--hl-5: var(--light-hl-5);
--hl-6: var(--light-hl-6);
--hl-7: var(--light-hl-7);
--hl-8: var(--light-hl-8);
--code-background: var(--light-code-background);
} }
@ -40,6 +43,7 @@
--hl-5: var(--dark-hl-5);
--hl-6: var(--dark-hl-6);
--hl-7: var(--dark-hl-7);
--hl-8: var(--dark-hl-8);
--code-background: var(--dark-code-background);
} }
@ -52,6 +56,7 @@
--hl-5: var(--light-hl-5);
--hl-6: var(--light-hl-6);
--hl-7: var(--light-hl-7);
--hl-8: var(--light-hl-8);
--code-background: var(--light-code-background);
}
@ -64,6 +69,7 @@
--hl-5: var(--dark-hl-5);
--hl-6: var(--dark-hl-6);
--hl-7: var(--dark-hl-7);
--hl-8: var(--dark-hl-8);
--code-background: var(--dark-code-background);
}
@ -75,4 +81,5 @@
.hl-5 { color: var(--hl-5); }
.hl-6 { color: var(--hl-6); }
.hl-7 { color: var(--hl-7); }
.hl-8 { color: var(--hl-8); }
pre, code { background: var(--code-background); }

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 12 KiB

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
window.navigationData = "eJyVmU9z2zYQxb8Le/U0saykjW/+oyqeWLXH9jSHTA4wuZJQkQsOCCpWM/nuHRKSABLgLnXFe+8ncBckQejbz8TAm0kuk0yLH8lZUgqzTi6TQmV1DtW7ZvT3tSny5CzZSMySy+lZkq5lnmnA5PLbMa5KIxVWjrAVWorXI2Ovd1kXk19nR4LIc5de1pi2AZsWed5Nfpx6yVeV7QajjUhkU4FbUQ2mrUzklyKFwXQjEtkVVKbWw/G9ThDWArPBeCMSWYnSDGYbkciq138hHU5bmciXoCuFg3krE3kDWCk9mLdykP/uEQph0nW43tvhUQv+FqpUy9L40zC78shwehc3ef/pj/MP/sJfNP6H/v3js3wHR8tkZQTGF6WlHRzUqpbxdWUBjUqEK1nIXGhpojelRTgP3SWVQV5F2tSOj+rToodIc1FVDrGIkM4nf3pz+AIaIX8oPYZEA7q5uY+Yo6nXng8f/UY33mcjDIlyLoq1FbnMhIHWHa2zpXV8ZK1fevfUodYvkZvJb/eTwI1LAdZF9a4Z6yb8is5wG/ZjhluqC5/rQmCYaoep3LXKdjcKl3IVrbmTqWI3ri+wK5VEM4g5GDjQE1R1PoyxMgUhLoe/lFstfgTPGo/g6RTmL5HCFRr5XCq1JCYU8bFYYwCbCXDYro/DMrRxkMNDnZ9d4OTRBlKjNMv1bRx0VqgRc+24OOQcBDdHZ+Fgd1pWDMxZONi93AJCxQG7Ng66gGrNAJ2FgxG3vpNJiMwNkOX3DBRoDghapgSp46BR7S6VRHkOEqVFue690XzOUaYgnwVmxGSczEGIbjmZfd/f4VJFGUeVQjy0O2nicnwDDyIuyTdQoMd2b06AfAMFIhB8+BlWBaARzNMttFHQ/g7IA8U2Qd3wV3i9EUU0bCU+TFyIb6BAV7i76X3R2g+Jo8B9P1zh7q4QK4gA2vER+X9kBiqSb8e5/LVIN4DZDOuij/AklqKy3RWisq0PQB31NNZ1Lv6DR1UFBRqwnUafLZcylYCG/4WOdcyvzPvHDY46j500xCn3ArNC6E0Mc9BO4ZD1DEynkI8F+hsMBfd9p/AXagsMem85hdpcJUPdW3jqW0h541L7zWA/uR9m01tAEzx87CibfTOgUeTxB1hX5Vh2Gxpd7540hjK03n2N5UhcQXBOZEfHZW9qncfzjTKOcSs1pLHe9mSONgfMwquxo3y2LXz/3X9AeCJHarZgAx32pDGUl10ZRTTjXL59JdqtU7BifY3lYFkH9WgH2aSW1UAdPImj2GnGKuEUjvHYPR6x8cfIkUiQfOocotvgU3B2Hub87V1sw9DXOZ7d5Z3f9jmH8XH5yUB+MjJ/MZC/GJmfDuSnI/P3chN0wykc46vQRV3GuuEU9gwblqLOTfzfpL1G/JME/vmiS0L/hLEbKsr4gXUrEMfd+wn52/YM7Gv2N6ftz03PP00v3k9/ff8fP3Qzuw=="
window.navigationData = "data:application/octet-stream;base64,H4sIAAAAAAAAA5WZT3PbNhDFvwt7dZtIVtLGN/9RFU+s2mNnmkOmB5hcSajIBQcEFaudfvcOCUkACXCXuu577ydwAZIg9P3fxMCbSa6SDFaizk1ykZTCbJKrRGIGb79sTJH/5LStxCy5mk0+zS7fz/67OKW/AlZKu3ChsjqH6p2ttxSX9nKZFj/CVFPtZS6SdCPzTAMmV99PcVUaqbByhJ3QUryeGAe9y7qcegMQee7SqxrTNmDTIs+7yY/+0F9Vth+MNiKRTQXuRDWYtjKRX4kUBtONSGTXUJlaD8cPOkHYCMwG441IZCVKM5htRCKrXv+GdDhtZSJfgq4UDuatHOT/8giFMOkmXK9tedSCvYMq1bI0/r1i9uWJ4fQubvr+06+TD/7CXTb+x/7691m+g6NlsjIC44vK0o4OalXK+LqwgEYlwpUsZC60NNGbyiKch54llUFeRaaprY+ap2UPkeaiqhxiGSFNpr95Y/gCGiF/LCv/gWpANzfnCXMy9abnw0d/ohvvixGGRDkXxdqJXGbCQOuO9tnSOj6y188Ctw4EWBfVu6bWDfmdmeMu7Oscd1Q3F1qUm96gj1GnUYTPdSEwDLdlKtd/sR2Dtv7zhMp+g9dbUYRZW6eSNyrb3ypcyXV0zp1MTXbj+gL7Ukk0g5ijgQM9Q9XbHXQwVqYgxOXwl3KnxY/gWecRPJ3C/C5SuEYjX0qlVsSAIj4WawxgMwAO2/VxWIY2DnJ8qfCjC5w82kBqlGa5vo2Dzgs1YqwdF4dcgODG6Cwc7F7LioE5Cwd7kDtAqDhg18ZBl1BtGKCzcDDi1ncyCZG5AbL9noECLQBBy5QgdRw0qt3lkijPQaE+C8wIjpM5CNFoJ7NbhXtcqSjjpFKIx3YTTVyOb+BBxCX5Bgr01G7LCZBvoEAEgg+/wLoANIJ5MIU2Cmo3AgTON1Cga9zf9j4p7ZfASeA+AK5xf1+INUQAbX1E/k+ZgYrk2zqXvxHpFjCbY130EZ7EUlS2v0ZUdgICUEc9j3WTi3/gSVVBgwZs59Hnq5VMJaDhf6FjHfMri/73vqMuYp/6ccqDwKwQehvDHLVzOGQ/A9M55FOD/gBDwX3fOfyl2gGDPljOoTZXyVAPFp76FlLeuNRhN9VPHspsegdogoePrbLZNwMaRR5/gHVVjmX3cdH17kljKEPr3ddYjsQ1BAc9tjoue1vrPJ5vlHGMO6khjc1tT+ZoC8AsvBpb5bNt4/tv4CPCEzlSsxEamGFPGkP5ui+jiKbO5dtXot3ABCvW11gOlnXQj7bIJrWsBvrgSRzFDjPWCadwjKfu+YKNP0XOFILkc+cU2wafg8PrMOdvsmIbhr7O8exZzuSuzznWx+WnA/npyPzlQP5yZH42kJ+NzD/IbTAbTuEY34Qu6jI2G05hD6Ht30zxv3MOGvFXDvgHiy4JuOsf03VjRRk/c26F8PDzf7TeFt4zGwAA"

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

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

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

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

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

View File

@ -1,2 +0,0 @@
<!DOCTYPE html><html class="default" lang="en" data-base="../"><head><meta charset="utf-8"/><meta http-equiv="x-ua-compatible" content="IE=edge"/><title>tensor | @vladmandic/human - v3.3.6</title><meta name="description" content="Documentation for @vladmandic/human"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="../assets/style.css"/><link rel="stylesheet" href="../assets/highlight.css"/><script defer src="../assets/main.js"></script><script async src="../assets/icons.js" id="tsd-icons-script"></script><script async src="../assets/search.js" id="tsd-search-script"></script><script async src="../assets/navigation.js" id="tsd-nav-script"></script><script async src="../assets/hierarchy.js" id="tsd-hierarchy-script"></script></head><body><script>document.documentElement.dataset.theme = localStorage.getItem("tsd-theme") || "os";document.body.style.display="none";setTimeout(() => window.app?app.showPage():document.body.style.removeProperty("display"),500)</script><header class="tsd-page-toolbar"><div class="tsd-toolbar-contents container"><a href="../index.html" class="title">@vladmandic/human - v3.3.6</a><div id="tsd-toolbar-links"></div><button id="tsd-search-trigger" class="tsd-widget" aria-label="Search"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-search"></use></svg></button><dialog id="tsd-search" aria-label="Search"><input role="combobox" id="tsd-search-input" aria-controls="tsd-search-results" aria-autocomplete="list" aria-expanded="true" autocapitalize="off" autocomplete="off" placeholder="Search the docs" maxLength="100"/><ul role="listbox" id="tsd-search-results"></ul><div id="tsd-search-status" aria-live="polite" aria-atomic="true"><div>Preparing search index...</div></div></dialog><a href="#" class="tsd-widget menu" id="tsd-toolbar-menu-trigger" data-toggle="menu" aria-label="Menu"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-menu"></use></svg></a></div></header><div class="container container-main"><div class="col-content"><div class="tsd-page-title"><ul class="tsd-breadcrumb" aria-label="Breadcrumb"><li><a href="../modules/draw.html">draw</a></li><li><a href="" aria-current="page">tensor</a></li></ul><h1>Function tensor</h1></div><section class="tsd-panel"><ul class="tsd-signatures"><li class=""><div class="tsd-signature tsd-anchor-link" id="tensor"><span class="tsd-kind-call-signature">tensor</span><span class="tsd-signature-symbol">(</span><span class="tsd-kind-parameter">input</span><span class="tsd-signature-symbol">:</span> <a href="../types/Tensor2D.html" class="tsd-signature-type tsd-kind-type-alias">Tensor2D</a><span class="tsd-signature-symbol">,</span> <span class="tsd-kind-parameter">output</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">HTMLCanvasElement</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">&gt;</span><a href="#tensor" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></div><div class="tsd-description"><div class="tsd-comment tsd-typography"><p>draw processed canvas</p>
</div><div class="tsd-parameters"><h4 class="tsd-parameters-title">Parameters</h4><ul class="tsd-parameter-list"><li><span><span class="tsd-kind-parameter">input</span>: <a href="../types/Tensor2D.html" class="tsd-signature-type tsd-kind-type-alias">Tensor2D</a></span></li><li><span><span class="tsd-kind-parameter">output</span>: <span class="tsd-signature-type">HTMLCanvasElement</span></span></li></ul></div><h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">Promise</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">void</span><span class="tsd-signature-symbol">&gt;</span></h4><div class="tsd-comment tsd-typography"></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/vladmandic/human/blob/main/src/draw/draw.ts#L66">src/draw/draw.ts:66</a></li></ul></aside></div></li></ul></section></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-accordion"><summary class="tsd-accordion-summary"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg><h3>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li></ul></div><div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div></div><div class="site-menu"><nav class="tsd-navigation"><a href="../index.html">@vladmandic/human - v3.3.6</a><ul class="tsd-small-nested-navigation" id="tsd-nav-container"><li>Loading...</li></ul></nav></div></div></div><footer></footer><div class="overlay"></div></body></html>

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

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

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

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

Some files were not shown because too many files have changed in this diff Show More