Face Detection using Haar Cascades in opencv.js - Node.js error

I have implemented the opencv.js in Node.js server using the tutorials from OpenCV: Using OpenCV.js In Node.js.

Emulating HTML DOM and canvas in the tutorials works successfully in the project but the code for detecting objects(Face) is throwing error while loading Haar Cascades.

Here is my code in github,
rusaik/opencv_detect (github.com)

I have attached the project which i have forked in Stackblitz using above repository, Unfortunately it is not running , but you can easily view the code there.
Stackblitz repo

When the compiler is running the code to load the haarcascade_frontalface_default.xml

  faceCascade.load('./haarcascade_frontalface_default.xml');

Error

6620792

Please let me know anyone find what i’m missing here.

Of course, you should post your code here and not ask people to navigate a repository #makeHelpingAsEasyAsPosdible

You obviously have googled about this, but must have missed this

1 Like

index.js file

const { Canvas, createCanvas, Image, ImageData, loadImage } = require('canvas');
const { JSDOM } = require('jsdom');
const { writeFileSync, existsSync, mkdirSync } = require('fs');
const Utils = require("./utils.js");
(async () => {
  await loadOpenCV();
  const image = await loadImage('lena.jpg');
  const src = cv.imread(image);
  //await copyFile(src);
  let gray = new cv.Mat();
  console.log('image loaded');
  cv.cvtColor(src, gray, cv.COLOR_RGBA2GRAY);
  console.log('0');
  let faces = new cv.RectVector();
  let eyes = new cv.RectVector();
  console.log('1');

  let faceCascade = new cv.CascadeClassifier();
  let eyeCascade = new cv.CascadeClassifier();
  console.log('2');
  console.log(gray.shape);
  let utils = new Utils('errorMessage');

  let faceCascadeFile = 'haarcascade_frontalface_default.xml';
  let url = 'https://github.com/opencv/opencv/blob/4.x/data/haarcascades/haarcascade_frontalface_default.xml';
  
  await utils.createFileFromUrl(url, faceCascadeFile);
  //, async () => {});
  console.log(`faceCascade loading started`);
  // Load pre-trained classifier files. Notice how we reference local files using relative paths just
  // like we normally would do
  faceCascade.load('haarcascade_frontalface_default.xml');
  // eyeCascade.load('./haarcascade_eye.xml');
  console.log(`faceCascade`);
 // console.log(faceCascade.empty());

  //let mSize = new cv.Size(0, 0);
  /*faceCascade.detectMultiScale(gray, faces, 1.1, 3, 0, mSize, mSize);
  for (let i = 0; i < faces.size(); ++i) {
    let roiGray = gray.roi(faces.get(i));
    let roiSrc = src.roi(faces.get(i));
    let point1 = new cv.Point(faces.get(i).x, faces.get(i).y);
    let point2 = new cv.Point(faces.get(i).x + faces.get(i).width, faces.get(i).y + faces.get(i).height);
    cv.rectangle(src, point1, point2, [255, 0, 0, 255]);
    roiGray.delete();
    roiSrc.delete();
  }
  const canvas = createCanvas(image.width, image.height);
  cv.imshow(canvas, src);
  writeFileSync('output3.jpg', canvas.toBuffer('image/jpeg'));
  src.delete(); gray.delete(); faceCascade.delete(); eyeCascade.delete(); faces.delete(); eyes.delete()*/
})();
/**
 * Loads opencv.js.
 *
 * Installs HTML Canvas emulation to support `cv.imread()` and `cv.imshow`
 *
 * Mounts given local folder `localRootDir` in emscripten filesystem folder `rootDir`. By default it will mount the local current directory in emscripten `/work` directory. This means that `/work/foo.txt` will be resolved to the local file `./foo.txt`
 * @param {string} rootDir The directory in emscripten filesystem in which the local filesystem will be mount.
 * @param {string} localRootDir The local directory to mount in emscripten filesystem.
 * @returns {Promise} resolved when the library is ready to use.
 */
function loadOpenCV(rootDir = '/work', localRootDir = process.cwd()) {
  if (global.Module && global.Module.onRuntimeInitialized && global.cv && global.cv.imread) {
    return Promise.resolve()
  }
  return new Promise(resolve => {
    installDOM()
    global.Module = {
      onRuntimeInitialized() {
        // We change emscripten current work directory to 'rootDir' so relative paths are resolved
        // relative to the current local folder, as expected
        cv.FS.chdir(rootDir)
        resolve()
      },
      preRun() {
        console.log('pre run')
        // preRun() is another callback like onRuntimeInitialized() but is called just before the
        // library code runs. Here we mount a local folder in emscripten filesystem and we want to
        // do this before the library is executed so the filesystem is accessible from the start
        const FS = global.Module.FS
        // create rootDir if it doesn't exists
        if (!FS.analyzePath(rootDir).exists) {
          FS.mkdir(rootDir);
        }
        // create localRootFolder if it doesn't exists
        if (!existsSync(localRootDir)) {
          mkdirSync(localRootDir, { recursive: true });
        }
        // FS.mount() is similar to Linux/POSIX mount operation. It basically mounts an external
        // filesystem with given format, in given current filesystem directory.
        FS.mount(FS.filesystems.NODEFS, { root: localRootDir }, rootDir);
      }
    };
    global.cv = require('./opencv.js')
  });
}
function installDOM() {
  const dom = new JSDOM();
  global.document = dom.window.document;
  global.Image = Image;
  global.HTMLCanvasElement = Canvas;
  global.ImageData = ImageData;
  global.HTMLImageElement = Image;
  console.log('install dom')
}

utils.js file

const fs = require('fs');
const util = require('util');
const fetch = require('cross-fetch');

// utils.js
class Utils {
    constructor(errorMessage) {
        this.errorMessage = errorMessage;
        console.log(this.errorMessage);
    }

    writeFile = util.promisify(fs.writeFile);

    throwErrorIfNull(value) {
        if (value === null || value === undefined) {
            throw new Error(this.errorMessage);
        }
    }

    async createFileFromUrl(url, filePath) {
        try {
            const response = await fetch(url);
            const buffer = await response.buffer();
            await this.writeFile(filePath, buffer);
            console.log(`File ${filePath} created successfully from ${url}`);
        } catch (error) {
            console.error(`Error creating file from ${url}: ${error}`);
        }
    }
}

module.exports = Utils;

Downloaded the haarcascade_frontalface_default.xml file from [OpenCV sources] (opencv/data/haarcascades at 4.x · opencv/opencv · GitHub)

Every files are in the same directory as below structure.

  • haarcascade_frontalface_default.xml
  • index.js
  • lena.jpg
  • opencv.js

The error thrown while loading the facecascade is given below.

abort(6620792). Build with -s ASSERTIONS=1 for more info.
Thrown at:
    at path\opencv\opencv.js:30:1693
    at emit (node:events:513:28)

@matti.vuori i have tried the example you mentioned, please check the code given, Also i am running this code in Noed.js server environment (Not browser)

Thanks in advance!

this will dl the html rendered view, not the required raw xml, use a different URL:

https://github.com/opencv/opencv/raw/4.x/data/haarcascades/haarcascade_frontalface_default.xml

(s/blob/raw)

1 Like

It works! Thank you very much @berak :heart:

1 Like