Loading

Node Js OpenCV Face Match

A simple facial match example with node.js and OpenCV

Barnabas Nomo | Wed, October 18th 2017


OpenCV (Open Source Computer Vision Library) is an open source computer vision and machine learning software library. OpenCV was built to provide a common infrastructure for computer vision applications and to accelerate the use of machine perception in the commercial products.

In this example, we'll compare a picture from our webcam with a picture saved on our computer and log the dissimilarities to the console.

To be able to do this, we'll need ot download OpenCV for our computer.

Note: As at the time of this tutorial(October 18, 2017), node js isn't fully compatible with opencv 3. We will use version 2.4.xx

Installing OpenCV on Mac.

brew tap homebrew/science
brew install opencv@2

Installing OpenCV on Linux

sudo apt-get install build-essential
sudo apt-get install cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev
sudo apt-get install python-dev python-numpy libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libjasper-dev libdc1394-22-dev

.Now we can run the following command to install opencv on linux

sudo apt-get install libopencv-dev

Installing OpenCV on Windows.

Please refer to this article Open Cv Install Guide for Windows

Project

npm init -y

Now let's install the opencv npm module.

npm install --save opencv

let's look at a simple example on reading images first.

Here's an image we would like to read

Example image

Steps

  • We will first read the file
  • Then ask the OpenCV library to detect faces
  • Create a copy of the file with faces circled.

detect-faces.js

// Require OpenCV node module
var cv = require('opencv');

// create a function to read images
function readImg(obj) {
    // invoke readImage method
    cv.readImage(obj, function (err, im) {
        if (err) throw err;

        // Ensure image has been read/object is an actual image
        if (im.width() < 1 || im.height() < 1) throw new Error('Image has no size');
        
        // detect faces and push into array called faces(passed as an argument in
        // the callback
        im.detectObject(cv.FACE_CASCADE, {}, function (err, faces) {
            if (err) throw err;

            for (var i = 0; i < faces.length; i++) {
                var face = faces[i];
                // use the ellipse method to draw circle
                im.ellipse(face.x + face.width / 2, face.y + face.height / 2, face.width / 2, face.height / 2);
            }
            // save image under new name
            var newObj = `faces-${obj}`;
            im.save(newObj);
            console.log('Image saved as '+newObj);
        });
    });
}

readImg('all-smiles.JPG');

this is how the image will look after the detection algorithm runs

After detection

Now, let's look at the steps we'll take to compare two images

  1. Snap picture if face is detected in webcam
  2. Compare the picture with the image of a saved face
  3. Run dissimilarity algorithm
  4. Log the dissimilarity as a percentage
var cv = require('opencv');
try {
  var vid = new cv.VideoCapture(0);

  // read video being captured
  vid.read(function(err, im){
    if (err) throw err;
    // check for file
    if (im.size()[0] > 0 && im.size()[1] > 0){
      
      // detect faces
      im.detectObject(cv.FACE_CASCADE, {}, function(err, faces){
        if (err) throw err;
        if (!faces.length) return console.log("No Faces");

        // get just the first face
        var face = faces[0];
        var ims = im.size();
        var im2 = im.roi(face.x, face.y, face.width, face.height)
        
        // best to use a picture of a face, just a face for accuracy
        cv.readImage('./all-smiles.JPG', function(err, me){
          if(err) throw err;
          
          // Detect faces from the picture, it should return an array
          me.detectObject(cv.FACE_CASCADE, {}, function(err, my_faces){
            if (err) throw err;
            if (!my_faces.length) return console.log("No Faces");

            // get the first face in the array (which happens to not be me)
            var myface = my_faces[0];

            // get only the face you want to
            // compare with by resizing the picture
            // to new dimension relative to the position
            // of said face in the picture
            var face_only = me.roi(myface.x, myface.y, myface.width, myface.height);

            // check dissimilarity
            cv.ImageSimilarity(face_only, im2, function(err, dissimilarity){
              if(err) throw err;
              console.log(`Dissimilarity:  ${dissimilarity}%`);
            });
            // you can save the two images being compared 😉
            face_only.save('my-face-1.jpg');
            im2.save('./take-face-pics-1.jpg')
          });
        });
     });
    } else {
      // camera couldn't start
      console.log("Camera didn't return image")
    }
  });
} catch (e){
  // handle error
  console.log("Couldn't start camera", e)
}

The terminal output will look like this

Dissimilarity:  60.6%

If you would rather want to see the similarity instead, change the following line in your code from

console.log(`Dissimilarity:  ${dissimilarity}%`);

to

console.log(`Similarity:  ${100 - dissimilarity}%`);

That's it! Very easy, you can check out the code repo on Github or Click here to download