mirror of https://github.com/vladmandic/human
switch to central logger
parent
9340cb41f0
commit
adf638d306
|
@ -5,7 +5,6 @@ export default {
|
|||
backend: 'webgl', // select tfjs backend to use
|
||||
wasmPath: '../assets/', // path for wasm binaries
|
||||
// only used for backend: wasm
|
||||
console: true, // enable debugging output to console
|
||||
async: true, // execute enabled models in parallel
|
||||
// this disables per-model performance data but
|
||||
// slightly increases performance
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
import Human from '../dist/human.esm.js';
|
||||
|
||||
let config;
|
||||
let busy = false;
|
||||
const human = new Human();
|
||||
|
||||
const log = (...msg) => {
|
||||
function log(...msg) {
|
||||
const dt = new Date();
|
||||
const ts = `${dt.getHours().toString().padStart(2, '0')}:${dt.getMinutes().toString().padStart(2, '0')}:${dt.getSeconds().toString().padStart(2, '0')}.${dt.getMilliseconds().toString().padStart(3, '0')}`;
|
||||
// eslint-disable-next-line no-console
|
||||
if (config.console) console.log(...msg);
|
||||
};
|
||||
if (msg) console.log(ts, 'Human:', ...msg);
|
||||
}
|
||||
|
||||
onmessage = async (msg) => {
|
||||
if (busy) return;
|
||||
|
|
|
@ -34,9 +34,9 @@
|
|||
"@tensorflow/tfjs-node-gpu": "^2.7.0",
|
||||
"@vladmandic/pilogger": "^0.2.9",
|
||||
"chokidar": "^3.4.3",
|
||||
"dayjs": "^1.9.6",
|
||||
"esbuild": "^0.8.15",
|
||||
"eslint": "^7.14.0",
|
||||
"dayjs": "^1.9.7",
|
||||
"esbuild": "^0.8.21",
|
||||
"eslint": "^7.15.0",
|
||||
"eslint-config-airbnb-base": "^14.2.1",
|
||||
"eslint-plugin-import": "^2.22.1",
|
||||
"eslint-plugin-json": "^2.1.2",
|
||||
|
@ -44,7 +44,7 @@
|
|||
"eslint-plugin-promise": "^4.2.1",
|
||||
"rimraf": "^3.0.2",
|
||||
"seedrandom": "^3.0.5",
|
||||
"simple-git": "^2.23.0"
|
||||
"simple-git": "^2.25.0"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "node --trace-warnings --unhandled-rejections=strict --trace-uncaught --no-deprecation src/node.js",
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { log } from '../log.js';
|
||||
import * as tf from '../../dist/tfjs.esm.js';
|
||||
import * as profile from '../profile.js';
|
||||
|
||||
|
@ -9,7 +10,7 @@ async function load(config) {
|
|||
if (!models.age) {
|
||||
models.age = await tf.loadGraphModel(config.face.age.modelPath);
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Human: load model: ${config.face.age.modelPath.match(/\/(.*)\./)[1]}`);
|
||||
log(`Human: load model: ${config.face.age.modelPath.match(/\/(.*)\./)[1]}`);
|
||||
}
|
||||
return models.age;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { log } from '../log.js';
|
||||
import * as tf from '../../dist/tfjs.esm.js';
|
||||
import * as profile from '../profile.js';
|
||||
|
||||
|
@ -13,8 +14,7 @@ const scale = 1; // score multiplication factor
|
|||
async function load(config) {
|
||||
if (!models.emotion) {
|
||||
models.emotion = await tf.loadGraphModel(config.face.emotion.modelPath);
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Human: load model: ${config.face.emotion.modelPath.match(/\/(.*)\./)[1]}`);
|
||||
log(`Human: load model: ${config.face.emotion.modelPath.match(/\/(.*)\./)[1]}`);
|
||||
}
|
||||
return models.emotion;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { log } from '../log.js';
|
||||
import * as tf from '../../dist/tfjs.esm.js';
|
||||
import * as profile from '../profile.js';
|
||||
|
||||
|
@ -13,8 +14,7 @@ async function load(config) {
|
|||
if (!models.gender) {
|
||||
models.gender = await tf.loadGraphModel(config.face.gender.modelPath);
|
||||
alternative = models.gender.inputs[0].shape[3] === 1;
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Human: load model: ${config.face.gender.modelPath.match(/\/(.*)\./)[1]}`);
|
||||
log(`Human: load model: ${config.face.gender.modelPath.match(/\/(.*)\./)[1]}`);
|
||||
}
|
||||
return models.gender;
|
||||
}
|
||||
|
|
|
@ -103,7 +103,7 @@ class HandPipeline {
|
|||
if (this.storedBoxes.length > 0) useFreshBox = true;
|
||||
}
|
||||
const hands = [];
|
||||
// console.log(`skipped: ${this.skipped} max: ${config.hand.maxHands} detected: ${this.detectedHands} stored: ${this.storedBoxes.length} new: ${boxes?.length}`);
|
||||
// log(`skipped: ${this.skipped} max: ${config.hand.maxHands} detected: ${this.detectedHands} stored: ${this.storedBoxes.length} new: ${boxes?.length}`);
|
||||
|
||||
// go through working set of boxes
|
||||
for (let i = 0; i < this.storedBoxes.length; i++) {
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
*/
|
||||
// https://storage.googleapis.com/tfjs-models/demos/handpose/index.html
|
||||
|
||||
import { log } from '../log.js';
|
||||
import * as tf from '../../dist/tfjs.esm.js';
|
||||
import * as handdetector from './handdetector';
|
||||
import * as pipeline from './handpipeline';
|
||||
|
@ -75,10 +76,8 @@ async function load(config) {
|
|||
const detector = new handdetector.HandDetector(handDetectorModel, config.hand.inputSize, anchors.anchors);
|
||||
const pipe = new pipeline.HandPipeline(detector, handPoseModel, config.hand.inputSize);
|
||||
const handpose = new HandPose(pipe);
|
||||
// eslint-disable-next-line no-console
|
||||
if (config.hand.enabled) console.log(`Human: load model: ${config.hand.detector.modelPath.match(/\/(.*)\./)[1]}`);
|
||||
// eslint-disable-next-line no-console
|
||||
if (config.hand.landmarks) console.log(`Human: load model: ${config.hand.skeleton.modelPath.match(/\/(.*)\./)[1]}`);
|
||||
if (config.hand.enabled) log(`Human: load model: ${config.hand.detector.modelPath.match(/\/(.*)\./)[1]}`);
|
||||
if (config.hand.landmarks) log(`Human: load model: ${config.hand.skeleton.modelPath.match(/\/(.*)\./)[1]}`);
|
||||
return handpose;
|
||||
}
|
||||
exports.load = load;
|
||||
|
|
35
src/human.js
35
src/human.js
|
@ -1,3 +1,4 @@
|
|||
import { log } from './log.js';
|
||||
import * as tf from '../dist/tfjs.esm.js';
|
||||
import * as facemesh from './face/facemesh.js';
|
||||
import * as age from './age/age.js';
|
||||
|
@ -68,12 +69,6 @@ class Human {
|
|||
this.hand = handpose;
|
||||
}
|
||||
|
||||
// helper function: wrapper around console output
|
||||
log(...msg) {
|
||||
// eslint-disable-next-line no-console
|
||||
if (msg && this.config.console) console.log('Human:', ...msg);
|
||||
}
|
||||
|
||||
profile() {
|
||||
if (this.config.profile) return profile.data;
|
||||
return {};
|
||||
|
@ -86,7 +81,7 @@ class Human {
|
|||
const previous = this.numTensors;
|
||||
this.numTensors = current;
|
||||
const leaked = current - previous;
|
||||
if (leaked !== 0) this.log(...msg, leaked);
|
||||
if (leaked !== 0) log(...msg, leaked);
|
||||
}
|
||||
|
||||
// quick sanity check on inputs
|
||||
|
@ -116,11 +111,11 @@ class Human {
|
|||
if (userConfig) this.config = mergeDeep(this.config, userConfig);
|
||||
|
||||
if (this.firstRun) {
|
||||
this.log(`version: ${this.version} TensorFlow/JS version: ${tf.version_core}`);
|
||||
log(`version: ${this.version} TensorFlow/JS version: ${tf.version_core}`);
|
||||
await this.checkBackend(true);
|
||||
if (tf.ENV.flags.IS_BROWSER) {
|
||||
this.log('configuration:', this.config);
|
||||
this.log('tf flags:', tf.ENV.flags);
|
||||
log('configuration:', this.config);
|
||||
log('tf flags:', tf.ENV.flags);
|
||||
}
|
||||
this.firstRun = false;
|
||||
}
|
||||
|
@ -166,17 +161,17 @@ class Human {
|
|||
tf.removeBackend(this.config.backend);
|
||||
tf.registerBackend(this.config.backend, backendFactory);
|
||||
} else {
|
||||
this.log('Backend not registred:', this.config.backend);
|
||||
log('Backend not registred:', this.config.backend);
|
||||
}
|
||||
*/
|
||||
|
||||
this.log('setting backend:', this.config.backend);
|
||||
log('setting backend:', this.config.backend);
|
||||
|
||||
if (this.config.backend === 'wasm') {
|
||||
this.log('settings wasm path:', this.config.wasmPath);
|
||||
log('settings wasm path:', this.config.wasmPath);
|
||||
tf.setWasmPaths(this.config.wasmPath);
|
||||
const simd = await tf.env().getAsync('WASM_HAS_SIMD_SUPPORT');
|
||||
if (!simd) this.log('warning: wasm simd support is not enabled');
|
||||
if (!simd) log('warning: wasm simd support is not enabled');
|
||||
}
|
||||
|
||||
await tf.setBackend(this.config.backend);
|
||||
|
@ -186,13 +181,13 @@ class Human {
|
|||
*/
|
||||
if (tf.getBackend() === 'webgl') {
|
||||
if (this.config.deallocate) {
|
||||
this.log('changing webgl: WEBGL_DELETE_TEXTURE_THRESHOLD:', this.config.deallocate);
|
||||
log('changing webgl: WEBGL_DELETE_TEXTURE_THRESHOLD:', this.config.deallocate);
|
||||
tf.ENV.set('WEBGL_DELETE_TEXTURE_THRESHOLD', this.config.deallocate ? 0 : -1);
|
||||
}
|
||||
tf.ENV.set('WEBGL_FORCE_F16_TEXTURES', true);
|
||||
tf.ENV.set('WEBGL_PACK_DEPTHWISECONV', true);
|
||||
const gl = await tf.backend().getGPGPUContext().gl;
|
||||
this.log(`gl version:${gl.getParameter(gl.VERSION)} renderer:${gl.getParameter(gl.RENDERER)}`);
|
||||
log(`gl version:${gl.getParameter(gl.VERSION)} renderer:${gl.getParameter(gl.RENDERER)}`);
|
||||
}
|
||||
await tf.ready();
|
||||
this.perf.backend = Math.trunc(now() - timeStamp);
|
||||
|
@ -217,7 +212,7 @@ class Human {
|
|||
|
||||
// is something went wrong, skip the face
|
||||
if (!face.image || face.image.isDisposedInternal) {
|
||||
this.log('Face object is disposed:', face.image);
|
||||
log('Face object is disposed:', face.image);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -330,7 +325,7 @@ class Human {
|
|||
this.state = 'check';
|
||||
const error = this.sanity(input);
|
||||
if (error) {
|
||||
this.log(error, input);
|
||||
log(error, input);
|
||||
resolve({ error });
|
||||
}
|
||||
|
||||
|
@ -352,7 +347,7 @@ class Human {
|
|||
timeStamp = now();
|
||||
const process = image.process(input, this.config);
|
||||
if (!process || !process.tensor) {
|
||||
this.log('could not convert input to tensor');
|
||||
log('could not convert input to tensor');
|
||||
resolve({ error: 'could not convert input to tensor' });
|
||||
return;
|
||||
}
|
||||
|
@ -423,7 +418,7 @@ class Human {
|
|||
if (!sample) sample = new ImageData(255, 255);
|
||||
// const sample = tf.zeros([1, 255, 255, 3]);
|
||||
const warmup = await this.detect(sample, userConfig);
|
||||
this.log('warmed up');
|
||||
log('warmed up');
|
||||
return warmup;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { log } from './log.js';
|
||||
import * as tf from '../dist/tfjs.esm.js';
|
||||
import * as fxImage from './imagefx.js';
|
||||
|
||||
|
@ -22,8 +23,7 @@ function process(input, config) {
|
|||
if (config.filter.height > 0) targetHeight = config.filter.height;
|
||||
else if (config.filter.width > 0) targetHeight = originalHeight * (config.filter.width / originalWidth);
|
||||
if (!targetWidth || !targetHeight) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Human: invalid input', input);
|
||||
log('Human: invalid input', input);
|
||||
return null;
|
||||
}
|
||||
if (!inCanvas || (inCanvas.width !== targetWidth) || (inCanvas.height !== targetHeight)) {
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import { log } from './log.js';
|
||||
|
||||
const profileData = {};
|
||||
|
||||
function profile(name, data) {
|
||||
|
@ -18,8 +20,7 @@ function profile(name, data) {
|
|||
if (largest.length > maxResults) largest.length = maxResults;
|
||||
const res = { newBytes: data.newBytes, newTensors: data.newTensors, peakBytes: data.peakBytes, numKernelOps: data.kernels.length, timeKernelOps: time, slowestKernelOps: slowest, largestKernelOps: largest };
|
||||
profileData[name] = res;
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Human profiler', name, res);
|
||||
log('Human profiler', name, res);
|
||||
}
|
||||
|
||||
exports.run = profile;
|
||||
|
|
Loading…
Reference in New Issue