mirror of https://github.com/vladmandic/human
added human.env diagnostic class
parent
f6724de956
commit
7fa09937b4
|
@ -13,16 +13,23 @@ assignees: vladmandic
|
||||||
|
|
||||||
**Expected Behavior**
|
**Expected Behavior**
|
||||||
|
|
||||||
**Environment
|
**Environment**
|
||||||
|
|
||||||
- Module version?
|
- Human library version?
|
||||||
- Built-in demo or custom code?
|
- Built-in demo or custom code?
|
||||||
- Type of module used (e.g. `js`, `esm`, `esm-nobundle`)?
|
- Type of module used (e.g. `js`, `esm`, `esm-nobundle`)?
|
||||||
- Browser or NodeJS and version (e.g. NodeJS 14.15 or Chrome 89)?
|
- TensorFlow/JS version (if not using bundled module)?
|
||||||
- OS and Hardware platform (e.g. Windows 10, Ubuntu Linux on x64, Android 10)?
|
- Browser or NodeJS and version (e.g. *NodeJS 14.15* or *Chrome 89*)?
|
||||||
- Packager (if any) (e.g, webpack, rollup, parcel, esbuild, etc.)?
|
- OS and Hardware platform (e.g. *Windows 10*, *Ubuntu Linux on x64*, *Android 10*)?
|
||||||
|
- Packager (if any) (e.g, *webpack*, *rollup*, *parcel*, *esbuild*, etc.)?
|
||||||
|
- Framework (if any) (e.g. *React*, *NextJS*, etc.)?
|
||||||
|
|
||||||
|
**Diagnostics**
|
||||||
|
|
||||||
|
- Check out any applicable [diagnostic steps](https://github.com/vladmandic/human/wiki/Diag)
|
||||||
|
|
||||||
**Additional**
|
**Additional**
|
||||||
|
|
||||||
- For installation or startup issues include your `package.json`
|
- For installation or startup issues include your `package.json`
|
||||||
- For usage issues, it is recommended to post your code as [gist](https://gist.github.com/)
|
- For usage issues, it is recommended to post your code as [gist](https://gist.github.com/)
|
||||||
|
- For general questions, create a [discussion topic](https://github.com/vladmandic/human/discussions)
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
|
|
||||||
### **HEAD -> main** 2021/09/12 mandic00@live.com
|
### **HEAD -> main** 2021/09/12 mandic00@live.com
|
||||||
|
|
||||||
|
- release candidate
|
||||||
|
- parametrize face config
|
||||||
- mark all config items as optional
|
- mark all config items as optional
|
||||||
- redefine config and result interfaces
|
- redefine config and result interfaces
|
||||||
- fix usge of string enums
|
- fix usge of string enums
|
||||||
|
|
|
@ -72,6 +72,7 @@ Check out [**Live Demo**](https://vladmandic.github.io/human/demo/index.html) ap
|
||||||
- [**Performance Notes**](https://github.com/vladmandic/human/wiki/Performance)
|
- [**Performance Notes**](https://github.com/vladmandic/human/wiki/Performance)
|
||||||
- [**Performance Profiling**](https://github.com/vladmandic/human/wiki/Profiling)
|
- [**Performance Profiling**](https://github.com/vladmandic/human/wiki/Profiling)
|
||||||
- [**Platform Support**](https://github.com/vladmandic/human/wiki/Platforms)
|
- [**Platform Support**](https://github.com/vladmandic/human/wiki/Platforms)
|
||||||
|
- [**Diagnostic and Performance trace information**](https://github.com/vladmandic/human/wiki/Diag)
|
||||||
- [**List of Models & Credits**](https://github.com/vladmandic/human/wiki/Models)
|
- [**List of Models & Credits**](https://github.com/vladmandic/human/wiki/Models)
|
||||||
- [**Security & Privacy Policy**](https://github.com/vladmandic/human/blob/main/SECURITY.md)
|
- [**Security & Privacy Policy**](https://github.com/vladmandic/human/blob/main/SECURITY.md)
|
||||||
- [**License & Usage Restrictions**](https://github.com/vladmandic/human/blob/main/LICENSE)
|
- [**License & Usage Restrictions**](https://github.com/vladmandic/human/blob/main/LICENSE)
|
||||||
|
@ -309,6 +310,12 @@ For more info, see [**Configuration Details**](https://github.com/vladmandic/hum
|
||||||
|
|
||||||
<br><hr><br>
|
<br><hr><br>
|
||||||
|
|
||||||
|
## Diagnostics
|
||||||
|
|
||||||
|
- [How to get diagnostic information or performance trace information](https://github.com/vladmandic/human/wiki/Diag)
|
||||||
|
|
||||||
|
<br><hr><br>
|
||||||
|
|
||||||
`Human` library is written in `TypeScript` [4.3](https://www.typescriptlang.org/docs/handbook/intro.html)
|
`Human` library is written in `TypeScript` [4.3](https://www.typescriptlang.org/docs/handbook/intro.html)
|
||||||
Conforming to `JavaScript` [ECMAScript version 2020](https://www.ecma-international.org/ecma-262/11.0/index.html) standard
|
Conforming to `JavaScript` [ECMAScript version 2020](https://www.ecma-international.org/ecma-262/11.0/index.html) standard
|
||||||
Build target is `JavaScript` [EMCAScript version 2018](https://262.ecma-international.org/9.0/)
|
Build target is `JavaScript` [EMCAScript version 2018](https://262.ecma-international.org/9.0/)
|
||||||
|
|
|
@ -953,8 +953,7 @@ async function main() {
|
||||||
|
|
||||||
// create instance of human
|
// create instance of human
|
||||||
human = new Human(userConfig);
|
human = new Human(userConfig);
|
||||||
log('human version:', Human.version);
|
log('human version:', human.version);
|
||||||
log('tfjs version:', human.tf.version.tfjs);
|
|
||||||
userConfig = { ...human.config, ...userConfig };
|
userConfig = { ...human.config, ...userConfig };
|
||||||
if (typeof tf !== 'undefined') {
|
if (typeof tf !== 'undefined') {
|
||||||
// eslint-disable-next-line no-undef
|
// eslint-disable-next-line no-undef
|
||||||
|
@ -962,6 +961,7 @@ async function main() {
|
||||||
// eslint-disable-next-line no-undef
|
// eslint-disable-next-line no-undef
|
||||||
human.tf = tf; // use externally loaded version of tfjs
|
human.tf = tf; // use externally loaded version of tfjs
|
||||||
}
|
}
|
||||||
|
log('tfjs version:', human.tf.version.tfjs);
|
||||||
|
|
||||||
// setup main menu
|
// setup main menu
|
||||||
await setupMenu();
|
await setupMenu();
|
||||||
|
@ -1013,6 +1013,8 @@ async function main() {
|
||||||
log('overriding images list:', JSON.parse(params.get('images')));
|
log('overriding images list:', JSON.parse(params.get('images')));
|
||||||
await detectSampleImages();
|
await detectSampleImages();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (human.config.debug) log('environment:', human.env);
|
||||||
}
|
}
|
||||||
|
|
||||||
window.onload = main;
|
window.onload = main;
|
||||||
|
|
|
@ -246,9 +246,11 @@ export interface Config {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
const config: Config = {
|
const config: Config = {
|
||||||
backend: 'humangl', // select tfjs backend to use, leave empty to use default backend
|
backend: '', // select tfjs backend to use, leave empty to use default backend
|
||||||
// can be 'webgl', 'wasm', 'cpu', or 'humangl' which is a custom version of webgl
|
// can be 'webgl', 'wasm', 'cpu', or 'humangl' which is a custom version of webgl
|
||||||
modelBasePath: '../models/', // base path for all models
|
// default set to `humangl` for browsers and `tensorflow` for nodejs
|
||||||
|
modelBasePath: '', // base path for all models
|
||||||
|
// default set to `../models/` for browsers and `file://models/` for nodejs
|
||||||
wasmPath: '', // path for wasm binaries, only used for backend: wasm
|
wasmPath: '', // path for wasm binaries, only used for backend: wasm
|
||||||
// default set to download from jsdeliv during Human class instantiation
|
// default set to download from jsdeliv during Human class instantiation
|
||||||
debug: true, // print additional status messages to console
|
debug: true, // print additional status messages to console
|
||||||
|
|
|
@ -0,0 +1,128 @@
|
||||||
|
import * as tf from '../dist/tfjs.esm.js';
|
||||||
|
|
||||||
|
export interface Env {
|
||||||
|
browser: undefined | boolean,
|
||||||
|
node: undefined | boolean,
|
||||||
|
worker: undefined | boolean,
|
||||||
|
platform: undefined | string,
|
||||||
|
agent: undefined | string,
|
||||||
|
backends: string[],
|
||||||
|
tfjs: {
|
||||||
|
version: undefined | string,
|
||||||
|
external: undefined | boolean,
|
||||||
|
},
|
||||||
|
wasm: {
|
||||||
|
supported: undefined | boolean,
|
||||||
|
simd: undefined | boolean,
|
||||||
|
multithread: undefined | boolean,
|
||||||
|
},
|
||||||
|
webgl: {
|
||||||
|
supported: undefined | boolean,
|
||||||
|
version: undefined | string,
|
||||||
|
renderer: undefined | string,
|
||||||
|
},
|
||||||
|
webgpu: {
|
||||||
|
supported: undefined | boolean,
|
||||||
|
adapter: undefined | string,
|
||||||
|
},
|
||||||
|
kernels: string[],
|
||||||
|
}
|
||||||
|
|
||||||
|
export const env: Env = {
|
||||||
|
browser: undefined,
|
||||||
|
node: undefined,
|
||||||
|
worker: undefined,
|
||||||
|
platform: undefined,
|
||||||
|
agent: undefined,
|
||||||
|
backends: [],
|
||||||
|
tfjs: {
|
||||||
|
version: undefined,
|
||||||
|
external: undefined,
|
||||||
|
},
|
||||||
|
wasm: {
|
||||||
|
supported: undefined,
|
||||||
|
simd: undefined,
|
||||||
|
multithread: undefined,
|
||||||
|
},
|
||||||
|
webgl: {
|
||||||
|
supported: undefined,
|
||||||
|
version: undefined,
|
||||||
|
renderer: undefined,
|
||||||
|
},
|
||||||
|
webgpu: {
|
||||||
|
supported: undefined,
|
||||||
|
adapter: undefined,
|
||||||
|
},
|
||||||
|
kernels: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
export function cpuinfo() {
|
||||||
|
const cpu = { model: '', flags: [] };
|
||||||
|
if (env.node && env.platform?.startsWith('linux')) {
|
||||||
|
// eslint-disable-next-line global-require
|
||||||
|
const fs = require('fs');
|
||||||
|
try {
|
||||||
|
const data = fs.readFileSync('/proc/cpuinfo').toString();
|
||||||
|
for (const line of data.split('\n')) {
|
||||||
|
if (line.startsWith('model name')) {
|
||||||
|
cpu.model = line.match(/:(.*)/g)[0].replace(':', '').trim();
|
||||||
|
}
|
||||||
|
if (line.startsWith('flags')) {
|
||||||
|
cpu.flags = line.match(/:(.*)/g)[0].replace(':', '').trim().split(' ').sort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch { /**/ }
|
||||||
|
}
|
||||||
|
if (!env['cpu']) Object.defineProperty(env, 'cpu', { value: cpu });
|
||||||
|
else env['cpu'] = cpu;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function get() {
|
||||||
|
env.browser = typeof navigator !== 'undefined';
|
||||||
|
env.node = typeof process !== 'undefined';
|
||||||
|
// @ts-ignore WorkerGlobalScope evaluated in browser only
|
||||||
|
env.worker = env.browser ? (typeof WorkerGlobalScope !== 'undefined') : undefined;
|
||||||
|
env.tfjs.version = tf.version_core;
|
||||||
|
|
||||||
|
// get platform and agent
|
||||||
|
if (typeof navigator !== 'undefined') {
|
||||||
|
const raw = navigator.userAgent.match(/\(([^()]+)\)/g);
|
||||||
|
if (raw && raw[0]) {
|
||||||
|
const platformMatch = raw[0].match(/\(([^()]+)\)/g);
|
||||||
|
env.platform = (platformMatch && platformMatch[0]) ? platformMatch[0].replace(/\(|\)/g, '') : '';
|
||||||
|
env.agent = navigator.userAgent.replace(raw[0], '');
|
||||||
|
if (env.platform[1]) env.agent = env.agent.replace(raw[1], '');
|
||||||
|
env.agent = env.agent.replace(/ /g, ' ');
|
||||||
|
}
|
||||||
|
} else if (typeof process !== 'undefined') {
|
||||||
|
env.platform = `${process.platform} ${process.arch}`;
|
||||||
|
env.agent = `NodeJS ${process.version}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// analyze backends
|
||||||
|
env.backends = Object.keys(tf.engine().registryFactory);
|
||||||
|
env.wasm.supported = env.backends.includes('wasm');
|
||||||
|
if (env.wasm.supported) {
|
||||||
|
env.wasm.simd = await tf.env().getAsync('WASM_HAS_SIMD_SUPPORT');
|
||||||
|
env.wasm.multithread = await tf.env().getAsync('WASM_HAS_MULTITHREAD_SUPPORT');
|
||||||
|
}
|
||||||
|
|
||||||
|
env.webgl.supported = typeof tf.backend().gpgpu !== 'undefined';
|
||||||
|
if (env.webgl.supported) {
|
||||||
|
// @ts-ignore getGPGPUContext only exists on WebGL backend
|
||||||
|
const gl = await tf.backend().getGPGPUContext().gl;
|
||||||
|
if (gl) {
|
||||||
|
env.webgl.version = gl.getParameter(gl.VERSION);
|
||||||
|
env.webgl.renderer = gl.getParameter(gl.RENDERER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
env.webgpu.supported = env.browser && typeof navigator['gpu'] !== 'undefined';
|
||||||
|
if (env.webgpu.supported) env.webgpu.adapter = (await navigator['gpu'].requestAdapter())?.name;
|
||||||
|
|
||||||
|
// enumerate kernels
|
||||||
|
env.kernels = tf.getKernelsForBackend(tf.getBackend()).map((kernel) => kernel.kernelName);
|
||||||
|
|
||||||
|
// get cpu info
|
||||||
|
// cpuinfo();
|
||||||
|
}
|
30
src/human.ts
30
src/human.ts
|
@ -5,7 +5,6 @@
|
||||||
import { log, now, mergeDeep } from './helpers';
|
import { log, now, mergeDeep } from './helpers';
|
||||||
import { Config, defaults } from './config';
|
import { Config, defaults } from './config';
|
||||||
import { Result, FaceResult, HandResult, BodyResult, ObjectResult, GestureResult } from './result';
|
import { Result, FaceResult, HandResult, BodyResult, ObjectResult, GestureResult } from './result';
|
||||||
import * as sysinfo from './sysinfo';
|
|
||||||
import * as tf from '../dist/tfjs.esm.js';
|
import * as tf from '../dist/tfjs.esm.js';
|
||||||
import * as backend from './tfjs/backend';
|
import * as backend from './tfjs/backend';
|
||||||
import * as models from './models';
|
import * as models from './models';
|
||||||
|
@ -26,6 +25,7 @@ import * as draw from './draw/draw';
|
||||||
import * as persons from './persons';
|
import * as persons from './persons';
|
||||||
import * as interpolate from './interpolate';
|
import * as interpolate from './interpolate';
|
||||||
import * as sample from './sample';
|
import * as sample from './sample';
|
||||||
|
import * as env from './env';
|
||||||
import * as app from '../package.json';
|
import * as app from '../package.json';
|
||||||
import { Tensor, GraphModel } from './tfjs/types';
|
import { Tensor, GraphModel } from './tfjs/types';
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@ import { Tensor, GraphModel } from './tfjs/types';
|
||||||
export * from './config';
|
export * from './config';
|
||||||
export * from './result';
|
export * from './result';
|
||||||
export type { DrawOptions } from './draw/draw';
|
export type { DrawOptions } from './draw/draw';
|
||||||
|
export { env } from './env';
|
||||||
|
|
||||||
/** Defines all possible input types for **Human** detection
|
/** Defines all possible input types for **Human** detection
|
||||||
* @typedef Input Type
|
* @typedef Input Type
|
||||||
|
@ -93,6 +94,10 @@ export class Human {
|
||||||
* - Can be embedded or externally provided
|
* - Can be embedded or externally provided
|
||||||
*/
|
*/
|
||||||
tf: TensorFlow;
|
tf: TensorFlow;
|
||||||
|
/**
|
||||||
|
* Object containing environment information used for diagnostics
|
||||||
|
*/
|
||||||
|
env: env.Env;
|
||||||
/** Draw helper classes that can draw detected objects on canvas using specified draw
|
/** Draw helper classes that can draw detected objects on canvas using specified draw
|
||||||
* - options: {@link DrawOptions} global settings for all draw operations, can be overriden for each draw method
|
* - options: {@link DrawOptions} global settings for all draw operations, can be overriden for each draw method
|
||||||
* - face: draw detected faces
|
* - face: draw detected faces
|
||||||
|
@ -141,8 +146,6 @@ export class Human {
|
||||||
faceTriangulation: typeof facemesh.triangulation;
|
faceTriangulation: typeof facemesh.triangulation;
|
||||||
/** Refernce UV map of 468 values, used for 3D mapping of the face mesh */
|
/** Refernce UV map of 468 values, used for 3D mapping of the face mesh */
|
||||||
faceUVMap: typeof facemesh.uvmap;
|
faceUVMap: typeof facemesh.uvmap;
|
||||||
/** Platform and agent information detected by Human */
|
|
||||||
sysinfo: { platform: string, agent: string };
|
|
||||||
/** Performance object that contains values for all recently performed operations */
|
/** Performance object that contains values for all recently performed operations */
|
||||||
performance: Record<string, number>; // perf members are dynamically defined as needed
|
performance: Record<string, number>; // perf members are dynamically defined as needed
|
||||||
#numTensors: number;
|
#numTensors: number;
|
||||||
|
@ -159,9 +162,13 @@ export class Human {
|
||||||
* @param userConfig: {@link Config}
|
* @param userConfig: {@link Config}
|
||||||
*/
|
*/
|
||||||
constructor(userConfig?: Partial<Config>) {
|
constructor(userConfig?: Partial<Config>) {
|
||||||
|
env.get();
|
||||||
|
this.env = env.env;
|
||||||
|
defaults.wasmPath = `https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-backend-wasm@${tf.version_core}/dist/`;
|
||||||
|
defaults.modelBasePath = this.env.browser ? '../models/' : 'file://models/';
|
||||||
|
defaults.backend = this.env.browser ? 'humangl' : 'tensorflow';
|
||||||
this.version = app.version; // expose version property on instance of class
|
this.version = app.version; // expose version property on instance of class
|
||||||
Object.defineProperty(this, 'version', { value: app.version }); // expose version property directly on class itself
|
Object.defineProperty(this, 'version', { value: app.version }); // expose version property directly on class itself
|
||||||
defaults.wasmPath = `https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-backend-wasm@${tf.version_core}/dist/`;
|
|
||||||
this.config = mergeDeep(defaults, userConfig || {});
|
this.config = mergeDeep(defaults, userConfig || {});
|
||||||
this.tf = tf;
|
this.tf = tf;
|
||||||
this.draw = draw;
|
this.draw = draw;
|
||||||
|
@ -199,7 +206,6 @@ export class Human {
|
||||||
this.faceTriangulation = facemesh.triangulation;
|
this.faceTriangulation = facemesh.triangulation;
|
||||||
this.faceUVMap = facemesh.uvmap;
|
this.faceUVMap = facemesh.uvmap;
|
||||||
// include platform info
|
// include platform info
|
||||||
this.sysinfo = sysinfo.info();
|
|
||||||
this.#lastInputSum = 1;
|
this.#lastInputSum = 1;
|
||||||
this.#emit('create');
|
this.#emit('create');
|
||||||
}
|
}
|
||||||
|
@ -287,10 +293,9 @@ export class Human {
|
||||||
if (this.#firstRun) { // print version info on first run and check for correct backend setup
|
if (this.#firstRun) { // print version info on first run and check for correct backend setup
|
||||||
if (this.config.debug) log(`version: ${this.version}`);
|
if (this.config.debug) log(`version: ${this.version}`);
|
||||||
if (this.config.debug) log(`tfjs version: ${this.tf.version_core}`);
|
if (this.config.debug) log(`tfjs version: ${this.tf.version_core}`);
|
||||||
if (this.config.debug) log('platform:', this.sysinfo.platform);
|
if (this.config.debug) log('environment:', env.env);
|
||||||
if (this.config.debug) log('agent:', this.sysinfo.agent);
|
|
||||||
|
|
||||||
await this.#checkBackend(true);
|
await this.#checkBackend();
|
||||||
if (this.tf.ENV.flags.IS_BROWSER) {
|
if (this.tf.ENV.flags.IS_BROWSER) {
|
||||||
if (this.config.debug) log('configuration:', this.config);
|
if (this.config.debug) log('configuration:', this.config);
|
||||||
if (this.config.debug) log('tf flags:', this.tf.ENV.flags);
|
if (this.config.debug) log('tf flags:', this.tf.ENV.flags);
|
||||||
|
@ -316,8 +321,8 @@ export class Human {
|
||||||
|
|
||||||
// check if backend needs initialization if it changed
|
// check if backend needs initialization if it changed
|
||||||
/** @hidden */
|
/** @hidden */
|
||||||
#checkBackend = async (force = false) => {
|
#checkBackend = async () => {
|
||||||
if (this.config.backend && (this.config.backend.length > 0) && force || (this.tf.getBackend() !== this.config.backend)) {
|
if (this.#firstRun || (this.config.backend && (this.config.backend.length > 0) || (this.tf.getBackend() !== this.config.backend))) {
|
||||||
const timeStamp = now();
|
const timeStamp = now();
|
||||||
this.state = 'backend';
|
this.state = 'backend';
|
||||||
/* force backend reload
|
/* force backend reload
|
||||||
|
@ -343,7 +348,7 @@ export class Human {
|
||||||
this.config.backend = 'humangl';
|
this.config.backend = 'humangl';
|
||||||
}
|
}
|
||||||
if (this.tf.ENV.flags.IS_NODE && (this.config.backend === 'webgl' || this.config.backend === 'humangl')) {
|
if (this.tf.ENV.flags.IS_NODE && (this.config.backend === 'webgl' || this.config.backend === 'humangl')) {
|
||||||
log('override: backend set to webgl while running in nodejs');
|
log(`override: backend set to ${this.config.backend} while running in nodejs`);
|
||||||
this.config.backend = 'tensorflow';
|
this.config.backend = 'tensorflow';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -410,6 +415,9 @@ export class Human {
|
||||||
this.tf.enableProdMode();
|
this.tf.enableProdMode();
|
||||||
await this.tf.ready();
|
await this.tf.ready();
|
||||||
this.performance.backend = Math.trunc(now() - timeStamp);
|
this.performance.backend = Math.trunc(now() - timeStamp);
|
||||||
|
|
||||||
|
env.get(); // update env on backend init
|
||||||
|
this.env = env.env;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
2
wiki
2
wiki
|
@ -1 +1 @@
|
||||||
Subproject commit ec49beb9f19c0abde3e62b24ba2c7749ef54c9aa
|
Subproject commit ee12bda3113d3d893c898a9827f9c174d4058fb8
|
Loading…
Reference in New Issue