2020-11-21 18:21:47 +01:00
const log = require ( '@vladmandic/pilogger' ) ;
2020-10-14 02:52:30 +02:00
const fs = require ( 'fs' ) ;
const process = require ( 'process' ) ;
2020-11-21 18:21:47 +01:00
// for Node, `tfjs-node` or `tfjs-node-gpu` should be loaded before using Human
const tf = require ( '@tensorflow/tfjs-node' ) ; // or const tf = require('@tensorflow/tfjs-node-gpu');
// 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;
2020-10-14 02:52:30 +02:00
2021-01-30 19:23:07 +01:00
let human = null ;
2020-11-21 18:21:47 +01:00
const myConfig = {
2020-10-16 16:12:12 +02:00
backend : 'tensorflow' ,
console : true ,
2020-10-19 17:03:48 +02:00
videoOptimized : false ,
2021-02-06 23:41:53 +01:00
async : false ,
2020-10-14 02:52:30 +02:00
face : {
2021-03-04 16:33:08 +01:00
enabled : true ,
detector : { modelPath : 'file://models/faceboxes.json' , enabled : true , minConfidence : 0.5 } ,
// detector: { modelPath: 'file://models/blazeface-back.json', enabled: false }, // cannot use blazeface in nodejs due to missing required kernel function in tfjs-node
mesh : { modelPath : 'file://models/facemesh.json' , enabled : false } , // depends on blazeface detector
iris : { modelPath : 'file://models/iris.json' , enabled : true } ,
age : { modelPath : 'file://models/age-ssrnet-imdb.json' , enabled : true } ,
gender : { modelPath : 'file://models/gender.json' , enabled : true } ,
emotion : { modelPath : 'file://models/emotion.json' , enabled : true } ,
2020-10-14 02:52:30 +02:00
} ,
2021-03-04 16:33:08 +01:00
// body: { modelPath: 'file://models/blazepose.json', modelType: 'blazepose', inputSize: 256, enabled: true },
body : { modelPath : 'file://models/posenet.json' , modelType : 'posenet' , inputSize : 257 , enabled : true } ,
2020-10-14 02:52:30 +02:00
hand : {
2021-03-04 16:33:08 +01:00
enabled : true ,
2020-11-03 15:34:36 +01:00
detector : { modelPath : 'file://models/handdetect.json' } ,
skeleton : { modelPath : 'file://models/handskeleton.json' } ,
2020-10-14 02:52:30 +02:00
} ,
} ;
2021-01-30 19:23:07 +01:00
async function init ( ) {
2020-11-21 18:21:47 +01:00
// wait until tf is ready
2020-10-14 02:52:30 +02:00
await tf . ready ( ) ;
2020-11-21 18:21:47 +01:00
// create instance of human
2021-01-30 19:23:07 +01:00
human = new Human ( myConfig ) ;
2020-11-21 18:21:47 +01:00
// pre-load models
2021-03-04 16:33:08 +01:00
log . info ( 'Human:' , human . version ) ;
log . info ( 'Active Configuration' , human . config ) ;
log . info ( 'TFJS Version:' , human . tf . version _core , 'Backend:' , tf . getBackend ( ) ) ;
log . info ( 'TFJS Flags:' , human . tf . env ( ) . features ) ;
2020-11-21 18:21:47 +01:00
await human . load ( ) ;
2021-03-04 16:33:08 +01:00
const loaded = Object . keys ( human . models ) . filter ( ( a ) => human . models [ a ] ) ;
log . info ( 'Loaded:' , loaded ) ;
log . info ( 'Memory state:' , human . tf . engine ( ) . memory ( ) ) ;
2021-01-30 19:23:07 +01:00
}
async function detect ( input ) {
2020-11-21 18:21:47 +01:00
// read input image file and create tensor to be used for processing
2020-10-14 02:52:30 +02:00
const buffer = fs . readFileSync ( input ) ;
2020-11-21 18:21:47 +01:00
const decoded = human . tf . node . decodeImage ( buffer ) ;
2020-10-19 17:03:48 +02:00
const casted = decoded . toFloat ( ) ;
const image = casted . expandDims ( 0 ) ;
decoded . dispose ( ) ;
casted . dispose ( ) ;
2020-11-21 18:21:47 +01:00
// image shape contains image dimensions and depth
log . state ( 'Processing:' , image . shape ) ;
// run actual detection
const result = await human . detect ( image , myConfig ) ;
// dispose image tensor as we no longer need it
2020-10-14 17:43:33 +02:00
image . dispose ( ) ;
2020-11-21 18:21:47 +01:00
// print data to console
log . data ( result ) ;
2020-10-14 02:52:30 +02:00
}
2021-01-30 19:23:07 +01:00
async function test ( ) {
2021-02-08 17:39:09 +01:00
// test with embedded face image
2021-02-06 23:41:53 +01:00
log . state ( 'Processing embedded warmup image: face' ) ;
myConfig . warmup = 'face' ;
const resultFace = await human . warmup ( myConfig ) ;
2021-02-08 17:39:09 +01:00
log . data ( 'Face: ' , resultFace . face ) ;
// test with embedded full body image
2021-02-06 23:41:53 +01:00
log . state ( 'Processing embedded warmup image: full' ) ;
2021-01-30 19:23:07 +01:00
myConfig . warmup = 'full' ;
2021-02-06 23:41:53 +01:00
const resultFull = await human . warmup ( myConfig ) ;
2021-02-08 17:39:09 +01:00
log . data ( 'Body:' , resultFull . body ) ;
log . data ( 'Hand:' , resultFull . hand ) ;
log . data ( 'Gesture:' , resultFull . gesture ) ;
2021-01-30 19:23:07 +01:00
}
2020-10-14 02:52:30 +02:00
async function main ( ) {
2020-12-23 19:55:22 +01:00
log . info ( 'NodeJS:' , process . version ) ;
2021-03-04 16:33:08 +01:00
log . info ( 'Current folder:' , process . env . PWD ) ;
2021-01-30 19:23:07 +01:00
await init ( ) ;
if ( process . argv . length !== 3 ) {
log . warn ( 'Parameters: <input image> missing' ) ;
await test ( ) ;
} else if ( ! fs . existsSync ( process . argv [ 2 ] ) ) {
log . error ( ` File not found: ${ process . argv [ 2 ] } ` ) ;
} else {
await detect ( process . argv [ 2 ] ) ;
}
2020-10-14 02:52:30 +02:00
}
main ( ) ;