Use face-api.js on node js

Use face-api.js on node js

Face-api.js is a great library that uses tensorflowjs to do face recognition, face detection, face landmarks, and other stuff with faces...
The problem is that is complicated, the code is complicated, the examples are complicated and the documentation is complicated.
The dude writing here likes simple things, he is a simple guy.

so here is a dumb proof step by step tutorial to get started using face-api.js.

step 1
clone the default repo

git clone https://github.com/justadudewhohacks/face-api.js.git

step 2
create your project folder

mkdir facetest &&
cd facetest &&
npm init

step 3
install dependencies required for the canvas module

sudo apt install libpango1.0-dev libcairo-dev libpixman-1-dev libjpeg-dev

step 4
add faceapi and canvas as dependencies

npm i -s face-api.js canvas

step 5
copy the weights directory from face-api.js

step 6
create a app.js file with the following content

const faceapi = require("face-api.js")
const canvas = require("canvas")
const fs = require("fs")
const path = require("path")

// mokey pathing the faceapi canvas
const { Canvas, Image, ImageData } = canvas
faceapi.env.monkeyPatch({ Canvas, Image, ImageData })

const faceDetectionNet = faceapi.nets.ssdMobilenetv1

// SsdMobilenetv1Options
const minConfidence = 0.5

// TinyFaceDetectorOptions
const inputSize = 408
const scoreThreshold = 0.5

// MtcnnOptions
const minFaceSize = 50
const scaleFactor = 0.8

function getFaceDetectorOptions(net) {
    return net === faceapi.nets.ssdMobilenetv1
        ? new faceapi.SsdMobilenetv1Options({ minConfidence })
        : (net === faceapi.nets.tinyFaceDetector
            ? new faceapi.TinyFaceDetectorOptions({ inputSize, scoreThreshold })
            : new faceapi.MtcnnOptions({ minFaceSize, scaleFactor })
        )
}

const faceDetectionOptions = getFaceDetectorOptions(faceDetectionNet)

// simple utils to save files
const baseDir = path.resolve(__dirname, './out')
function saveFile(fileName, buf) {
    if (!fs.existsSync(baseDir)) {
      fs.mkdirSync(baseDir)
    }
    // this is ok for prototyping but using sync methods
    // is bad practice in NodeJS
    fs.writeFileSync(path.resolve(baseDir, fileName), buf)
  }

async function run() {

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

    // load the image
    const img = await canvas.loadImage('imgs_src/da.jpeg')
    
    // detect the faces with landmarks
    const results = await faceapi.detectAllFaces(img, faceDetectionOptions)
        .withFaceLandmarks()
    // create a new canvas and draw the detection and landmarks
    const out = faceapi.createCanvasFromMedia(img)
    faceapi.drawDetection(out, results.map(res => res.detection))
    faceapi.drawLandmarks(out, results.map(res => res.landmarks), { drawLines: true, color: 'red' })

    // save the new canvas as image
    saveFile('faceLandmarkDetection.jpg', out.toBuffer('image/jpeg'))
    console.log('done, saved results to out/faceLandmarkDetection.jpg')
}

run()

step7
create a folder img_src and ad a jpeg file (in this case da.jpeg)

step8
run the following command

node app.js

step 9
watch the result in the directory out/

Here is the result obtained using my profile pic