Compare commits

...

24 Commits
3.2.1 ... main

Author SHA1 Message Date
Vladimir Mandic a6fd9a41c1 update readme
Signed-off-by: Vladimir Mandic <mandic00@live.com>
2025-02-05 10:11:17 -05:00
Vladimir Mandic 7e7c6d2ea2 update compatibility notes
Signed-off-by: Vladimir Mandic <mandic00@live.com>
2025-02-05 09:50:45 -05:00
Vladimir Mandic 5208b9ec2d full rebuild
Signed-off-by: Vladimir Mandic <mandic00@live.com>
2025-02-05 09:41:58 -05:00
Vladimir Mandic f515b9c20d 3.3.5 2025-02-05 09:29:56 -05:00
Vladimir Mandic 5a51889edb update build platform
Signed-off-by: Vladimir Mandic <mandic00@live.com>
2025-02-05 09:29:47 -05:00
Vladimir Mandic 745fd626a3 rebuild
Signed-off-by: Vladimir Mandic <mandic00@live.com>
2024-10-24 11:11:55 -04:00
Vladimir Mandic c1dc719a67 add human.draw.tensor method
Signed-off-by: Vladimir Mandic <mandic00@live.com>
2024-10-24 11:09:45 -04:00
Vladimir Mandic 2b0a2fecc2 3.3.4 2024-10-24 11:09:27 -04:00
Vladimir Mandic 38922fe92d update packages
Signed-off-by: Vladimir Mandic <mandic00@live.com>
2024-10-14 09:06:22 -04:00
Vladimir Mandic c80540a934 3.3.3 2024-10-14 09:05:49 -04:00
Vladimir Mandic 49b25830b4 add loaded property to model stats and mark models not loaded correctly.
Signed-off-by: Vladimir Mandic <mandic00@live.com>
2024-10-14 09:04:10 -04:00
Vladimir Mandic df73c8247f update changelog 2024-09-11 12:16:59 -04:00
Vladimir Mandic dd186ab065 release build 2024-09-11 12:16:36 -04:00
Vladimir Mandic a2acfc433e 3.3.2 2024-09-11 12:14:26 -04:00
Vladimir Mandic 644235433d full rebuild 2024-09-11 12:13:42 -04:00
Vladimir Mandic 42dfe18736 update face roll/pitch/yaw math 2024-09-11 12:13:03 -04:00
Vladimir Mandic c5b7b43fca 3.3.1 2024-09-11 11:23:18 -04:00
Vladimir Mandic 715210db51 add config.face.detector.square option 2024-09-11 11:16:07 -04:00
Vladimir Mandic 9e2c612c1f human 3.3 alpha test run 2024-09-10 15:49:23 -04:00
Vladimir Mandic 862de3e6c8 human 3.3 alpha with new build environment 2024-09-10 15:44:39 -04:00
Vladimir Mandic 1114014bfd update changelog 2024-04-17 11:37:23 -04:00
Vladimir Mandic 001a3d58ea release rebuild 2024-04-17 11:36:54 -04:00
Vladimir Mandic d7e66afe1f fix flazeface tensor scale and update build platform 2024-04-17 11:29:51 -04:00
Vladimir Mandic a2fedaba40 3.2.2 2024-04-17 10:31:25 -04:00
165 changed files with 19809 additions and 24578 deletions

View File

