Skip to content

Transparent OpenCV API for nodejs, with examples for: Face Detection, Hand Gesture Recognition, Object Tracking, Feature Matching, Image Histogram

Notifications You must be signed in to change notification settings

mstegmann-avarteq/opencv4nodejs

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

opencv4nodejs

Build Status node version

Brings lots of features of OpenCV 3.x to nodejs to use as a service, integrate into your Electron app or simply to play around with the OpenCV API in Javascript instead of C++.

Examples

See examples for implementation.

Face Detection

face0 face1

Hand Gesture Recognition

Check out my article for this example.

gesture-rec_sm

Object Tracking

trackbgsubtract trackbycolor

Feature Matching

matchsift

Image Histogram

plotbgr plotgray

How to install

$ npm install --save opencv4nodejs

Make sure to have OpenCV 3+ ( extra modules are optional ) installed on your System https://github.com/opencv/opencv/releases/. In case you are running Windows or have OpenCV set up in a custom directory make sure to set the following environment variables:

  1. OPENCV_DIR pointing to the root path containing include directory or set OPENCV_INCLUDE_DIR explicitly.
  2. OPENCV_LIB_DIR pointing to the static library dir containing the OpenCV .lib or .so files.

If you are running into issues also check the requirements for node-gyp specific to your OS https://github.com/nodejs/node-gyp.

Usage with Electron

$ npm install --save electron-rebuild

Add the following script to your package.json:

"electron-rebuild": "electron-rebuild -w opencv4nodejs"

Run the script:

$ npm run electron-rebuild

Require it in the application:

const electron = require('electron');
const cv = electron.remote.require('opencv4nodejs');

Documentation

const cv = require('opencv4nodejs');

Initializing Mat (image matrix), Vec, Point

const rows = 100; // height
const cols = 100; // width

// empty Mat
const emptyMat = new cv.Mat(rows, cols, cv.cvTypes.CV_8UC3);

// fill the Mat with default value
const whiteMat = new cv.Mat(rows, cols, cv.cvTypes.CV_8UC1, 255);
const blueMat = new cv.Mat(rows, cols, cv.cvTypes.CV_8UC3, [255, 0, 0]);

// from array (3x3 Matrix, 3 channels)
const matData = [
  [[255, 0, 0], [255, 0, 0], [255, 0, 0]],
  [[0, 0, 0], [0, 0, 0], [0, 0, 0]],
  [[255, 0, 0], [255, 0, 0], [255, 0, 0]]
];
const matFromArray = new cv.Mat(matData, cv.cvTypes.CV_8UC3);

// from node buffer
const charData = [255, 0, ...];
const matFromArray = new cv.Mat(new Buffer.from(charData), rows, cols, cv.cvTypes.CV_8UC3);

// Point
const pt2 = new cv.Point(100, 100);
const pt3 = new cv.Point(100, 100, 0.5);

// Vector
const vec2 = new cv.Vec(100, 100);
const vec3 = new cv.Vec(100, 100, 0.5);
const vec4 = new cv.Vec(100, 100, 0.5, 0.5);

Mat and Vec operations

const mat0 = new cv.Mat(...);
const mat1 = new cv.Mat(...);

// arithmetic operations for Mats and Vecs
const matMultipliedByScalar = mat0.mul(0.5);  // scalar multiplication
const matDividedByScalar = mat0.div(2);       // scalar division
const mat0PlusMat1 = mat0.add(mat1);          // addition
const mat0MinusMat1 = mat0.sub(mat1);         // subtraction
const mat0MulMat1 = mat0.hMul(mat1);          // elementwise multiplication
const mat0DivMat1 = mat0.hDiv(mat1);          // elementwise division

// logical operations Mat only
const mat0AndMat1 = mat0.and(mat1);
const mat0OrMat1 = mat0.or(mat1);
const mat0bwAndMat1 = mat0.bitwiseAnd(mat1);
const mat0bwOrMat1 = mat0.bitwiseOr(mat1);
const mat0bwXorMat1 = mat0.bitwiseXor(mat1);
const mat0bwNot = mat0.bitwiseNot();

Accessing Mat data

