diff --git a/config.js b/config.js index 2600ef03..a06daa1b 100644 --- a/config.js +++ b/config.js @@ -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 diff --git a/demo/worker.js b/demo/worker.js index 8b62675d..b4eed0d1 100644 --- a/demo/worker.js +++ b/demo/worker.js @@ -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; diff --git a/package.json b/package.json index 582e03c3..9e869111 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/src/age/age.js b/src/age/age.js index 5cfa707a..49fb29c7 100644 --- a/src/age/age.js +++ b/src/age/age.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; } diff --git a/src/emotion/emotion.js b/src/emotion/emotion.js index c167c5c1..31591b54 100644 --- a/src/emotion/emotion.js +++ b/src/emotion/emotion.js @@ -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; } diff --git a/src/gender/gender.js b/src/gender/gender.js index d2902e8f..dfb7a109 100644 --- a/src/gender/gender.js +++ b/src/gender/gender.js @@ -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; } diff --git a/src/hand/handpipeline.js b/src/hand/handpipeline.js index bd339bbc..49bb7b0e 100644 --- a/src/hand/handpipeline.js +++ b/src/hand/handpipeline.js @@ -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++) { diff --git a/src/hand/handpose.js b/src/hand/handpose.js index 92ea96ab..91ca889b 100644 --- a/src/hand/handpose.js +++ b/src/hand/handpose.js @@ -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; diff --git a/src/human.js b/src/human.js index 3f0a26de..5557a8d8 100644 --- a/src/human.js +++ b/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; } } diff --git a/src/image.js b/src/image.js index df265d15..6add8a63 100644 --- a/src/image.js +++ b/src/image.js @@ -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)) { diff --git a/src/profile.js b/src/profile.js index f5cddce7..e9696a72 100644 --- a/src/profile.js +++ b/src/profile.js @@ -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;