From fbd1eb94c291e4d7f5f6034b39e6d8e5976ba25d Mon Sep 17 00:00:00 2001 From: Vladimir Mandic Date: Sat, 30 Jan 2021 13:23:07 -0500 Subject: [PATCH] added warmup for nodejs --- demo/node.js | 31 ++++++++++++++++++++++++++----- src/human.js | 19 ++++++++++++++++--- 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/demo/node.js b/demo/node.js index 7bd76002..12b3d5ff 100644 --- a/demo/node.js +++ b/demo/node.js @@ -6,6 +6,8 @@ const tf = require('@tensorflow/tfjs-node'); // or const tf = require('@tensorfl // load specific version of Human library that matches TensorFlow mode const Human = require('../dist/human.node.js').default; // or const Human = require('../dist/human.node-gpu.js').default; +let human = null; + const myConfig = { backend: 'tensorflow', console: true, @@ -25,13 +27,16 @@ const myConfig = { }, }; -async function detect(input) { +async function init() { // wait until tf is ready await tf.ready(); // create instance of human - const human = new Human(myConfig); + human = new Human(myConfig); // pre-load models await human.load(); +} + +async function detect(input) { // read input image file and create tensor to be used for processing const buffer = fs.readFileSync(input); const decoded = human.tf.node.decodeImage(buffer); @@ -40,6 +45,7 @@ async function detect(input) { decoded.dispose(); casted.dispose(); // image shape contains image dimensions and depth + log.warn('Face model is disabled in NodeJS due to missing required TFJS functions'); log.state('Processing:', image.shape); // must disable face model when runing in tfjs-node as it's missing required ops // see @@ -52,11 +58,26 @@ async function detect(input) { log.data(result); } +async function test() { + log.state('Processing embedded warmup image'); + log.warn('Face model is disabled in NodeJS due to missing required TFJS functions'); + myConfig.face.enabled = false; + myConfig.warmup = 'full'; + const result = await human.warmup(myConfig); + log.data(result); +} + async function main() { log.info('NodeJS:', process.version); - if (process.argv.length !== 3) log.error('Parameters: '); - else if (!fs.existsSync(process.argv[2])) log.error(`File not found: ${process.argv[2]}`); - else detect(process.argv[2]); + await init(); + if (process.argv.length !== 3) { + log.warn('Parameters: missing'); + await test(); + } else if (!fs.existsSync(process.argv[2])) { + log.error(`File not found: ${process.argv[2]}`); + } else { + await detect(process.argv[2]); + } } main(); diff --git a/src/human.js b/src/human.js index eaed2ecf..90db40d0 100644 --- a/src/human.js +++ b/src/human.js @@ -444,7 +444,7 @@ class Human { } if (blob) { const bitmap = await createImageBitmap(blob); - res = await this.detect(bitmap, config); + res = await this.detect(bitmap, this.config); bitmap.close(); } return res; @@ -474,13 +474,25 @@ class Human { const ctx = canvas.getContext('2d'); ctx.drawImage(img, 0, 0); const data = ctx.getImageData(0, 0, size, size); - this.detect(data, config).then((res) => resolve(res)); + this.detect(data, this.config).then((res) => resolve(res)); }; if (src) img.src = src; else resolve(null); }); } + async warmupNode() { + const atob = (str) => Buffer.from(str, 'base64'); + const img = this.config.warmup === 'face' ? atob(sample.face) : atob(sample.body); + const data = tf.node.decodeJpeg(img); + const expanded = data.expandDims(0); + tf.dispose(data); + // log('Input:', expanded); + const res = await this.detect(expanded, this.config); + tf.dispose(expanded); + return res; + } + async warmup(userConfig) { const t0 = now(); if (userConfig) this.config = mergeDeep(this.config, userConfig); @@ -488,7 +500,8 @@ class Human { this.config.videoOptimized = false; let res; if (typeof createImageBitmap === 'function') res = await this.warmupBitmap(); - else res = await this.warmupCanvas(); + else if (typeof Image !== 'undefined') res = await this.warmupCanvas(); + else res = await this.warmupNode(); this.config.videoOptimized = video; const t1 = now(); log('Warmup', this.config.warmup, Math.round(t1 - t0), 'ms', res);