const matBGR = new cv.Mat(..., cv.cvTypes.CV_8UC3);
const matGray = new cv.Mat(..., cv.cvTypes.CV_8UC1);

// get pixel value as vector or number value
const vec3 = matBGR.at(200, 100);
const grayVal = matGray.at(200, 100);

// get raw pixel value as array
const [b, g, r] = matBGR.atRaw(200, 100);

// set single pixel values
matBGR.set(50, 50, [255, 0, 0]);
matBGR.set(50, 50, new Vec(255, 0, 0));
matGray.set(50, 50, 255);

// get a 25x25 sub region of the Mat at offset (50, 50)
const width = 25;
const height = 25;
const region = matBGR.getRegion(new cv.Rect(50, 50, width, height));

// get a node buffer with raw Mat data
const matAsBuffer = matBGR.getData();

// get entire Mat data as JS array
const matAsArray = matBGR.getDataAsArray();

IO

// load image from file
const mat = cv.imread('./path/img.jpg');

// save image
cv.imwrite('./path/img.png', mat);

// show image
cv.imshow('a window name', mat);
cv.waitKey();

// open capture from webcam
const devicePort = 0;
const wCap = new cv.VideoCapture(devicePort);

// open video capture
const vCap = new cv.VideoCapture('./path/video.mp4');

// read frames from capture
const delay = 10;
let done = false;
while (!done) {
  let frame = vCap.read();
  // loop back to start on end of stream reached
  if (frame.empty) {
    vCap.reset();
    frame = vCap.read();
  }

  // ...

  const key = cv.waitKey(delay);
  done = key !== 255;
}

Useful Mat methods

const matBGR = new cv.Mat(..., cv.cvTypes.CV_8UC3);

// convert types
const matSignedInt = matBGR.convertTo({
  type: cv.cvTypes.CV_32SC3
});
const matDoublePrecision = matBGR.convertTo({
  type: cv.cvTypes.CV_64FC3
});

// convert color space
const { COLOR_BGR2HSV, COLOR_BGR2Lab } = cv.cvTypes;
const matGray = matBGR.bgrToGray();
const matHSV = matBGR.cvtColor({
  code: COLOR_BGR2HSV
});
const matLab = matBGR.cvtColor({
  code: COLOR_BGR2Lab
});

// resize
const matHalfSize = matBGR.rescale(0.5);
const mat100x100 = matBGR.resize(100, 100);
const matMaxDimIs100 = matBGR.resizeToMax(100);

// extract channels and create Mat from channels
const [matB, matG, matR] = matBGR.splitChannels();
const matRGB = new cv.Mat([matR, matB, matG]);

Drawing a Mat into HTML Canvas

    const matBGR = ...;
    // convert your Mat to rgba space
    const matRGBA = matBGR.cvtColor({
      type: cv.cvTypes.colorConversionCodes.COLOR_BGR2RGBA
    });
    // get raw Mat data
    const matDataRaw = matRGBA.getData();

    // fill canvas pixels
    const canvas = document.getElementById('myCanvas');
    const ctx = canvas.getContext('2d');
    const imgData = ctx.getImageData(0, 0, matRGBA.cols, matRGBA.rows);
    for (let i = 0; i < matDataRaw.length; i += 1) {
      imgData.data[i] = matDataRaw[i];
    }
    ctx.putImageData(imgData, 0, 0);

Method Interface

OpenCV method interface from official docs or src:

void GaussianBlur(InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY = 0, int borderType = BORDER_DEFAULT);

translates to:

const src = new cv.Mat(...);
// invoke with required arguments
const dst0 = src.gaussianBlur({
  ksize: new cv.Size(5, 5),
  sigmaX: 1.2
});
// or pass optional parameters
const dst1 = src.gaussianBlur({
  ksize: new cv.Size(5, 5),
  sigmaX: 1.2,
  borderType: cv.cvTypes.borderTypes.BORDER_CONSTANT
});

For more documentation refer to examples or have a look into the tests for method invocation.

About

Transparent OpenCV API for nodejs, with examples for: Face Detection, Hand Gesture Recognition, Object Tracking, Feature Matching, Image Histogram

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • C++ 65.8%
  • JavaScript 33.4%
  • Python 0.8%