human/demo/multithread/node-multiprocess-worker.js

89 lines
2.9 KiB
JavaScript
Raw Normal View History

2021-05-25 14:58:20 +02:00
/**
* Human demo for NodeJS
*
* Used by node-multiprocess.js as an on-demand started worker process
* Receives messages from parent process and sends results
*/
2021-04-16 14:34:16 +02:00
const fs = require('fs');
const log = require('@vladmandic/pilogger');
// workers actual import tfjs and faceapi modules
2021-05-11 16:11:55 +02:00
// eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
2021-04-16 14:34:16 +02:00
const tf = require('@tensorflow/tfjs-node');
2021-06-14 14:16:10 +02:00
const Human = require('../../dist/human.node.js').default; // or const Human = require('../dist/human.node-gpu.js').default;
2021-04-16 14:34:16 +02:00
let human = null;
const myConfig = {
2021-11-18 16:10:06 +01:00
// backend: 'tensorflow',
2021-04-16 14:34:16 +02:00
modelBasePath: 'file://models/',
debug: false,
2021-04-16 15:31:58 +02:00
async: true,
2021-04-16 14:34:16 +02:00
face: {
enabled: true,
detector: { enabled: true, rotation: false },
mesh: { enabled: true },
2021-05-25 14:58:20 +02:00
iris: { enabled: true },
2021-04-16 14:34:16 +02:00
description: { enabled: true },
emotion: { enabled: true },
},
hand: {
2021-05-25 14:58:20 +02:00
enabled: true,
2021-04-16 14:34:16 +02:00
},
// body: { modelPath: 'blazepose.json', enabled: true },
2021-05-25 14:58:20 +02:00
body: { enabled: true },
object: { enabled: true },
2021-04-16 14:34:16 +02:00
};
// read image from a file and create tensor to be used by faceapi
// this way we don't need any monkey patches
// you can add any pre-proocessing here such as resizing, etc.
async function image(img) {
const buffer = fs.readFileSync(img);
2021-05-11 16:11:55 +02:00
const tensor = human.tf.tidy(() => human.tf.node.decodeImage(buffer).toFloat().expandDims());
2021-04-16 14:34:16 +02:00
return tensor;
}
// actual faceapi detection
async function detect(img) {
const tensor = await image(img);
const result = await human.detect(tensor);
2021-05-25 14:58:20 +02:00
if (process.send) { // check if ipc exists
process.send({ image: img, detected: result }); // send results back to main
process.send({ ready: true }); // send signal back to main that this worker is now idle and ready for next image
}
2021-07-29 22:06:03 +02:00
tf.dispose(tensor);
2021-04-16 14:34:16 +02:00
}
async function main() {
process.on('unhandledRejection', (err) => {
// @ts-ignore // no idea if exception message is compelte
log.error(err?.message || err || 'no error message');
});
2021-04-16 14:34:16 +02:00
// on worker start first initialize message handler so we don't miss any messages
process.on('message', (msg) => {
2021-09-05 23:05:46 +02:00
// @ts-ignore
2021-05-25 14:58:20 +02:00
if (msg.exit && process.exit) process.exit(); // if main told worker to exit
2021-09-05 23:05:46 +02:00
// @ts-ignore
2021-05-25 14:58:20 +02:00
if (msg.test && process.send) process.send({ test: true });
2021-09-05 23:05:46 +02:00
// @ts-ignore
2021-04-16 14:34:16 +02:00
if (msg.image) detect(msg.image); // if main told worker to process image
log.data('Worker received message:', process.pid, msg); // generic log
});
// create instance of human
human = new Human(myConfig);
2021-05-11 16:11:55 +02:00
// wait until tf is ready
await human.tf.ready();
2021-04-16 14:34:16 +02:00
// pre-load models
2021-11-18 16:10:06 +01:00
log.state('Worker: PID:', process.pid, `TensorFlow/JS ${human.tf.version['tfjs-core']} Human ${human.version} Backend: ${human.tf.getBackend()}`);
2021-04-16 14:34:16 +02:00
await human.load();
// now we're ready, so send message back to main that it knows it can use this worker
2021-05-25 14:58:20 +02:00
if (process.send) process.send({ ready: true });
2021-04-16 14:34:16 +02:00
}
main();