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!