@ -1,9 +1,8 @@
{
"$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": false
"skipLibCheck": true
},
"newlineKind": "lf",
"dtsRollup": {

View File

@ -1,5 +1,9 @@
{
"globals": {},
"globals": {
},
"rules": {
"@typescript-eslint/no-require-imports":"off"
},
"overrides": [
{
"files": ["**/*.ts"],
@ -34,6 +38,8 @@
"@typescript-eslint/no-unsafe-call":"off",
"@typescript-eslint/no-unsafe-member-access":"off",
"@typescript-eslint/no-unsafe-return":"off",
"@typescript-eslint/no-require-imports":"off",
"@typescript-eslint/no-empty-object-type":"off",
"@typescript-eslint/non-nullable-type-assertion-style":"off",
"@typescript-eslint/prefer-for-of":"off",
"@typescript-eslint/prefer-nullish-coalescing":"off",
@ -155,9 +161,7 @@
"node": false,
"es2021": false
},
"extends": [
"plugin:json/recommended"
]
"extends": []
},
{
"files": ["**/*.html"],
@ -173,6 +177,7 @@
"extends": ["plugin:@html-eslint/recommended"],
"rules": {
"@html-eslint/element-newline":"off",
"@html-eslint/attrs-newline":"off",
"@html-eslint/indent": ["error", 2]
}
},

2
.gitignore vendored
View File

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

1
.npmrc
View File

@ -2,3 +2,4 @@ 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.2.1**
Version: **3.3.5**
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,12 +9,42 @@
## Changelog
### **3.3.5** 2025/02/05 mandic00@live.com
### **origin/main** 2024/10/24 mandic00@live.com
- 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,7 +4,6 @@
![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
@ -31,15 +30,20 @@
## Compatibility
- **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
**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`
<br>

View File

@ -10,12 +10,13 @@ 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 },
detector: { rotation: false, maxDetected: 100, minConfidence: 0.2, return: true, square: false },
iris: { enabled: true },
description: { enabled: true },
emotion: { enabled: true },
@ -93,7 +94,7 @@ function addFace(face, source) {
e.preventDefault();
document.getElementById('description').innerHTML = canvas.title;
};
human.tf.browser.draw(face.tensor, canvas);
human.draw.tensor(face.tensor, canvas);
human.tf.dispose(face.tensor);
return canvas;
}
@ -149,7 +150,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'];
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 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,
cacheSensitivity: 0.01,
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.tf.browser.draw(current.face.tensor, dom.canvas);
await human.draw.tensor(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,
cacheSensitivity: 0.01,
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.tf.browser.draw(face.tensor, c);
await human.draw.tensor(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.tf.browser.draw(current.tensor, canvas);
await human.draw.tensor(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.tf.browser.draw(res.face[i].tensor, canvas);
await human.draw.tensor(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.tf.browser.draw(result.face[0].tensor, c);
human.draw.tensor(result.face[0].tensor, c);
} else {
document.getElementById('compare-canvas').getContext('2d').drawImage(compare.original.canvas, 0, 0, 200, 200);
}

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,
cacheSensitivity: 0.01,
wasmPlatformFetch: true,
modelBasePath: 'https://vladmandic.github.io/human-models/models/',
};

View File

@ -92,7 +92,7 @@ async function detect(input) {
try {
result = await human.detect(tensor, myConfig);
} catch (err) {
log.error('caught');
log.error('caught', err);
}
// dispose image tensor as we no longer need it

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,
cacheSensitivity: 0.01,
face: { enabled: true, detector: { maxDetected: 100, minConfidence: 0.1 } },
object: { enabled: true, maxDetected: 100, minConfidence: 0.1 },
gesture: { enabled: true },

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.tf.browser.draw(rgba, dom.output); // draw raw output
human.draw.tensor(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

32293
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

1436
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

1448
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.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};
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};

View File

@ -1,6 +1,6 @@
{
"name": "@vladmandic/human",
"version": "3.2.1",
"version": "3.3.5",
"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,13 +8,7 @@
"browser": "dist/human.esm.js",
"types": "types/human.d.ts",
"exports": {
"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",
"node": "./dist/human.node.js",
"script": "./dist/human.js",
"module": "./dist/human.esm.js",
"types": "./types/human.d.ts",
@ -29,7 +23,9 @@
"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"
"dist/human.node-gpu.js": "./dist/human.node-gpu.js",
"require": "./dist/human.node.js",
"import": "./dist/human.esm.js"
},
"author": "Vladimir Mandic <mandic00@live.com>",
"bugs": {
@ -78,39 +74,40 @@
"tensorflow"
],
"devDependencies": {
"@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",
"@html-eslint/eslint-plugin": "^0.26.0",
"@html-eslint/parser": "^0.26.0",
"@microsoft/api-extractor": "^7.49.2",
"@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.0",
"@types/node": "^22.13.1",
"@types/offscreencanvas": "^2019.7.3",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"@typescript-eslint/parser": "^6.21.0",
"@vladmandic/build": "^0.9.3",
"@vladmandic/pilogger": "^0.4.9",
"@typescript-eslint/eslint-plugin": "^8.8.1",
"@typescript-eslint/parser": "^8.8.1",
"@vladmandic/build": "^0.10.2",
"@vladmandic/pilogger": "^0.5.1",
"@vladmandic/tfjs": "github:vladmandic/tfjs",
"canvas": "^2.11.2",
"esbuild": "^0.19.12",
"eslint": "8.55.0",
"canvas": "^3.1.0",
"esbuild": "^0.24.2",
"eslint": "8.57.0",
"eslint-config-airbnb-base": "^15.0.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-html": "^8.1.2",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-json": "^4.0.1",
"eslint-plugin-markdown": "^5.1.0",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^6.1.1",
"rimraf": "^5.0.5",
"tslib": "^2.6.2",
"typedoc": "0.25.4",
"typescript": "~5.3.3"
"eslint-plugin-promise": "^7.1.0",
"rimraf": "^6.0.1",
"tslib": "^2.8.1",
"typedoc": "0.27.6",
"typescript": "5.7.3"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 178 KiB

After

Width:  |  Height:  |  Size: 164 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 145 KiB

After

Width:  |  Height:  |  Size: 150 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';
export type BackendEnum = '' | 'cpu' | 'wasm' | 'webgl' | 'humangl' | 'tensorflow' | 'webgpu' | 'none';
/** Possible values for `human.warmup` */
export type WarmupEnum = '' | 'none' | 'face' | 'full' | 'body';
@ -39,6 +39,8 @@ 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,6 +2,7 @@
* 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';
@ -14,6 +15,7 @@ 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;
@ -60,6 +62,22 @@ 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,7 +60,9 @@ export const calculateFaceAngle = (face: FaceResult, imageSize: [number, number]
let thetaZ: number;
if (r10 < 1) { // YZX calculation
if (r10 > -1) {
thetaZ = Math.asin(r10);
// thetaZ = Math.asin(r10);
const cosThetaZ = Math.sqrt(r00 * r00 + r20 * r20); // <https://github.com/vladmandic/human/issues/464>
thetaZ = Math.atan2(r10, cosThetaZ);
thetaY = Math.atan2(-r20, r00);
thetaX = Math.atan2(-r12, r11);
} else {
@ -76,9 +78,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: 2 * -thetaX, yaw: 2 * -thetaY, roll: 2 * -thetaZ };
return { pitch: -thetaX, yaw: -thetaY, roll: -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,9 +55,20 @@ 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> = {};
t.resized = tf.image.resizeBilinear(inputImage, [inputSize, inputSize]);
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.div = tf.div(t.resized, constants.tf127);
t.normalized = tf.sub(t.div, constants.tf05);
t.normalized = tf.sub(t.div, constants.tf1);
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);
@ -81,7 +92,6 @@ 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]);
@ -89,9 +99,15 @@ 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: [points[0], points[1]] as Point,
endPoint: [points[2], points[3]] as Point,
startPoint: [unpadded[0], unpadded[1]] as Point,
endPoint: [unpadded[2], unpadded[3]] as Point,
landmarks: (await b.landmarks.array()) as Point[],
confidence,
};

View File

@ -17,7 +17,8 @@ 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);
}
return (options.multiplier || 20) * sum;
const dist = Math.round(100 * (options.multiplier || 20) * sum) / 100;
return dist;
}
// invert distance to similarity, normalize to given range and clamp
@ -25,7 +26,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.max(Math.min(norm, 1), 0); // clamp to 0..1
const clamp = Math.round(100 * Math.max(Math.min(norm, 1), 0)) / 100; // clamp to 0..1
return clamp;
};

View File

@ -290,7 +290,6 @@ 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

@ -27,7 +27,7 @@ class GLProgram {
this.gl = gl;
const vertexShader = this.compile(vertexSource, this.gl.VERTEX_SHADER);
const fragmentShader = this.compile(fragmentSource, this.gl.FRAGMENT_SHADER);
this.id = this.gl.createProgram() as WebGLProgram;
this.id = this.gl.createProgram();
if (!vertexShader || !fragmentShader) return;
if (!this.id) {
log('filter: could not create webgl program');

View File

@ -100,13 +100,13 @@ export class Models {
let totalSizeWeights = 0;
let totalSizeLoading = 0;
for (const m of Object.values(modelStats)) {
totalSizeFromManifest += m.sizeFromManifest;
totalSizeWeights += m.sizeLoadedWeights;
totalSizeLoading += m.sizeDesired;
totalSizeFromManifest += Number.isNaN(+m.sizeFromManifest) ? 0 : m.sizeFromManifest;
totalSizeWeights += Number.isNaN(+m.sizeLoadedWeights) ? 0 : m.sizeLoadedWeights;
totalSizeLoading += Number.isNaN(+m.sizeDesired) ? 0 : m.sizeDesired;
}
const percentageLoaded = totalSizeLoading > 0 ? totalSizeWeights / totalSizeLoading : 0;
return {
numLoadedModels: Object.values(modelStats).length,
numLoadedModels: Object.values(modelStats).filter((m) => m?.loaded).length,
numDefinedModels: Object.keys(this.models).length,
percentageLoaded,
totalSizeFromManifest,
@ -178,7 +178,7 @@ export class Models {
return models;
}
loaded() {
loaded(): string[] {
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 = `
export const face: string = `
/9j/4AAQSkZJRgABAQEAYABgAAD/4QBoRXhpZgAATU0AKgAAAAgABAEaAAUAAAABAAAAPgEbAAUA
AAABAAAARgEoAAMAAAABAAIAAAExAAIAAAARAAAATgAAAAAAAABgAAAAAQAAAGAAAAABcGFpbnQu
bmV0IDQuMi4xMwAA/9sAQwAGBAUGBQQGBgUGBwcGCAoQCgoJCQoUDg8MEBcUGBgXFBYWGh0lHxob

View File

@ -121,14 +121,17 @@ 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 = await navigator.gpu.requestAdapter();
const adapter: GPUAdapter = await navigator.gpu.requestAdapter() as GPUAdapter;
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 {
// @ts-ignore requestAdapterInfo is not in tslib
const adapterInfo = 'requestAdapterInfo' in adapter ? await adapter.requestAdapterInfo() : undefined;
let adapterInfo;
// @ts-ignore gpu adapter info
if ('requestAdapterInfo' in adapter) adapterInfo = await adapter?.requestAdapterInfo();
// @ts-ignore gpu adapter info
else adapterInfo = adapter.info;
// if (adapter.features) adapter.features.forEach((feature) => log('webgpu features:', feature));
log('webgpu adapter info:', adapterInfo);
}

View File

@ -14,6 +14,7 @@ const options = {
export interface ModelInfo {
name: string,
loaded: boolean,
inCache: boolean,
sizeDesired: number,
sizeFromManifest: number,
@ -42,6 +43,7 @@ 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],
@ -59,7 +61,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
let loaded = false;
modelStats[shortModelName].loaded = false;
try {
// @ts-ignore private function
model.findIOHandler(); // decide how to actually load a model
@ -74,13 +76,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 || 0;
modelStats[shortModelName].sizeLoadedWeights = model.artifacts?.weightData?.byteLength || model.artifacts?.weightData?.[0].byteLength || 0;
if (options.verbose) log('load:', { model: shortModelName, url: model['modelUrl'], bytes: modelStats[shortModelName].sizeLoadedWeights });
loaded = true;
modelStats[shortModelName].loaded = true;
} catch (err) {
log('error loading model:', modelUrl, err);
}
if (loaded && options.cacheModels && options.cacheSupported && !modelStats[shortModelName].inCache) { // save model to cache
if (modelStats[shortModelName].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,7 +154,12 @@ export class Env {
try {
if (this.webgpu.supported) {
const adapter = await navigator.gpu.requestAdapter();
this.webgpu.adapter = await adapter?.requestAdapterInfo();
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;
}
}
} catch {
this.webgpu.supported = false;

View File

@ -166,6 +166,7 @@ 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 @@
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"}
2025-02-05 09:39:04 DATA:  Build {"name":"@vladmandic/human","version":"3.3.5"}
2025-02-05 09:39:04 INFO:  Application: {"name":"@vladmandic/human","version":"3.3.5"}
2025-02-05 09:39:04 INFO:  Environment: {"profile":"production","config":".build.json","package":"package.json","tsconfig":true,"eslintrc":true,"git":true}
2025-02-05 09:39:04 INFO:  Toolchain: {"build":"0.10.2","esbuild":"0.24.2","typescript":"5.7.3","typedoc":"0.27.6","eslint":"8.57.0"}
2025-02-05 09:39:04 INFO:  Build: {"profile":"production","steps":["clean","compile","typings","typedoc","lint","changelog"]}
2025-02-05 09:39:04 STATE: Clean: {"locations":["dist/*","types/*","typedoc/*"]}
2025-02-05 09:39:04 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-02-05 09:39:04 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-02-05 09:39:04 STATE: Compile: {"name":"human/nodejs/cpu","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node.js","files":80,"inputBytes":678664,"outputBytes":321804}
2025-02-05 09:39:04 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-02-05 09:39:04 STATE: Compile: {"name":"human/nodejs/gpu","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node-gpu.js","files":80,"inputBytes":678672,"outputBytes":321808}
2025-02-05 09:39:04 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-02-05 09:39:04 STATE: Compile: {"name":"human/nodejs/wasm","format":"cjs","platform":"node","input":"src/human.ts","output":"dist/human.node-wasm.js","files":80,"inputBytes":679710,"outputBytes":321919}
2025-02-05 09:39:04 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-02-05 09:39:04 STATE: Compile: {"name":"human/browser/esm/nobundle","format":"esm","platform":"browser","input":"src/human.ts","output":"dist/human.esm-nobundle.js","files":80,"inputBytes":678397,"outputBytes":320365}
2025-02-05 09:39:04 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":1267320}
2025-02-05 09:39:04 STATE: Compile: {"name":"human/browser/iife/bundle","format":"iife","platform":"browser","input":"src/human.ts","output":"dist/human.js","files":80,"inputBytes":1945027,"outputBytes":1583413}
2025-02-05 09:39:04 STATE: Compile: {"name":"human/browser/esm/bundle","format":"esm","platform":"browser","input":"src/human.ts","output":"dist/human.esm.js","files":80,"inputBytes":1945027,"outputBytes":2067530}
2025-02-05 09:39:06 STATE: Typings: {"input":"src/human.ts","output":"types/lib","files":78}
2025-02-05 09:39:08 STATE: TypeDoc: {"input":"src/human.ts","output":"typedoc","objects":81,"generated":true}
2025-02-05 09:39:08 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-02-05 09:39:08 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-02-05 09:39:08 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}
2025-02-05 09:39:16 STATE: Lint: {"locations":["**/*.json","src/**/*.ts","test/**/*.js","demo/**/*.js","**/*.md"],"files":171,"errors":0,"warnings":0}
2025-02-05 09:39:16 STATE: ChangeLog: {"repository":"https://github.com/vladmandic/human","branch":"main","output":"CHANGELOG.md"}
2025-02-05 09:39:16 STATE: Copy: {"input":"node_modules/@vladmandic/tfjs/types/tfjs-core.d.ts","output":"types/tfjs-core.d.ts"}
2025-02-05 09:39:16 INFO:  Done...
2025-02-05 09:39:16 STATE: Copy: {"input":"node_modules/@vladmandic/tfjs/types/tfjs.d.ts","output":"types/tfjs.esm.d.ts"}
2025-02-05 09:39:16 STATE: Copy: {"input":"src/types/tsconfig.json","output":"types/tsconfig.json"}
2025-02-05 09:39:16 STATE: Copy: {"input":"src/types/eslint.json","output":"types/.eslintrc.json"}
2025-02-05 09:39:16 STATE: Copy: {"input":"src/types/tfjs.esm.d.ts","output":"dist/tfjs.esm.d.ts"}
2025-02-05 09:39:16 STATE: Filter: {"input":"types/tfjs-core.d.ts"}
2025-02-05 09:39:17 STATE: API-Extractor: {"succeeeded":true,"errors":0,"warnings":0}
2025-02-05 09:39:17 STATE: Filter: {"input":"types/human.d.ts"}
2025-02-05 09:39:17 STATE: Write: {"output":"dist/human.esm-nobundle.d.ts"}
2025-02-05 09:39:17 STATE: Write: {"output":"dist/human.esm.d.ts"}
2025-02-05 09:39:17 STATE: Write: {"output":"dist/human.d.ts"}
2025-02-05 09:39:17 STATE: Write: {"output":"dist/human.node-gpu.d.ts"}
2025-02-05 09:39:17 STATE: Write: {"output":"dist/human.node.d.ts"}
2025-02-05 09:39:17 STATE: Write: {"output":"dist/human.node-wasm.d.ts"}
2025-02-05 09:39:17 INFO:  Analyze models: {"folders":8,"result":"models/models.json"}
2025-02-05 09:39:17 STATE: Models {"folder":"./models","models":12}
2025-02-05 09:39:17 STATE: Models {"folder":"../human-models/models","models":44}
2025-02-05 09:39:17 STATE: Models {"folder":"../blazepose/model/","models":4}
2025-02-05 09:39:17 STATE: Models {"folder":"../anti-spoofing/model","models":1}
2025-02-05 09:39:17 STATE: Models {"folder":"../efficientpose/models","models":3}
2025-02-05 09:39:17 STATE: Models {"folder":"../insightface/models","models":5}
2025-02-05 09:39:17 STATE: Models {"folder":"../movenet/models","models":3}
2025-02-05 09:39:17 STATE: Models {"folder":"../nanodet/models","models":4}
2025-02-05 09:39:17 STATE: Models: {"count":58,"totalSize":380063249}
2025-02-05 09:39:17 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,
cacheSensitivity: 0.01,
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,
cacheSensitivity: 0.01,
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,
cacheSensitivity: 0.01,
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,
cacheSensitivity: 0.01,
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,
cacheSensitivity: 0.01,
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,
cacheSensitivity: 0.01,
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');
log('error', 'error warmup', err);
}
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", "demo/**/*.ts", "demo/facedetect/loader.js"],
"include": ["src", "tfjs/*.ts", "types/human.d.ts", "test/**/*.ts"],
"typedocOptions": {
"excludeExternals": true,
"externalPattern": ["**/node_modules/**", "tfjs/"]
"externalPattern": ["**/node_modules/**", "tfjs/", "demo/"]
}
}

View File

@ -0,0 +1 @@
window.hierarchyData = "eJyV1D1vgzAQBuD/crPTYvPN1s+0UqsOGasMFI7ELdiR7Vaqovz3yhkKmOWygAX38nDG+AhGa2eheuciyrYMDHY9Nk5qZaE6gr/qz6oeECpYo0IjmzutOrkDBl9StVCJNGPwbXqoQCqHpqsbtNez2qu9G3pg0PS1tVCBs+3Kh1f/AX9zL/vWoDq/DeeMC5EyLmI/inPGRSL8oWBcpIk/lIyLzI/yiHFR+FHJGY+jnPGYp9sTA/+gSQOPdYP36LBx2pC6WAYIrZxdkQbuK9o92RyLqV4c9vlspCV7YzHZywPvxjlUfuWQ0SBBlROx+KK2MfJwkb3IkPUi0B8GfZE8q6eqaRLOtnJyc9C6o8/2PEGWy0B+kT+o0NLX1jxAdbOw4zXW9H92LKZ6eRR4ZOsyp5j2davbX5IzFlKdcrofPNWqJTljIdGJo+k+8PbxiY0jSdNSqsWne+oGdwMqV5N/vmWA4p5Of40CVuo="

View File

@ -15,8 +15,6 @@
--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;
}
@ -30,7 +28,6 @@
--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);
} }
@ -43,7 +40,6 @@
--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);
} }
@ -56,7 +52,6 @@
--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);
}
@ -69,7 +64,6 @@
--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);
}
@ -81,5 +75,4 @@
.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); }

18
typedoc/assets/icons.js Normal file

File diff suppressed because one or more lines are too long

1
typedoc/assets/icons.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 12 KiB

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
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"
window.navigationData = "eJyVmU9z2zYQxb8Le3WbSFbSxjf/URVP7Npje5pDJgeYXEmoyAUHBBWrnXz3DglJAAlwl7rue+8nEABJcPXtv8TAm0kukkyLH8lZUgqzTi6SQmV1DtW7pvrb2hR5cpZsJGbJxewsSdcyzzRgcvHtGFelkQorR9gKLcXrkbHXu6zz6c+zI0HkuUsva0zbgE2LPO8mP8685KvKdoPRRiSyqcCtqAbTVibyS5HCYLoRiewKKlPr4fheJwhrgdlgvBGJrERpBrONSGTV6z+QDqetTORL0JXCwbyVibwBrJQezFs5yH/3CIUw6Trc72151Ia/gSrVsjT+MMyuPDKc3sVN33/6ffLB3/j3jf+hf//4LN/B0TJZGYHxTWlpBwe1q2V8X1lAoxLhShYyF1qa6E1pEc5Dr5LKIK8iy9TWR63TfQ+R5qKqHOI+QppM//DG8AU0Qv5QegyJBnRzcx8xR1NveT589Be68T4bYUiUc1GsrchlJgy07ug8W1rHR871S++eOsz1S+Rm8pf7SeDGpQDronrX1LoJf0bnuA3XY45bahUWWpTr3sUeok6jCJ/rQmAYbstUrj8vh6Ct/zqhsl/h9VoUYdbWqeSVynbXCpdyFd0rTqY2SeP6ArtSSTSDmIOBAz1BVefDGCtTEOJy+Eu50eJH8Iz0CJ5OYf4UKVyikc+lUktiQBEfizUGsBkAh+36OCxDGwc5vIz40QVOHm0gNUqzXN/GQeeFGjHWjotDLkBwY3QWDnarZcXAnIWD3cktIFQcsGvjoPdQrRmgs3Aw4tZ3MgmRuQFy+j0DBVoAgpYpQeo4aFR7uiZRnoNCfRaYERwncxBiop3MHjFucamijKNKIR7awztxOb6BBxGX5Bso0GP7OUCAfAMFIhB8+BlWBaARzIMptFFQexAgcL6BAl3i7rr3KWu/II4C9+FwibvbQqwgAmjrI/J/ywxUJN/WufyVSDeA2Rzroo/wJJaist0lorILEIA66mmsq1z8C4+qCiZowHYafb5cylQCGv4XOtYxv7Lo9xkcdRFrMcQpdwKzQuhNDHPQTuGQ8xmYTiEfJ+gvMBTc953Cv1dbYNB7yynU5ioZ6t7CU99CyhuX2p+m+sl9mU1vAU3w8LFVNvtmQKPI4w+wrsqx7Dkuut89aQxlaL/7GsuRuIKgQWSr47LXtc7j+UYZx7iRGtLY2vZkjrYAzMKrsVU+2058/w18QHgiR2oOQgMr7EljKC+7Mopo6ly+fSXaA0ywY32N5WBZB/PRFtmkltXAPHgSR7HDjM2EUzjGY7e/YOOPkZ5CkHzqdM9t8Clomoc5/5AVOzD0dY5nezmTmz7nUB+Xnw7kpyPz5wP585H52UB+NjJ/JzfBajiFY3wVuqjL2Go4hW1ew1LUuYn/jbTXiL+QwG8suiTgtt+m68aKMt6rbgWi070fkn9wz8C+aH9x2r5lOvk0O38/+/n9f3cUMM8="

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

@ -0,0 +1,2 @@
<!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.5</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(() => app?app.showPage():document.body.style.removeProperty("display"),500)</script><header class="tsd-page-toolbar"><div class="tsd-toolbar-contents container"><div class="table-cell" id="tsd-search"><div class="field"><label for="tsd-search-field" class="tsd-widget tsd-toolbar-icon search no-caption"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><use href="../assets/icons.svg#icon-search"></use></svg></label><input type="text" id="tsd-search-field" aria-label="Search"/></div><div class="field"><div id="tsd-toolbar-links"></div></div><ul class="results"><li class="state loading">Preparing search index...</li><li class="state failure">The search index is not available</li></ul><a href="../index.html" class="title">@vladmandic/human - v3.3.5</a></div><div class="table-cell" id="tsd-widgets"><a href="#" class="tsd-widget tsd-toolbar-icon menu no-caption" data-toggle="menu" aria-label="Menu"><svg width="16" height="16" viewBox="0 0 16 16" fill="none"><use href="../assets/icons.svg#icon-menu"></use></svg></a></div></div></header><div class="container container-main"><div class="col-content"><div class="tsd-page-title"><ul class="tsd-breadcrumb"><li><a href="../index.html">@vladmandic/human</a></li><li><a href="../modules/draw.html">draw</a></li><li><a href="draw.tensor.html">tensor</a></li></ul><h1>Function tensor</h1></div><section class="tsd-panel"><ul class="tsd-signatures"><li class="tsd-signature tsd-anchor-link"><a id="tensor" class="tsd-anchor"></a><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"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></li><li 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></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"><h3><svg width="20" height="20" viewBox="0 0 24 24" fill="none"><use href="../assets/icons.svg#icon-chevronDown"></use></svg>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.5</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

1
typedoc/hierarchy.html Normal file

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

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