Awesome
@u4/opencv4nodejs
Getting started
Opencv4nodejs can be linked to a prebuild openCV 3 or 4. or can build its own openCV using @u4/opencv-build, In this case, you have to choose which version you want to link.
Since version 7, you should be able to use this module directly without any configuration if you have OpenCV installed from your package manager (Chocolatey / Brew / apt).
To use your OWN openCV build
3 way to use your own openCV (Without automatic building)
1) Environment variable
Define environment variable:
OPENCV4NODEJS_DISABLE_AUTOBUILD
=1
If you do not install openCV with a common setup like chocolate, apt or brew, you may need to also define:
OPENCV_INCLUDE_DIR
=include path
, OPENCV_LIB_DIR
=lib path
, OPENCV_BIN_DIR
=binary path
2) package.json
Define an opencv4nodejs section in your package.json like:
"opencv4nodejs": {
"disableAutoBuild": "1"
}
If you do not install openCV with a common setup like chocolatey, apt or brew, you may need to also define:
"OPENCV_INCLUDE_DIR"
, "OPENCV_LIB_DIR"
, "OPENCV_BIN_DIR"
3) use build-opencv
Call build-opencv
once like:
npm link
build-opencv --nobuild rebuild
If you do not install openCV with a common setup like chocolatey, apt or brew, you may need to also define:
npm link
build-opencv --incDir /usr/include/opencv4/ --libDir /lib/x86_64-linux-gnu/ --binDir=/usr/bin/ --nobuild rebuild
To build openCV using the built-in builder
If you want to build OpenCV define the environment variable OPENCV_BUILD_ROOT
to speed up your development, so openCV build will be processed out of your node_modules
ex:
OPENCV_BUILD_ROOT=~/opencv
3 ways to build openCV 4.6.0
1) Environment variable
Define environment variable:
OPENCV4NODEJS_AUTOBUILD_OPENCV_VERSION
="4.9.0"
2) package.json
Define an opencv4nodejs section in your package.json like:
"opencv4nodejs" {
"autoBuildOpencvVersion": "4.6.0",
}
3) use build-opencv
Call build-opencv
once like:
npm link
build-opencv --version 4.6.0 rebuild
** make it portable use Docker **
You can also use my docker image I use it on my raspberry Pi 4, and build them on an Oracle Ampere (they delete all my stuff and do not reply to my requests) Mac Mini M1
check Docker sample below
for advanced option
- @u4/opencv-build for info.
opencv4nodejs allows you to use the native OpenCV library in nodejs. Besides a synchronous API the package provides an asynchronous API, which allows you to build non-blocking and multithreaded computer vision tasks. opencv4nodejs supports OpenCV 3 and OpenCV 4.
The ultimate goal of this project is to provide a comprehensive collection of nodejs bindings to the API of OpenCV and the OpenCV-contrib modules. To get an overview of the currently implemented bindings, have a look at the type declarations of this package. Furthermore, contribution is highly appreciated. If you want to add missing bindings check out the contribution guide.
- Examples
- How to install
- Usage with Docker
- Usage with Electron
- Usage with NW.js
- Quick Start
- Async API
- With TypeScript
- External Memory Tracking (v4.0.0) <a name="examples"></a>
Examples
See examples for implementation.
Face Detection
Face Recognition with the OpenCV face module
Check out Node.js + OpenCV for Face Recognition</b></a>.
Face Landmarks with the OpenCV face module
Face Recognition with face-recognition.js
Check out Node.js + face-recognition.js : Simple and Robust Face Recognition using Deep Learning.
Hand Gesture Recognition
Check out Simple Hand Gesture Recognition using OpenCV and JavaScript.
Object Recognition with Deep Neural Networks
Check out Node.js meets OpenCV’s Deep Neural Networks — Fun with Tensorflow and Caffe.
Tensorflow Inception
Single Shot Multibox Detector with COCO
Machine Learning
Check out Machine Learning with OpenCV and JavaScript: Recognizing Handwritten Letters using HOG and SVM.
Object Tracking
Feature Matching
Image Histogram
Boiler plate for combination of opencv4nodejs, express and websockets
opencv4nodejs-express-websockets - Boilerplate express app for getting started on opencv with nodejs and to live stream the video through websockets.
Automating lights by people detection through classifier
Check out Automating lights with Computer Vision & NodeJS.
<a name="how-to-install"></a>
How to install
npm install --save @u4/opencv4nodejs
Native node modules are built via node-gyp, which already comes with npm by default. However, node-gyp requires you to have python installed. If you are running into node-gyp specific issues have a look at known issues with node-gyp first.
Important note: node-gyp won't handle whitespaces properly, thus make sure, that the path to your project directory does not contain any whitespaces. Installing opencv4nodejs under "C:\Program Files\some_dir" or similar will not work and will fail with: "fatal error C1083: Cannot open include file: 'opencv2/core.hpp'"!**
On Windows, you will furthermore need Windows Build Tools to compile OpenCV and opencv4nodejs. If you don't have Visual Studio or Windows Build Tools installed, you can easily install the VS2015 build tools:
npm install --global windows-build-tools
Once the @u4/opencv4nodejs is installed, prepare a compilation task in your package.json
{
"scripts": {
"install_arm64": "build-opencv --version 4.5.4 --flag=\"-DCMAKE_SYSTEM_PROCESSOR=arm64 -DCMAKE_OSX_ARCHITECTURES=arm64\" build",
"install_4.5.5_cuda": "build-opencv --version 4.5.5 --flags=\"-DWITH_CUDA=ON -DWITH_CUDNN=ON -DOPENCV_DNN_CUDA=ON -DCUDA_FAST_MATH=ON\" build",
"do-install": "build-opencv build",
}
}
then call it to build the mapping
npm run install_4.5.5_cuda
All build params can be appended to the build-opencv
build command line (see build-opencv --help
) the opencv4nodejs part of package.json are still read but you should not use it for a new project.
Installing OpenCV Manually
Setting up OpenCV on your own will require you to set an environment variable to prevent the auto build script from running:
# linux and osx:
export OPENCV4NODEJS_DISABLE_AUTOBUILD=1
# on windows:
set OPENCV4NODEJS_DISABLE_AUTOBUILD=1
Windows
You can install any of the OpenCV 3 or OpenCV 4 releases manually or via the Chocolatey package manager:
# to install OpenCV 4.6.0
choco install OpenCV -y -version 4.6.0
Note, this will come without contrib modules. To install OpenCV under windows with contrib modules you have to build the library from source or you can use the auto build script.
Before installing opencv4nodejs with your own installation of OpenCV you need to expose the following environment variables:
- OPENCV_INCLUDE_DIR pointing to the directory with the subfolder opencv2 containing the header files
- OPENCV_LIB_DIR pointing to the lib directory containing the OpenCV .lib files
Also, you will need to add the OpenCV binaries to your system path:
- add an environment variable OPENCV_BIN_DIR pointing to the binary directory containing the OpenCV .dll files
- append
;%OPENCV_BIN_DIR%;
to your system path variable
Note: Restart your current console session after making changes to your environment.
MacOSX
Under OSX we can simply install OpenCV via brew:
brew update
brew install opencv@4
brew link --force opencv@4
Linux
Under Linux we have to build OpenCV from source manually or using the auto build script.
Installing OpenCV via Auto Build Script
The auto build script comes in the form of the opencv-build npm package, which will run by default when installing opencv4nodejs. The script requires you to have git and a recent version of cmake installed.
Auto Build Flags
You can customize the autobuild flags using OPENCV4NODEJS_AUTOBUILD_FLAGS=<flags>. Flags must be space-separated.
This is an advanced customization and you should have knowledge regarding the OpenCV compilation flags. Flags added by default are listed here.
Installing a Specific Version of OpenCV
You can specify the Version of OpenCV you want to install via the script by setting an environment variable:
export OPENCV4NODEJS_AUTOBUILD_OPENCV_VERSION=4.6.0
Installing only a Subset of OpenCV modules
If you only want to build a subset of the OpenCV modules you can pass the -DBUILD_LIST cmake flag via the OPENCV4NODEJS_AUTOBUILD_FLAGS environment variable. For example export OPENCV4NODEJS_AUTOBUILD_FLAGS=-DBUILD_LIST=dnn
will build only modules required for dnn
and reduces the size and compilation time of the OpenCV package.
Configuring Environments via package.json (deprecated)
It's possible to specify build environment variables by inserting them into the package.json
as follows:
{
"name": "my-project",
"version": "0.0.0",
"dependencies": {
"@u4/opencv4nodejs": "^X.X.X"
},
"opencv4nodejs": {
"disableAutoBuild": 1,
"opencvIncludeDir": "C:\\tools\\opencv\\build\\include",
"opencvLibDir": "C:\\tools\\opencv\\build\\x64\\vc14\\lib",
"opencvBinDir": "C:\\tools\\opencv\\build\\x64\\vc14\\bin"
}
}
The following environment variables can be passed:
- autoBuildBuildCuda
- autoBuildFlags
- autoBuildOpencvVersion
- autoBuildWithoutContrib
- disableAutoBuild
- opencvIncludeDir
- opencvLibDir
- opencvBinDir
Using distrib prebuilt package
sudo apt install libopencv-dev
build-opencv --incDir /usr/include/opencv4/ --libDir /lib/x86_64-linux-gnu/ --binDir=/usr/bin/ --nobuild rebuild
<a name="usage-with-docker"></a>
Usage with Docker
a sample DockerBuild script is available here
This is an optimized 2 stages images working on ARM64 and AMD64, tested on raspberry Pi4, and Apple silicon, intel Core, and AMD Ryzen CPU.
opencv-express - example for opencv4nodejs with express.js and docker
Or simply pull from urielch/opencv-nodejs for opencv-4.6.0 contrib with opencv4nodejs binary globally installed:
FROM urielch/opencv-nodejs
Note: The aforementioned Docker image already has opencv4nodejs
installed globally. In order to prevent build errors during an npm install
, your package.json
should not include opencv4nodejs
, and instead should include/require the global package either by requiring it by absolute path or setting the NODE_PATH
environment variable to /usr/lib/node_modules
in your Dockerfile and requiring the package as you normally would.
Different OpenCV 3.x base images can be found here: https://hub.docker.com/r/justadudewhohacks/.
<a name="usage-with-electron"></a>
Usage with Electron
opencv-electron - example for opencv4nodejs with electron
Add the following script to your package.json:
"electron-rebuild": "build-opencv --electron --version 4.5.4 build"
Run the script:
npm run electron-rebuild
Require it in the application:
const cv = require('@u4/opencv4nodejs');
<a name="usage-with-nwjs"></a>
Usage with NW.js
Any native modules, including opencv4nodejs, must be recompiled to be used with NW.js. Instructions on how to do this are available in the Use Native Modules section of the NW.js documentation.
Once recompiled, the module can be installed and required as usual:
const cv = require('@u4/opencv4nodejs');
<a name="quick-start"></a>
Quick Start
const cv = require('@u4/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.CV_8UC3);
// fill the Mat with default value
const whiteMat = new cv.Mat(rows, cols, cv.CV_8UC1, 255);
const blueMat = new cv.Mat(rows, cols, cv.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.CV_8UC3);
// from node buffer
const charData = [255, 0, ...];
const matFromArray = new cv.Mat(Buffer.from(charData), rows, cols, cv.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.CV_8UC3);
const matGray = new cv.Mat(..., cv.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');
cv.imreadAsync('./path/img.jpg', (err, mat) => {
...
})
// save image
cv.imwrite('./path/img.png', mat);
cv.imwriteAsync('./path/img.jpg', mat, (err) => {
...
})
// show image
cv.imshow('a window name', mat);
cv.waitKey();
// load base64 encoded image
const base64text='data:image/png;base64,R0lGO..';//Base64 encoded string
const base64data =base64text.replace('data:image/jpeg;base64','')
.replace('data:image/png;base64','');//Strip image type prefix
const buffer = Buffer.from(base64data,'base64');
const image = cv.imdecode(buffer); //Image is now represented as Mat
// convert Mat to base64 encoded jpg image
const outBase64 = cv.imencode('.jpg', croppedImage).toString('base64'); // Perform base64 encoding
const htmlImg='<img src=data:image/jpeg;base64,'+outBase64 + '>'; //Create insert into HTML compatible <img> tag
// 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 frame = vCap.read();
vCap.readAsync((err, frame) => {
...
});
// loop through the 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.CV_8UC3);
// convert types
const matSignedInt = matBGR.convertTo(cv.CV_32SC3);
const matDoublePrecision = matBGR.convertTo(cv.CV_64FC3);
// convert color space
const matGray = matBGR.bgrToGray();
const matHSV = matBGR.cvtColor(cv.COLOR_BGR2HSV);
const matLab = matBGR.cvtColor(cv.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 img = ...
// convert your image to rgba color space
const matRGBA = img.channels === 1
? img.cvtColor(cv.COLOR_GRAY2RGBA)
: img.cvtColor(cv.COLOR_BGR2RGBA);
// create new ImageData from raw mat data
const imgData = new ImageData(
new Uint8ClampedArray(matRGBA.getData()),
img.cols,
img.rows
);
// set canvas dimensions
const canvas = document.getElementById('myCanvas');
canvas.height = img.rows;
canvas.width = img.cols;
// set image data
const ctx = canvas.getContext('2d');
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(new cv.Size(5, 5), 1.2);
// with optional paramaters
const dst2 = src.gaussianBlur(new cv.Size(5, 5), 1.2, 0.8, cv.BORDER_REFLECT);
// or pass specific optional parameters
const optionalArgs = {
borderType: cv.BORDER_CONSTANT
};
const dst2 = src.gaussianBlur(new cv.Size(5, 5), 1.2, optionalArgs);
<a name="async-api"></a>
Async API
The async API can be consumed by passing a callback as the last argument of the function call. By default, if an async method is called without passing a callback, the function call will yield a Promise.
Async Face Detection
const classifier = new cv.CascadeClassifier(cv.HAAR_FRONTALFACE_ALT2);
// by nesting callbacks
cv.imreadAsync('./faceimg.jpg', (err, img) => {
if (err) { return console.error(err); }
const grayImg = img.bgrToGray();
classifier.detectMultiScaleAsync(grayImg, (err, res) => {
if (err) { return console.error(err); }
const { objects, numDetections } = res;
...
});
});
// via Promise
cv.imreadAsync('./faceimg.jpg')
.then(img =>
img.bgrToGrayAsync()
.then(grayImg => classifier.detectMultiScaleAsync(grayImg))
.then((res) => {
const { objects, numDetections } = res;
...
})
)
.catch(err => console.error(err));
// using async await
try {
const img = await cv.imreadAsync('./faceimg.jpg');
const grayImg = await img.bgrToGrayAsync();
const { objects, numDetections } = await classifier.detectMultiScaleAsync(grayImg);
...
} catch (err) {
console.error(err);
}
<a name="with-typescript"></a>
With TypeScript
import cv from '@u4/opencv4nodejs'
Check out the TypeScript examples.
<a name="external-mem-tracking"></a>
External Memory Tracking (v4.0.0)
Since version 4.0.0 was released, external memory tracking has been enabled by default. Simply put, the memory allocated for Matrices (cv.Mat) will be manually reported to the node process. This solves the issue of inconsistent Garbage Collection, which could have resulted in spiking memory usage of the node process eventually leading to overflowing the RAM of your system, prior to version 4.0.0.
Note, that in doubt this feature can be disabled by setting an environment variable OPENCV4NODEJS_DISABLE_EXTERNAL_MEM_TRACKING
before requiring the module:
export OPENCV4NODEJS_DISABLE_EXTERNAL_MEM_TRACKING=1 // linux
set OPENCV4NODEJS_DISABLE_EXTERNAL_MEM_TRACKING=1 // windows
Or directly in your code:
process.env.OPENCV4NODEJS_DISABLE_EXTERNAL_MEM_TRACKING = 1
const cv = require('@u4/opencv4nodejs')