Search code examples
javascriptnode.jstypescriptface-recognitionface-api

How can I increase the number of reference images in face-api.js using node.js?


The default face-api.js uses only one image as reference for face recognition, but through my tests I noticed a pretty high error gap. So I was wondering, how can I manage to increase the number of reference images, in order to reduce the error gap?

Assuming my images are in the imgs/ folder, how can I do this?

Here's my project folder :

Project Folder

Here's the faceRecognition.ts file :

import * as faceapi from 'face-api.js';

import { canvas, faceDetectionNet, faceDetectionOptions, saveFile } from './commons';
const REFERENCE_IMAGE = '../../imgs/test1.jpeg'
const QUERY_IMAGE = '../../test/test.jpeg'
// i want to have many images for the REFERENCE_IMAGE
// in folder imgs, i have 5 images in a want to use all five images for increase
// the result. Actually i have some bad prediction when i use only one image

async function run() {

  await faceDetectionNet.loadFromDisk('../../weights')
  await faceapi.nets.faceLandmark68Net.loadFromDisk('../../weights')
  await faceapi.nets.faceRecognitionNet.loadFromDisk('../../weights')

  const referenceImage = await canvas.loadImage(REFERENCE_IMAGE)
  const queryImage = await canvas.loadImage(QUERY_IMAGE)

  const resultsRef = await faceapi.detectAllFaces(referenceImage, faceDetectionOptions)
  .withFaceLandmarks()
  .withFaceDescriptors()

  const resultsQuery = await faceapi.detectAllFaces(queryImage, faceDetectionOptions)
  .withFaceLandmarks()
  .withFaceDescriptors()

  const faceMatcher = new faceapi.FaceMatcher(resultsRef)

  const labels = faceMatcher.labeledDescriptors
    .map(ld => ld.label)
  const refDrawBoxes = resultsRef
    .map(res => res.detection.box)
    .map((box, i) => new faceapi.draw.DrawBox(box, { label: labels[i] }))
  const outRef = faceapi.createCanvasFromMedia(referenceImage)
  refDrawBoxes.forEach(drawBox => drawBox.draw(outRef))

  saveFile('referenceImage.jpg', (outRef as any).toBuffer('image/jpeg'))

  const queryDrawBoxes = resultsQuery.map(res => {
    const bestMatch = faceMatcher.findBestMatch(res.descriptor)
    return new faceapi.draw.DrawBox(res.detection.box, { label: bestMatch.toString() })
  })
  const outQuery = faceapi.createCanvasFromMedia(queryImage)
  queryDrawBoxes.forEach(drawBox => drawBox.draw(outQuery))
  saveFile('queryImage.jpg', (outQuery as any).toBuffer('image/jpeg'))
}

run()

Can anyone help ?


Solution

  • const path = require('path')
    
    import * as faceapi from 'face-api.js';
    
    import { canvas, faceDetectionNet, faceDetectionOptions, saveFile } from    './commons';
    
    async function start() {
      await faceDetectionNet.loadFromDisk('../../weights')
      await faceapi.nets.faceLandmark68Net.loadFromDisk('../../weights')
      await faceapi.nets.faceRecognitionNet.loadFromDisk('../../weights')
    
      const labeledFaceDescriptors = await loadLabeledImages()
      const faceMatcher = new faceapi.FaceMatcher(labeledFaceDescriptors, 0.6)
    
      const queryImage = await canvas.loadImage(`test/test.jpeg`)
      //absolute link to image
    
    
    
        const detections = await faceapi.detectAllFaces(queryImage ).withFaceLandmarks().withFaceDescriptors()
        const queryDrawBoxes = detections.map(res => {
            const bestMatch = faceMatcher.findBestMatch(res.descriptor)
            return new faceapi.draw.DrawBox(res.detection.box, { label: bestMatch.toString() })
          })
          const outQuery = faceapi.createCanvasFromMedia(queryImage)
          queryDrawBoxes.forEach(drawBox => drawBox.draw(outQuery))
          saveFile('queryImage.jpg', (outQuery as any).toBuffer('image/jpeg'))
          console.log('done, saved results to out/queryImage.jpg')
    }
    
    function loadLabeledImages() {
      const labels = ['imgs']
      return Promise.all(
        labels.map(async label => {
          const descriptions = []
          for (let i = 1; i <= 5; i++) {
            const img = await canvas.loadImage(`/imgs/test${i}.jpeg` )
            // for example if you are test1 , test2, etc. like image's names
            const detections = await faceapi.detectSingleFace(img).withFaceLandmarks().withFaceDescriptor()
            descriptions.push(detections.descriptor)
          }
    
          return new faceapi.LabeledFaceDescriptors(label, descriptions)
        })
      )
    }
    start()