justadudewhohacks / face-api.js

JavaScript API for face detection and face recognition in the browser and nodejs with tensorflow.js
MIT License
16.61k stars 3.7k forks source link

sending faceMatcher as the response from node API #675

Open Aditya-Ace opened 4 years ago

Aditya-Ace commented 4 years ago

Very Urgent: Please help!

Node:

require("@tensorflow/tfjs-node"); const faceapi = require("face-api.js"); const canvas = require("canvas"); const path = require("path"); const { promisify } = require("util"); const readdir = promisify(require("fs").readdir); const stat = promisify(require("fs").stat); const router = require("express").Router();

const loadLabelledFaceImages = async () => { await faceapi.nets.tinyFaceDetector.loadFromDisk( ${__dirname}/../face-models/ ); await faceapi.nets.faceLandmark68Net.loadFromDisk( ${__dirname}/../face-models/ ); await faceapi.nets.faceRecognitionNet.loadFromDisk( ${__dirname}/../face-models/ ); await faceapi.nets.ssdMobilenetv1.loadFromDisk( ${__dirname}/../face-models/ ); await faceapi.nets.faceExpressionNet.loadFromDisk( ${__dirname}/../face-models/ ); await faceapi.nets.ageGenderNet.loadFromDisk(${__dirname}/../face-models/);

//joining path of directory let directoryPath = path.join(__dirname, "../labelled-images"); //passsing directoryPath const files = await readdir(directoryPath); return Promise.all( files.map(async (file) => { const descriptions = []; for (let i = 0; i <= 39; i++) { const imageLink = ${directoryPath}/${file}/${i}.jpg; const image = await canvas.loadImage(imageLink); const detections = await faceapi .detectSingleFace(image) .withFaceLandmarks() .withFaceDescriptor(); descriptions.push(detections.descriptor); } return new faceapi.LabeledFaceDescriptors(file, descriptions); }) ); };

router.get("/getimagesdata", async (req, res) => { const labeledFaceDescriptors = await loadLabelledFaceImages(); const faceMatcher = new faceapi.FaceMatcher(labeledFaceDescriptors, 0.6); res.status(200).send({ faceMatcher }); });

module.exports = router;

Frontend Angular:

faceRecognition = async () => { this.userManagementPermissionService.getImagesData().subscribe((res) => { const faceMatcher = res.faceMatcher; const faceCanvas = faceapi.createCanvasFromMedia( this.video.nativeElement ); this.webcam.nativeElement.append(faceCanvas); faceCanvas.classList.add('face-canvas'); const displaySize = { width: this.video.nativeElement.width, height: this.video.nativeElement.height, }; faceapi.matchDimensions(faceCanvas, displaySize); let x: any = []; let y: any = []; let width: any = []; let height: any = []; let resizedDetections: any = [];

  setInterval(async () => {
    const detection = await faceapi
      .detectAllFaces(
        this.video.nativeElement,
        new faceapi.TinyFaceDetectorOptions()
      )
      .withFaceLandmarks()
      .withFaceDescriptors();

    resizedDetections = faceapi.resizeResults(detection, displaySize);
    faceCanvas
      .getContext('2d')
      .clearRect(0, 0, faceCanvas.width, faceCanvas.height);
    const results = resizedDetections.map((d: any) => {
      return faceMatcher.findBestMatch(d.descriptor);
    });
    results.forEach((result: any, i: any) => {
      const box = resizedDetections[i].detection.box;
      const drawBox = new faceapi.draw.DrawBox(box, {
        label: result.toString(),
      });
      drawBox.draw(faceCanvas);
    });
  }, 100);

I am getting error : TypeError: faceMatcher.findBestMatch is not a function TypeError: faceMatcher.findBestMatch is not a function

Please do help!! Thanks in advance error

Aditya-Ace commented 4 years ago

Please guys, If anyone can provide the solution

cindyloo commented 4 years ago

my best guess is that you don't have faceapi 'loaded' or in state somewhere in the sense it is instantiated and can access it's methods. I'm in the react world and had to re-purpose react-use-faceapi to access the methods without error

Aditya-Ace commented 4 years ago

actually this is a MEAN stack project and just to load the require("@tensorflow/tfjs-node"); i had to install node v10.16.3 as it was not compatible and throwing error. I used "@tensorflow/tfjs-node": "^1.2.11", to make it compatible, I have no idea what is the issue, working great with just used on angular but photos been saved to server that's why wanna run it on server.

karthik-Gopalan commented 4 years ago

if I am not wrong, you can't load the Facematcher on the server and then pass it onto the client. I don't think that will work. What you can do, is create the descriptors and save that as a json. And send the json file to the client and then load it on the client side. You would still need to initiate the faceMatcher on the client side except you don't have to create the descriptors all over again. Just load them.