node-multiprocess-worker.js 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. /**
  2. * FaceAPI Demo for NodeJS
  3. * - Used by `node-multiprocess.js`
  4. */
  5. const fs = require('fs');
  6. const path = require('path');
  7. const log = require('@vladmandic/pilogger');
  8. // workers actual import tfjs and faceapi modules
  9. const tf = require('@tensorflow/tfjs-node'); // in nodejs environments tfjs-node is required to be loaded before face-api
  10. const faceapi = require('../dist/face-api.node.js'); // use this when using face-api in dev mode
  11. // const faceapi = require('@vladmandic/face-api'); // use this when face-api is installed as module (majority of use cases)
  12. // options used by faceapi
  13. const modelPathRoot = '../model';
  14. const minConfidence = 0.15;
  15. const maxResults = 5;
  16. let optionsSSDMobileNet;
  17. // read image from a file and create tensor to be used by faceapi
  18. // this way we don't need any monkey patches
  19. // you can add any pre-proocessing here such as resizing, etc.
  20. async function image(img) {
  21. const buffer = fs.readFileSync(img);
  22. const tensor = tf.tidy(() => tf.node.decodeImage(buffer).toFloat().expandDims());
  23. return tensor;
  24. }
  25. // actual faceapi detection
  26. async function detect(img) {
  27. const tensor = await image(img);
  28. const result = await faceapi
  29. .detectAllFaces(tensor, optionsSSDMobileNet)
  30. .withFaceLandmarks();
  31. // .withFaceExpressions()
  32. // .withFaceDescriptors()
  33. // .withAgeAndGender();
  34. process.send({ image: img, detected: result }); // send results back to main
  35. process.send({ ready: true }); // send signal back to main that this worker is now idle and ready for next image
  36. tensor.dispose();
  37. }
  38. async function main() {
  39. // on worker start first initialize message handler so we don't miss any messages
  40. process.on('message', (msg) => {
  41. if (msg.exit) process.exit(); // if main told worker to exit
  42. if (msg.test) process.send({ test: true });
  43. if (msg.image) detect(msg.image); // if main told worker to process image
  44. log.data('Worker received message:', process.pid, msg); // generic log
  45. });
  46. // then initialize tfjs
  47. await faceapi.tf.setBackend('tensorflow');
  48. await faceapi.tf.enableProdMode();
  49. await faceapi.tf.ENV.set('DEBUG', false);
  50. await faceapi.tf.ready();
  51. log.state('Worker: PID:', process.pid, `TensorFlow/JS ${faceapi.tf.version_core} FaceAPI ${faceapi.version} Backend: ${faceapi.tf.getBackend()}`);
  52. // and load and initialize facepi models
  53. const modelPath = path.join(__dirname, modelPathRoot);
  54. await faceapi.nets.ssdMobilenetv1.loadFromDisk(modelPath);
  55. await faceapi.nets.ageGenderNet.loadFromDisk(modelPath);
  56. await faceapi.nets.faceLandmark68Net.loadFromDisk(modelPath);
  57. await faceapi.nets.faceRecognitionNet.loadFromDisk(modelPath);
  58. await faceapi.nets.faceExpressionNet.loadFromDisk(modelPath);
  59. optionsSSDMobileNet = new faceapi.SsdMobilenetv1Options({ minConfidence, maxResults });
  60. // now we're ready, so send message back to main that it knows it can use this worker
  61. process.send({ ready: true });
  62. }
  63. main();