switch to central logger

pull/280/head
Vladimir Mandic 2020-12-08 09:00:44 -05:00
parent 3c54914a5c
commit f65effc69d
11 changed files with 39 additions and 43 deletions

View File

@ -5,7 +5,6 @@ export default {
backend: 'webgl', // select tfjs backend to use backend: 'webgl', // select tfjs backend to use
wasmPath: '../assets/', // path for wasm binaries wasmPath: '../assets/', // path for wasm binaries
// only used for backend: wasm // only used for backend: wasm
console: true, // enable debugging output to console
async: true, // execute enabled models in parallel async: true, // execute enabled models in parallel
// this disables per-model performance data but // this disables per-model performance data but
// slightly increases performance // slightly increases performance

View File

@ -1,13 +1,14 @@
import Human from '../dist/human.esm.js'; import Human from '../dist/human.esm.js';
let config;
let busy = false; let busy = false;
const human = new Human(); 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 // eslint-disable-next-line no-console
if (config.console) console.log(...msg); if (msg) console.log(ts, 'Human:', ...msg);
}; }
onmessage = async (msg) => { onmessage = async (msg) => {
if (busy) return; if (busy) return;

View File

@ -34,9 +34,9 @@
"@tensorflow/tfjs-node-gpu": "^2.7.0", "@tensorflow/tfjs-node-gpu": "^2.7.0",
"@vladmandic/pilogger": "^0.2.9", "@vladmandic/pilogger": "^0.2.9",
"chokidar": "^3.4.3", "chokidar": "^3.4.3",
"dayjs": "^1.9.6", "dayjs": "^1.9.7",
"esbuild": "^0.8.15", "esbuild": "^0.8.21",
"eslint": "^7.14.0", "eslint": "^7.15.0",
"eslint-config-airbnb-base": "^14.2.1", "eslint-config-airbnb-base": "^14.2.1",
"eslint-plugin-import": "^2.22.1", "eslint-plugin-import": "^2.22.1",
"eslint-plugin-json": "^2.1.2", "eslint-plugin-json": "^2.1.2",
@ -44,7 +44,7 @@
"eslint-plugin-promise": "^4.2.1", "eslint-plugin-promise": "^4.2.1",
"rimraf": "^3.0.2", "rimraf": "^3.0.2",
"seedrandom": "^3.0.5", "seedrandom": "^3.0.5",
"simple-git": "^2.23.0" "simple-git": "^2.25.0"
}, },
"scripts": { "scripts": {
"start": "node --trace-warnings --unhandled-rejections=strict --trace-uncaught --no-deprecation src/node.js", "start": "node --trace-warnings --unhandled-rejections=strict --trace-uncaught --no-deprecation src/node.js",

View File

@ -1,3 +1,4 @@
import { log } from '../log.js';
import * as tf from '../../dist/tfjs.esm.js'; import * as tf from '../../dist/tfjs.esm.js';
import * as profile from '../profile.js'; import * as profile from '../profile.js';
@ -9,7 +10,7 @@ async function load(config) {
if (!models.age) { if (!models.age) {
models.age = await tf.loadGraphModel(config.face.age.modelPath); models.age = await tf.loadGraphModel(config.face.age.modelPath);
// eslint-disable-next-line no-console // 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; return models.age;
} }

View File

@ -1,3 +1,4 @@
import { log } from '../log.js';
import * as tf from '../../dist/tfjs.esm.js'; import * as tf from '../../dist/tfjs.esm.js';
import * as profile from '../profile.js'; import * as profile from '../profile.js';
@ -13,8 +14,7 @@ const scale = 1; // score multiplication factor
async function load(config) { async function load(config) {
if (!models.emotion) { if (!models.emotion) {
models.emotion = await tf.loadGraphModel(config.face.emotion.modelPath); models.emotion = await tf.loadGraphModel(config.face.emotion.modelPath);
// eslint-disable-next-line no-console log(`Human: load model: ${config.face.emotion.modelPath.match(/\/(.*)\./)[1]}`);
console.log(`Human: load model: ${config.face.emotion.modelPath.match(/\/(.*)\./)[1]}`);
} }
return models.emotion; return models.emotion;
} }

View File

@ -1,3 +1,4 @@
import { log } from '../log.js';
import * as tf from '../../dist/tfjs.esm.js'; import * as tf from '../../dist/tfjs.esm.js';
import * as profile from '../profile.js'; import * as profile from '../profile.js';
@ -13,8 +14,7 @@ async function load(config) {
if (!models.gender) { if (!models.gender) {
models.gender = await tf.loadGraphModel(config.face.gender.modelPath); models.gender = await tf.loadGraphModel(config.face.gender.modelPath);
alternative = models.gender.inputs[0].shape[3] === 1; alternative = models.gender.inputs[0].shape[3] === 1;
// eslint-disable-next-line no-console log(`Human: load model: ${config.face.gender.modelPath.match(/\/(.*)\./)[1]}`);
console.log(`Human: load model: ${config.face.gender.modelPath.match(/\/(.*)\./)[1]}`);
} }
return models.gender; return models.gender;
} }

View File

@ -103,7 +103,7 @@ class HandPipeline {
if (this.storedBoxes.length > 0) useFreshBox = true; if (this.storedBoxes.length > 0) useFreshBox = true;
} }
const hands = []; 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 // go through working set of boxes
for (let i = 0; i < this.storedBoxes.length; i++) { for (let i = 0; i < this.storedBoxes.length; i++) {

View File

@ -16,6 +16,7 @@
*/ */
// https://storage.googleapis.com/tfjs-models/demos/handpose/index.html // 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 tf from '../../dist/tfjs.esm.js';
import * as handdetector from './handdetector'; import * as handdetector from './handdetector';
import * as pipeline from './handpipeline'; 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 detector = new handdetector.HandDetector(handDetectorModel, config.hand.inputSize, anchors.anchors);
const pipe = new pipeline.HandPipeline(detector, handPoseModel, config.hand.inputSize); const pipe = new pipeline.HandPipeline(detector, handPoseModel, config.hand.inputSize);
const handpose = new HandPose(pipe); const handpose = new HandPose(pipe);
// eslint-disable-next-line no-console if (config.hand.enabled) log(`Human: load model: ${config.hand.detector.modelPath.match(/\/(.*)\./)[1]}`);
if (config.hand.enabled) console.log(`Human: load model: ${config.hand.detector.modelPath.match(/\/(.*)\./)[1]}`); if (config.hand.landmarks) log(`Human: load model: ${config.hand.skeleton.modelPath.match(/\/(.*)\./)[1]}`);
// eslint-disable-next-line no-console
if (config.hand.landmarks) console.log(`Human: load model: ${config.hand.skeleton.modelPath.match(/\/(.*)\./)[1]}`);
return handpose; return handpose;
} }
exports.load = load; exports.load = load;

View File

@ -1,3 +1,4 @@
import { log } from './log.js';
import * as tf from '../dist/tfjs.esm.js'; import * as tf from '../dist/tfjs.esm.js';
import * as facemesh from './face/facemesh.js'; import * as facemesh from './face/facemesh.js';
import * as age from './age/age.js'; import * as age from './age/age.js';
@ -68,12 +69,6 @@ class Human {
this.hand = handpose; 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() { profile() {
if (this.config.profile) return profile.data; if (this.config.profile) return profile.data;
return {}; return {};
@ -86,7 +81,7 @@ class Human {
const previous = this.numTensors; const previous = this.numTensors;
this.numTensors = current; this.numTensors = current;
const leaked = current - previous; const leaked = current - previous;
if (leaked !== 0) this.log(...msg, leaked); if (leaked !== 0) log(...msg, leaked);
} }
// quick sanity check on inputs // quick sanity check on inputs
@ -116,11 +111,11 @@ class Human {
if (userConfig) this.config = mergeDeep(this.config, userConfig); if (userConfig) this.config = mergeDeep(this.config, userConfig);
if (this.firstRun) { 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); await this.checkBackend(true);
if (tf.ENV.flags.IS_BROWSER) { if (tf.ENV.flags.IS_BROWSER) {
this.log('configuration:', this.config); log('configuration:', this.config);
this.log('tf flags:', tf.ENV.flags); log('tf flags:', tf.ENV.flags);
} }
this.firstRun = false; this.firstRun = false;
} }
@ -166,17 +161,17 @@ class Human {
tf.removeBackend(this.config.backend); tf.removeBackend(this.config.backend);
tf.registerBackend(this.config.backend, backendFactory); tf.registerBackend(this.config.backend, backendFactory);
} else { } 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') { 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); tf.setWasmPaths(this.config.wasmPath);
const simd = await tf.env().getAsync('WASM_HAS_SIMD_SUPPORT'); 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); await tf.setBackend(this.config.backend);
@ -186,13 +181,13 @@ class Human {
*/ */
if (tf.getBackend() === 'webgl') { if (tf.getBackend() === 'webgl') {
if (this.config.deallocate) { 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_DELETE_TEXTURE_THRESHOLD', this.config.deallocate ? 0 : -1);
} }
tf.ENV.set('WEBGL_FORCE_F16_TEXTURES', true); tf.ENV.set('WEBGL_FORCE_F16_TEXTURES', true);
tf.ENV.set('WEBGL_PACK_DEPTHWISECONV', true); tf.ENV.set('WEBGL_PACK_DEPTHWISECONV', true);
const gl = await tf.backend().getGPGPUContext().gl; 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(); await tf.ready();
this.perf.backend = Math.trunc(now() - timeStamp); this.perf.backend = Math.trunc(now() - timeStamp);
@ -217,7 +212,7 @@ class Human {
// is something went wrong, skip the face // is something went wrong, skip the face
if (!face.image || face.image.isDisposedInternal) { if (!face.image || face.image.isDisposedInternal) {
this.log('Face object is disposed:', face.image); log('Face object is disposed:', face.image);
continue; continue;
} }
@ -330,7 +325,7 @@ class Human {
this.state = 'check'; this.state = 'check';
const error = this.sanity(input); const error = this.sanity(input);
if (error) { if (error) {
this.log(error, input); log(error, input);
resolve({ error }); resolve({ error });
} }
@ -352,7 +347,7 @@ class Human {
timeStamp = now(); timeStamp = now();
const process = image.process(input, this.config); const process = image.process(input, this.config);
if (!process || !process.tensor) { 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' }); resolve({ error: 'could not convert input to tensor' });
return; return;
} }
@ -423,7 +418,7 @@ class Human {
if (!sample) sample = new ImageData(255, 255); if (!sample) sample = new ImageData(255, 255);
// const sample = tf.zeros([1, 255, 255, 3]); // const sample = tf.zeros([1, 255, 255, 3]);
const warmup = await this.detect(sample, userConfig); const warmup = await this.detect(sample, userConfig);
this.log('warmed up'); log('warmed up');
return warmup; return warmup;
} }
} }

View File

@ -1,3 +1,4 @@
import { log } from './log.js';
import * as tf from '../dist/tfjs.esm.js'; import * as tf from '../dist/tfjs.esm.js';
import * as fxImage from './imagefx.js'; import * as fxImage from './imagefx.js';
@ -22,8 +23,7 @@ function process(input, config) {
if (config.filter.height > 0) targetHeight = config.filter.height; if (config.filter.height > 0) targetHeight = config.filter.height;
else if (config.filter.width > 0) targetHeight = originalHeight * (config.filter.width / originalWidth); else if (config.filter.width > 0) targetHeight = originalHeight * (config.filter.width / originalWidth);
if (!targetWidth || !targetHeight) { if (!targetWidth || !targetHeight) {
// eslint-disable-next-line no-console log('Human: invalid input', input);
console.log('Human: invalid input', input);
return null; return null;
} }
if (!inCanvas || (inCanvas.width !== targetWidth) || (inCanvas.height !== targetHeight)) { if (!inCanvas || (inCanvas.width !== targetWidth) || (inCanvas.height !== targetHeight)) {

View File

@ -1,3 +1,5 @@
import { log } from './log.js';
const profileData = {}; const profileData = {};
function profile(name, data) { function profile(name, data) {
@ -18,8 +20,7 @@ function profile(name, data) {
if (largest.length > maxResults) largest.length = maxResults; 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 }; const res = { newBytes: data.newBytes, newTensors: data.newTensors, peakBytes: data.peakBytes, numKernelOps: data.kernels.length, timeKernelOps: time, slowestKernelOps: slowest, largestKernelOps: largest };
profileData[name] = res; profileData[name] = res;
// eslint-disable-next-line no-console log('Human profiler', name, res);
console.log('Human profiler', name, res);
} }
exports.run = profile; exports.run = profile;