Merge pull request #1 from peterbraden/master

update the fork
This commit is contained in:
Dmitry Ivanov 2017-03-07 22:12:46 -05:00 committed by GitHub
commit d1fe7e8f3a
53 changed files with 1263 additions and 177 deletions

1
.gitignore vendored
View File

@ -8,3 +8,4 @@ out*.png
examples/*.avi
examples/tmp/*
vagrant/.vagrant
coverage/

View File

@ -30,6 +30,8 @@ before_install:
- sudo add-apt-repository -y ppa:kubuntu-ppa/backports
- sudo apt-get update
- sudo apt-get install --force-yes --yes libcv-dev libcvaux-dev libhighgui-dev libopencv-dev
# for code coverage
- sudo apt-get install lcov
# get commit message
- COMMIT_MESSAGE=$(git show -s --format=%B $TRAVIS_COMMIT | tr -d '\n')
# put local node-pre-gyp on PATH
@ -49,11 +51,11 @@ before_install:
- platform=$(uname -s | sed "y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/")
install:
# ensure source install works
- npm install --build-from-source
# test our module
- npm test
- node lib/opencv.js
# install dependencies first
- npm install
# build from source, run test and generate code coverage
- make cover
- NODE_OPENCV_DEBUG=true node lib/opencv.js
- docker build -t peterbraden/node-opencv-ubuntu-12-04 -f test/Dockerfile-ubuntu-12-04 .
- docker build -t peterbraden/node-opencv-ubuntu-14-04 -f test/Dockerfile-ubuntu-14-04 .
@ -81,3 +83,5 @@ script:
after_success:
# if success then query and display all published binaries
- node-pre-gyp info
# Upload coverage to codecov
- bash <(curl -s https://codecov.io/bash) -s coverage -f *.info

View File

@ -1,6 +1,45 @@
# Changelog
## 6.0.0
# Enhancements
- @wenq added `contour.moments` method.
- @andreasgal added `matrix.substract` method.
- @jainanshul added `matrix.mean` method.
- @idubinskiy restored `contour.points` method.
- @danschultzer updated node-pre-gyp to fix load of node-opencv in electron runtime.
- @andreasgal made `matrix.getData` work with RGB images.
- @Evilcat325 added `matrix.MatchTemplateByMatrix` method.
- @danschultzer added code coverage.
# Bug fixes
- @dominikdolancic fixed image load issue in `matrix.matchTemplate()`.
- @AwooOOoo fixed `type_info` errors in Visual Studio with std namespace pollution.
- @mvines fixed issue that prevented `AsyncSaveWorker` from using de-allocated memory.
- @mcwhittemore fixed dissimilarity example image load.
- @saoron fixed dead index.html documentup source.
- @andreasgal fixed an issue with `matrix.crop` (and potentially others), where `matrix.getData` ends up returning less than full matrix.
- @danschultzer fixed `examples/test.js` channel issue, and problematic Vec3b casting (instead of Vec3f) in `matrix.set`.
## Backwards incompatible changes
- @dxprog changed readImage to load image with `CV_LOAD_IMAGE_UNCHANGED` instead of `CV_LOAD_IMAGE_COLOR`. The latter returned the image as 3-channel.
- @danschultzer changed `VideoCapture.close` to `VideoCapture.release`.
Thanks to all, also a massive thanks to @danschultzer for helping get the open
tickets and PR's under control.
## 5.0.0 (Feb 9 2016)
- @mvines and @svogl started working on OpenCV 3.x support.
- @sirotenko added a getFrameCount method
- @vaceta implemented getFrameAt
- @jainanshul improved some methods
- @cascade256 improved the windows build
Plus fixes from @banterability, @punnerud, @vargad etc. Thanks all.
## 4.0.0
I've been super slow releasing this one, and there's a ton of new stuff.

View File

@ -68,3 +68,4 @@ Ordered by date of first contribution. [Auto-generated](https://github.com/xingr
- [vyacheslav](https://github.com/vyacheslav-lonschakov)
- vyacheslav
- [Harold Ozouf](https://github.com/jspdown)
- [Dan Schultzer](https://github.com/danschultzer)

View File

@ -4,16 +4,80 @@
# 2) Build: wget https://raw.github.com/dotcloud/docker/v0.1.6/contrib/docker-build/docker-build && python docker-build $USER/node-opencv < Dockerfile
# 3) Test: docker run $USER/node-opencv node -e "console.log(require('opencv').version)"
#
# VERSION 0.2
# VERSION 0.3
# DOCKER-VERSION 8.1.2
# update to 14.04
from ubuntu:14.04
run apt-get update -qq
run apt-get install -y software-properties-common python-software-properties
run add-apt-repository -y ppa:kubuntu-ppa/backports
run apt-get update
run apt-get install -y libcv-dev libcvaux-dev libhighgui-dev libopencv-dev
run curl -sL https://deb.nodesource.com/setup | bash -
run apt-get install -y nodejs
run npm install opencv || cat npm-debug.log
FROM ubuntu:14.04
# listing myself as maintainer of _this_ Dockerfile, though I am not the author of the install script (credit to http://rodrigoberriel.com/)
MAINTAINER borromeotlhs@gmail.com
# run Rodrigo Berriels script for installing opencv3 on Ubuntu 14.04
# Ill convert this into a full Dockerfile later, once I see if it works
#COPY ./install-opencv3.sh /tmp/
# this is needed as libfaac-dev comes from multiverse, according to:
# http://superuser.com/questions/467774/how-to-install-libfaac-dev
RUN echo "deb http://us.archive.ubuntu.com/ubuntu/ precise multiverse\n\
deb-src http://us.archive.ubuntu.com/ubuntu/ precise multiverse\n\
deb http://us.archive.ubuntu.com/ubuntu/ precise-updates multiverse\n\
deb-src http://us.archive.ubuntu.com/ubuntu/ precise-updates multiverse\n"\
>> /etc/apt/sources.list
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y \
software-properties-common
RUN add-apt-repository ppa:george-edison55/cmake-3.x
RUN apt-get update -qq
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y \
curl \
cmake \
wget \
unzip \
libopencv-dev \
build-essential \
git \
libgtk2.0-dev \
pkg-config \
python-dev \
python-numpy \
libdc1394-22 \
libdc1394-22-dev \
libjpeg-dev \
libpng12-dev \
libtiff4-dev \
libjasper-dev \
libavcodec-dev \
libavformat-dev \
libswscale-dev \
libxine-dev \
libgstreamer0.10-dev \
libgstreamer-plugins-base0.10-dev \
libv4l-dev \
libtbb-dev \
libqt4-dev \
libfaac-dev \
libmp3lame-dev \
libopencore-amrnb-dev \
libopencore-amrwb-dev \
libtheora-dev \
libvorbis-dev \
libxvidcore-dev \
x264 \
v4l-utils
RUN mkdir opencv
WORKDIR opencv
RUN wget https://github.com/Itseez/opencv/archive/3.0.0.zip -O opencv-3.0.0.zip
RUN unzip opencv-3.0.0.zip
RUN mkdir opencv-3.0.0/build
WORKDIR opencv-3.0.0/build
RUN cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -D WITH_TBB=ON -D BUILD_NEW_PYTHON_SUPPORT=ON -D WITH_V4L=ON -D WITH_OPENGL=ON ..
RUN make -j $(nproc) && make install
RUN echo "/usr/local/lib" > /etc/ld.so.conf.d/opencv.conf
RUN ldconfig

View File

@ -39,3 +39,63 @@ travis-build:
docker build -t peterbraden/node-opencv-ubuntu-12-04 -f test/Dockerfile-ubuntu-12-04 .
docker build -t peterbraden/node-opencv-ubuntu-14-04 -f test/Dockerfile-ubuntu-14-04 .
.PHONY: travis-build
# Below build, coverage and clean tasks were partly lifted from https://github.com/geo-data/node-mapserv/blob/e99b23a44d910d444f5a45d144859758f820e1d1/Makefile
# @author danschultzer
# The location of the `istanbul` JS code coverage framework. Try and get a
# globally installed version, falling back to a local install.
ISTANBUL := $(shell which istanbul)
ifeq ($(ISTANBUL),)
ISTANBUL = ./node_modules/.bin/istanbul/lib/cli.js
endif
# The location of the `node-pre-gyp` module builder. Try and get a globally
# installed version, falling back to a local install.
NODE_PRE_GYP = $(shell which node-pre-gyp)
ifeq ($(NODE_GYP),)
NODE_PRE_GYP = ./node_modules/.bin/node-pre-gyp
endif
NODE := $(shell which node)
test_deps = build \
./test/*.js \
./lib/*.js \
$(NODE)
build: build/Debug/opencv.node
build/Debug/opencv.node:
$(NODE_PRE_GYP) --verbose --debug rebuild
# Perform the code coverage
cover: coverage/index.html
coverage/index.html: coverage/node-opencv.info
genhtml --output-directory coverage coverage/node-opencv.info
@echo "\033[0;32mPoint your browser at \`coverage/index.html\`\033[m\017"
coverage/node-opencv.info: coverage/bindings.info
lcov --test-name node-opencv \
--add-tracefile coverage/lcov.info \
--add-tracefile coverage/bindings.info \
--output-file coverage/node-opencv.info
coverage/bindings.info: coverage/addon.info
lcov --extract coverage/addon.info '*opencv/src/*' --output-file coverage/bindings.info
coverage/addon.info: coverage/lcov.info
lcov --capture --base-directory build/ --directory . --output-file coverage/addon.info
# This generates the JS lcov info as well as gcov `*.gcda` files:
coverage/lcov.info: $(test_deps) $(ISTANBUL)
NODE_OPENCV_DEBUG=true $(NODE) --nouse_idle_notification --expose-gc \
$(ISTANBUL) cover --report lcovonly -- test/unit.js
$(NODE_PRE_GYP):
npm install node-pre-gyp
$(ISTANBUL): package.json
npm install istanbul
@touch $(ISTANBUL)
# Clean up any generated files
clean: $(NODE_PRE_GYP)
$(NODE_PRE_GYP) clean
rm -rf coverage
rm -rf build

View File

@ -1,7 +1,7 @@
# node-opencv
[![Build Status](https://secure.travis-ci.org/peterbraden/node-opencv.png)](http://travis-ci.org/peterbraden/node-opencv)
[![Coverage](http://codecov.io/github/peterbraden/node-opencv/coverage.svg?branch=master)](https://codecov.io/gh/peterbraden/node-opencv)
[OpenCV](http://opencv.org) bindings for Node.js. OpenCV is
the defacto computer vision library - by interfacing with it natively in node,
@ -13,44 +13,31 @@ cool, I'd love to hear about it!
## Install
You'll need OpenCV 2.3.1 or newer installed before installing node-opencv.
You'll need OpenCV 2.3.1 or newer installed before installing node-opencv. Note
that OpenCV 3.x is not yet fully supported.
## Specific for Windows
1. Download Install opencv @ - (I used version 2.4.4)
1. Download and install OpenCV (Be sure to use a 2.4 version) @
http://opencv.org/downloads.html
Put it in c:\opencv
For these instructions we will assume OpenCV is put at C:\OpenCV, but you can
adjust accordingly.
2. Install python version 2.7 @
http://www.python.org/download/releases/2.7/
put it in c:\python27
2. If you haven't already, create a system variable called OPENCV_DIR and set it
to C:\OpenCV\build\x64\vc12
3. install pkg-config by downloading the all in one bundle @ - (I used Gtk+ 3.6.4)
http://www.gtk.org/download/win64.php
put it in c:\pkg-config
Make sure the "x64" part matches the version of NodeJS you are using.
4. Add the following to your path variables
C:\pkg-config\bin;C:\OpenCV\build\x64\vc11\bin;
Also add the following to your system PATH
;%OPENCV_DIR%\bin
5. Install visual-studio in 4 steps
3. Install Visual Studio 2013. Make sure to get the C++ components.
You can use a different edition, just make sure OpenCV supports it, and you
set the "vcxx" part of the variables above to match.
- install Visual C++ 2010 Express
- install Windows SDK for windows 7 and .net framework 4
- install Visual Studio 2010 Service Pack 1
- install Visual C++ 2010 Service Pack 1 Compiler
6. Download npeterbraden/node-opencv fork
4. Download peterbraden/node-opencv fork
git clone https://github.com/peterbraden/node-opencv
7. edit file src/Matrix.cpp
put "inline double round( double d ) { return floor( d + 0.5);}" below "cv::Rect* setRect(Local<Object> objRect, cv::Rect &result);"
8. run npm install
Then:
5. run npm install
```bash
$ npm install opencv
@ -176,7 +163,7 @@ im.line([x1,y1], [x2, y2])
#### Object Detection
There is a shortcut method for
[Viola-Jones Haar Cascade](http://www.cognotics.com/opencv/servo_2007_series/part_2/sidebar.html) object
[Viola-Jones Haar Cascade](http://docs.opencv.org/trunk/d7/d8b/tutorial_py_face_detection.html) object
detection. This can be used for face detection etc.
```javascript
@ -206,7 +193,7 @@ functions for accessing, computing with, and altering the contours contained in
See [relevant source code](src/Contours.cc) and [examples](examples/)
```javascript
var contours = im.findContours;
var contours = im.findContours();
// Count of contours in the Contours object
contours.size();
@ -236,7 +223,20 @@ contours.approxPolyDP(index, epsilon, isClosed);
contours.convexHull(index, clockwise);
```
## Test
Using [tape](https://github.com/substack/tape). Run with command:
`npm test`.
## Code coverage
Using [istanbul](http://gotwarlost.github.io/istanbul/) and [lcov](http://ltp.sourceforge.net/coverage/lcov.php). Run with command:
`make cover`
Build version of `opencv.node` will be generated, and coverage files will be put in `coverage/` directory. These files can be remvoved automatically by running `make clean`.
## MIT License
The library is distributed under the MIT License - if for some reason that
doesn't work for you please get in touch.

View File

@ -24,12 +24,12 @@
],
"libraries": [
"<!@(pkg-config --libs opencv)"
"<!@(node utils/find-opencv.js --libs)"
],
# For windows
"include_dirs": [
"<!@(pkg-config --cflags opencv)",
"<!@(node utils/find-opencv.js --cflags)",
"<!(node -e \"require('nan')\")"
],
@ -37,17 +37,19 @@
"cflags_cc!": [ "-fno-rtti", "-fno-exceptions"],
"conditions": [
[ "OS==\"linux\"", {
[ "OS==\"linux\" or OS==\"freebsd\" or OS==\"openbsd\" or OS==\"solaris\" or OS==\"aix\"", {
"cflags": [
"<!@(pkg-config --cflags \"opencv >= 2.3.1\" )",
"<!@(node utils/find-opencv.js --cflags)",
"-Wall"
]
}],
[ "OS==\"win\"", {
"cflags": [
"<!@(pkg-config --cflags \"opencv >= 2.4.9\" )",
"-Wall"
],
"defines": [
"WIN"
],
"msvs_settings": {
"VCCLCompilerTool": {
"ExceptionHandling": "2",
@ -62,7 +64,88 @@
"-mmacosx-version-min=10.7",
"-std=c++11",
"-stdlib=libc++",
"<!@(pkg-config --cflags opencv)"
"<!@(node utils/find-opencv.js --cflags)",
],
"GCC_ENABLE_CPP_RTTI": "YES",
"GCC_ENABLE_CPP_EXCEPTIONS": "YES"
}
}
]
],
"configurations": {
# This is used for generating code coverage with the `--debug` argument
"Debug": {
"conditions": [
['OS=="linux"', {
"cflags": ["-coverage"],
"ldflags": ["-coverage"]
}],
['OS=="mac"', {
"xcode_settings": {
"OTHER_CFLAGS": [
"-fprofile-arcs -ftest-coverage",
],
"OTHER_LDFLAGS": [
"--coverage"
]
}
}]
]
},
}
},
{
"target_name": "test_nativemat",
"sources": [
"test/nativemat.cc",
],
"libraries": [
"<!@(node utils/find-opencv.js --libs)",
],
# For windows
"include_dirs": [
"<!@(node utils/find-opencv.js --cflags)",
"<!(node -e \"require('nan')\")",
"<!(node -e \"require('./include_dirs')\")"
],
"cflags!" : [ "-fno-exceptions"],
"cflags_cc!": [ "-fno-rtti", "-fno-exceptions"],
"conditions": [
[ "OS==\"linux\"", {
"cflags": [
"<!@(node utils/find-opencv.js --cflags)",
"-Wall"
]
}],
[ "OS==\"win\"", {
"cflags": [
"-Wall"
],
"defines": [
"WIN"
],
"msvs_settings": {
"VCCLCompilerTool": {
"ExceptionHandling": "2",
"DisableSpecificWarnings": [ "4530", "4506", "4244" ],
},
}
}],
[ # cflags on OS X are stupid and have to be defined like this
"OS==\"mac\"", {
"xcode_settings": {
"OTHER_CFLAGS": [
"-mmacosx-version-min=10.7",
"-std=c++11",
"-stdlib=libc++",
"<!@(node utils/find-opencv.js --cflags)",
],
"GCC_ENABLE_CPP_RTTI": "YES",
"GCC_ENABLE_CPP_EXCEPTIONS": "YES"

View File

@ -1,14 +1,14 @@
var cv = require('../lib/opencv');
cv.readImage("./examples/files/mona.png", function(err, orig) {
cv.readImage("./files/mona.png", function(err, orig) {
if (err) throw err;
cv.readImage("./examples/files/over_text.png", function(err, over_text) {
cv.readImage("./files/over_text.png", function(err, over_text) {
if (err) throw err;
var result = new cv.Matrix(orig.width(), orig.height());
result.addWeighted(orig, 0.7, over_text, 0.9);
result.save("./examples/tmp/weighted.png");
console.log('Image saved to ./examples/tmp/weighted.png');
result.save("./tmp/weighted.png");
console.log('Image saved to ./tmp/weighted.png');
});
});

View File

@ -19,19 +19,22 @@ cv.readImage('./files/stuff.png', function(err, im) {
var all = new cv.Matrix(height, width);
im.convertGrayscale();
im_canny = im.copy();
var im_canny = im.copy();
im_canny.canny(lowThresh, highThresh);
im_canny.dilate(nIters);
contours = im_canny.findContours();
var contours = im_canny.findContours();
const lineType = 8;
const maxLevel = 0;
const thickness = 1;
for(i = 0; i < contours.size(); i++) {
if(contours.area(i) > maxArea) {
var moments = contours.moments(i);
var cgx = Math.round(moments.m10 / moments.m00);
var cgy = Math.round(moments.m01 / moments.m00);
big.drawContour(contours, i, GREEN);
big.drawContour(contours, i, GREEN, thickness, lineType, maxLevel, [0, 0]);
big.line([cgx - 5, cgy], [cgx + 5, cgy], RED);
big.line([cgx, cgy - 5], [cgx, cgy + 5], RED);
}

View File

@ -1,9 +1,14 @@
var cv = require('../lib/opencv');
cv.readImage("./examples/files/car1.jpg", function(err, car1) {
if (cv.ImageSimilarity === undefined) {
console.log('TODO: Please port Features2d.cc to OpenCV 3')
process.exit(0);
}
cv.readImage("./files/car1.jpg", function(err, car1) {
if (err) throw err;
cv.readImage("./examples/files/car2.jpg", function(err, car2) {
cv.readImage("./files/car2.jpg", function(err, car2) {
if (err) throw err;
cv.ImageSimilarity(car1, car2, function (err, dissimilarity) {

Binary file not shown.

After

Width:  |  Height:  |  Size: 815 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 B

Binary file not shown.

BIN
examples/files/opencv.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

22
examples/mat-dct.js Normal file
View File

@ -0,0 +1,22 @@
var cv = require('../lib/opencv');
cv.readImage("./files/mona.png", function(err, orig) {
if (err) throw err;
var chan1 = orig.split()[0];
var floatInputMatrix = new cv.Matrix();
chan1.convertTo(floatInputMatrix, cv.Constants.CV_32F)
var foatAfterDct = floatInputMatrix.dct();
// for inverse dct, set argument to "true"
var afterDoubleDct = foatAfterDct.dct(true);
var intOutImage = new cv.Matrix();
afterDoubleDct.convertTo(intOutImage, cv.Constants.CV_8U);
intOutImage.save("./tmp/dct.png");
console.log('Image saved to ./tmp/dct.png');
});

View File

@ -1,6 +1,5 @@
var cv = require('../lib/opencv');
var mat = new cv.Matrix(1, 2, cv.Constants.CV_8U, [1]);
var mat = new cv.Matrix(1, 2, cv.Constants.CV_8UC3, [1]);
var row = mat.pixelRow(0);
console.log("mat: " + row[0] + row[1]);

28
inc/Matrix.h Executable file
View File

@ -0,0 +1,28 @@
/*
This file defines the public native interface into an node-opencv Matrix
object. This is used to retrieve the wrapped OpenCV cv:Mat object from other
native code:
NAN_METHOD(UnwrapMatrix) {
cv::Mat mat = Nan::ObjectWrap::Unwrap<node_opencv::Matrix>(info[0]->ToObject())->mat;
// ...
}
*/
#ifndef NODE_OPENCV_MATRIX_H
#define NODE_OPENCV_MATRIX_H
#include <opencv/cv.h>
#include <node_object_wrap.h>
namespace node_opencv {
class Matrix: public Nan::ObjectWrap {
public:
cv::Mat mat;
protected:
Matrix(): Nan::ObjectWrap() {};
};
}
#endif // NODE_OPENCV_MATRIX_H

14
include_dirs.js Normal file
View File

@ -0,0 +1,14 @@
// Outputs the path to public node-opencv header files. This is used when
// building other native node modules that require access to the
// node-opencv Matrix base class.
//
// To use this file, add something like the following to your binding.gyp:
//
// "include_dirs": [
// "<!@(pkg-config --cflags opencv)",
// "<!(node -e \"require('nan')\")",
// "<!(node -e \"require('opencv/include_dirs')\")"
// ],
//
var path = require('path');
console.log(path.relative('.', path.join(__dirname, 'inc')));

View File

@ -2,7 +2,7 @@
<html>
<head>
<title></title>
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/documentup/latest.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/documentup/0.1.1/documentup.min.js"></script>
<script type="text/javascript">
DocumentUp.document("peterbraden/node-opencv");
</script>

View File

@ -1,6 +1,6 @@
var binary = require('node-pre-gyp');
var path = require('path');
var binding_path = binary.find(path.resolve(path.join(__dirname,'../package.json')));
var binding_path = binary.find(path.resolve(path.join(__dirname,'../package.json')), { debug: !!process.env.NODE_OPENCV_DEBUG });
var binding = require(binding_path);
//module.exports = require('../build/Release/opencv.node');

View File

@ -1,12 +1,13 @@
{
"name": "opencv",
"version": "4.0.0",
"version": "6.0.0",
"description": "Node Bindings to OpenCV",
"author": "Peter Braden <peterbraden@peterbraden.co.uk>",
"dependencies": {
"buffers": "^0.1.1",
"istanbul": "0.4.5",
"nan": "^2.0.9",
"node-pre-gyp": "^0.6.11"
"node-pre-gyp": "^0.6.30"
},
"devDependencies": {
"tape": "^3.0.0",

View File

@ -3,7 +3,11 @@
#include <iostream>
#include <nan.h>
#if ((CV_MAJOR_VERSION >= 2) && (CV_MINOR_VERSION >=4))
#if CV_MAJOR_VERSION >= 3
#warning TODO: port me to OpenCV 3
#endif
#if ((CV_MAJOR_VERSION == 2) && (CV_MINOR_VERSION >=4))
Nan::Persistent<FunctionTemplate> BackgroundSubtractorWrap::constructor;

View File

@ -1,6 +1,6 @@
#include "OpenCV.h"
#if ((CV_MAJOR_VERSION >= 2) && (CV_MINOR_VERSION >=4))
#if ((CV_MAJOR_VERSION == 2) && (CV_MINOR_VERSION >=4))
#include <opencv2/video/background_segm.hpp>

View File

@ -3,6 +3,10 @@
#include "OpenCV.h"
#if CV_MAJOR_VERSION >= 3
#include <opencv2/calib3d.hpp>
#endif
/**
* Implementation of calib3d.hpp functions
*/

View File

@ -2,6 +2,9 @@
#include "OpenCV.h"
#include "Matrix.h"
#if CV_MAJOR_VERSION >= 3
#include <opencv2/video/tracking.hpp>
#endif
#define CHANNEL_HUE 0
#define CHANNEL_SATURATION 1

View File

@ -1,4 +1,7 @@
#include "OpenCV.h"
#if CV_MAJOR_VERSION >= 3
#include <opencv2/objdetect.hpp>
#endif
class CascadeClassifierWrap: public Nan::ObjectWrap {
public:

View File

@ -4,6 +4,9 @@
#define CONST(C) \
obj->Set(Nan::New<String>(#C).ToLocalChecked(), Nan::New<Integer>(C));
#define CONST_INT(C) \
obj->Set(Nan::New<String>(#C).ToLocalChecked(), Nan::New<Integer>((int)C));
#define CONST_DOUBLE(C) \
obj->Set(Nan::New<String>(#C).ToLocalChecked(), Nan::New<Number>(C));
@ -62,6 +65,13 @@ void Constants::Init(Local<Object> target) {
CONST_DOUBLE(CV_PI);
CONST(CV_FILLED);
CONST_ENUM(BORDER_DEFAULT);
CONST_ENUM(BORDER_REPLICATE);
CONST_ENUM(BORDER_REFLECT);
CONST_ENUM(BORDER_REFLECT_101);
CONST_ENUM(BORDER_WRAP);
CONST_ENUM(BORDER_CONSTANT);
CONST_ENUM(INTER_NEAREST);
CONST_ENUM(INTER_LINEAR);
CONST_ENUM(INTER_AREA);
@ -78,6 +88,19 @@ void Constants::Init(Local<Object> target) {
CONST_ENUM(NORM_RELATIVE);
CONST_ENUM(NORM_TYPE_MASK);
CONST_ENUM(RETR_EXTERNAL);
CONST_ENUM(RETR_LIST);
CONST_ENUM(RETR_CCOMP);
CONST_ENUM(RETR_TREE);
CONST_INT(CV_DIST_C);
CONST_INT(CV_DIST_L1);
CONST_INT(CV_DIST_L2);
CONST_INT(CV_DIST_MASK_3);
CONST_INT(CV_DIST_MASK_5);
CONST_INT(CV_DIST_MASK_PRECISE);
target->Set(Nan::New("Constants").ToLocalChecked(), obj);
}

View File

@ -18,6 +18,7 @@ void Contour::Init(Local<Object> target) {
// Prototype
// Local<ObjectTemplate> proto = constructor->PrototypeTemplate();
Nan::SetPrototypeMethod(ctor, "point", Point);
Nan::SetPrototypeMethod(ctor, "points", Points);
Nan::SetPrototypeMethod(ctor, "size", Size);
Nan::SetPrototypeMethod(ctor, "cornerCount", CornerCount);
Nan::SetPrototypeMethod(ctor, "area", Area);
@ -75,7 +76,7 @@ NAN_METHOD(Contour::Points) {
Contour *self = Nan::ObjectWrap::Unwrap<Contour>(info.This());
int pos = info[0]->NumberValue();
vector<cv::Point> points = self->contours[pos];
std::vector<cv::Point> points = self->contours[pos];
Local<Array> data = Nan::New<Array>(points.size());
for (std::vector<int>::size_type i = 0; i != points.size(); i++) {
@ -114,9 +115,10 @@ NAN_METHOD(Contour::Area) {
Contour *self = Nan::ObjectWrap::Unwrap<Contour>(info.This());
int pos = info[0]->NumberValue();
bool orientation = (info.Length() > 1 && info[1]->BooleanValue());
// info.GetReturnValue().Set(Nan::New<Number>(contourArea(self->contours)));
info.GetReturnValue().Set(Nan::New<Number>(contourArea(cv::Mat(self->contours[pos]))));
info.GetReturnValue().Set(Nan::New<Number>(contourArea(cv::Mat(self->contours[pos]), orientation)));
}
NAN_METHOD(Contour::ArcLength) {
@ -295,7 +297,7 @@ NAN_METHOD(Contour::Serialize) {
Local<Array> contours_data = Nan::New<Array>(self->contours.size());
for (std::vector<int>::size_type i = 0; i != self->contours.size(); i++) {
vector<cv::Point> points = self->contours[i];
std::vector<cv::Point> points = self->contours[i];
Local<Array> contour_data = Nan::New<Array>(points.size());
for (std::vector<int>::size_type j = 0; j != points.size(); j++) {
@ -336,12 +338,12 @@ NAN_METHOD(Contour::Deserialize) {
Local<Array> contours_data = Local<Array>::Cast(data->Get(Nan::New<String>("contours").ToLocalChecked()));
Local<Array> hierarchy_data = Local<Array>::Cast(data->Get(Nan::New<String>("hierarchy").ToLocalChecked()));
vector<vector<cv::Point> > contours_res;
std::vector<std::vector<cv::Point> > contours_res;
int contours_length = contours_data->Length();
for (int i = 0; i < contours_length; i++) {
Local<Array> contour_data = Local<Array>::Cast(contours_data->Get(i));
vector<cv::Point> points;
std::vector<cv::Point> points;
int contour_length = contour_data->Length();
for (int j = 0; j < contour_length; j++) {
@ -354,7 +356,7 @@ NAN_METHOD(Contour::Deserialize) {
contours_res.push_back(points);
}
vector<cv::Vec4i> hierarchy_res;
std::vector<cv::Vec4i> hierarchy_res;
int hierarchy_length = hierarchy_data->Length();
for (int i = 0; i < hierarchy_length; i++) {

View File

@ -1,12 +1,11 @@
#include "OpenCV.h"
using namespace std;
class Contour: public Nan::ObjectWrap {
public:
cv::Mat mat;
vector<vector<cv::Point> > contours;
vector<cv::Vec4i> hierarchy;
std::vector<std::vector<cv::Point> > contours;
std::vector<cv::Vec4i> hierarchy;
static Nan::Persistent<FunctionTemplate> constructor;
static void Init(Local<Object> target);

View File

@ -1,11 +1,19 @@
#include "FaceRecognizer.h"
#include "OpenCV.h"
#if ((CV_MAJOR_VERSION >= 2) && (CV_MINOR_VERSION >=4) && (CV_SUBMINOR_VERSION>=4))
#ifdef HAVE_OPENCV_FACE
#include "FaceRecognizer.h"
#include "Matrix.h"
#include <nan.h>
#if CV_MAJOR_VERSION >= 3
namespace cv {
using std::vector;
using cv::face::createEigenFaceRecognizer;
using cv::face::createFisherFaceRecognizer;
using cv::face::createLBPHFaceRecognizer;
}
#endif
#define EIGEN 0
#define LBPH 1
#define FISHER 2
@ -274,6 +282,17 @@ NAN_METHOD(FaceRecognizerWrap::PredictSync) {
double confidence = 0.0;
self->rec->predict(im, predictedLabel, confidence);
#if CV_MAJOR_VERSION >= 3
// Older versions of OpenCV3 incorrectly returned label=0 at
// confidence=DBL_MAX instead of label=-1 on failure. This can be removed
// once the fix* becomes more widespread.
//
// * https://github.com/Itseez/opencv_contrib/commit/0aa58ae9b30a017b356a86d29453c0b56ed9e625#diff-d9c561bf45c255c5951ff1ab55e80473
if (predictedLabel == 0 && confidence == DBL_MAX) {
predictedLabel = -1;
}
#endif
v8::Local<v8::Object> res = Nan::New<Object>();
res->Set(Nan::New("id").ToLocalChecked(), Nan::New<Number>(predictedLabel));
res->Set(Nan::New("confidence").ToLocalChecked(), Nan::New<Number>(confidence));
@ -296,6 +315,16 @@ public:
void Execute() {
this->rec->predict(this->im, this->predictedLabel, this->confidence);
#if CV_MAJOR_VERSION >= 3
// Older versions of OpenCV3 incorrectly returned label=0 at
// confidence=DBL_MAX instead of label=-1 on failure. This can be removed
// once the fix* becomes more widespread.
//
// * https://github.com/Itseez/opencv_contrib/commit/0aa58ae9b30a017b356a86d29453c0b56ed9e625#diff-d9c561bf45c255c5951ff1ab55e80473
if (this->predictedLabel == 0 && this->confidence == DBL_MAX) {
this->predictedLabel = -1;
}
#endif
}
void HandleOKCallback() {
@ -369,7 +398,27 @@ NAN_METHOD(FaceRecognizerWrap::GetMat) {
JSTHROW("getMat takes a key")
}
std::string key = std::string(*Nan::Utf8String(info[0]->ToString()));
cv::Mat m = self->rec->getMat(key);
cv::Mat m;
#if CV_MAJOR_VERSION >= 3
cv::face::BasicFaceRecognizer *bfr =
dynamic_cast<cv::face::BasicFaceRecognizer*>(self->rec.get());
if (bfr == NULL) {
Nan::ThrowTypeError("getMat not supported");
return;
}
if (key.compare("mean") == 0) {
m = bfr->getMean();
} else if (key.compare("eigenvectors") == 0) {
m = bfr->getEigenVectors();
} else if (key.compare("eigenvalues") == 0) {
m = bfr->getEigenValues();
} else {
Nan::ThrowTypeError("Unknown getMat keyname");
return;
}
#else
m = self->rec->getMat(key);
#endif
Local<Object> im = Nan::New(Matrix::constructor)->GetFunction()->NewInstance();
Matrix *img = Nan::ObjectWrap::Unwrap<Matrix>(im);

View File

@ -1,8 +1,15 @@
#include "OpenCV.h"
#if ((CV_MAJOR_VERSION >= 2) && (CV_MINOR_VERSION >=4))
#ifdef HAVE_OPENCV_FACE
#if CV_MAJOR_VERSION >= 3
#include <opencv2/face.hpp>
namespace cv {
using cv::face::FaceRecognizer;
}
#else
#include "opencv2/contrib/contrib.hpp"
#endif
class FaceRecognizerWrap: public Nan::ObjectWrap {
public:

View File

@ -1,10 +1,11 @@
#include "OpenCV.h"
#if ((CV_MAJOR_VERSION == 2) && (CV_MINOR_VERSION >=4))
#include "Features2d.h"
#include "Matrix.h"
#include <nan.h>
#include <stdio.h>
#if ((CV_MAJOR_VERSION >= 2) && (CV_MINOR_VERSION >=4))
void Features::Init(Local<Object> target) {
Nan::HandleScope scope;

View File

@ -1,6 +1,6 @@
#include "OpenCV.h"
#if ((CV_MAJOR_VERSION >= 2) && (CV_MINOR_VERSION >=4))
#if ((CV_MAJOR_VERSION == 2) && (CV_MINOR_VERSION >=4))
#include <opencv2/core/core.hpp>
#include <opencv2/features2d/features2d.hpp>

View File

@ -9,11 +9,44 @@ void ImgProc::Init(Local<Object> target) {
Nan::SetMethod(obj, "undistort", Undistort);
Nan::SetMethod(obj, "initUndistortRectifyMap", InitUndistortRectifyMap);
Nan::SetMethod(obj, "remap", Remap);
Nan::SetMethod(obj, "distanceTransform", DistanceTransform);
Nan::SetMethod(obj, "getStructuringElement", GetStructuringElement);
target->Set(Nan::New("imgproc").ToLocalChecked(), obj);
}
// cv::distanceTransform
NAN_METHOD(ImgProc::DistanceTransform) {
Nan::EscapableHandleScope scope;
try {
// Arg 0 is the image
Matrix* m0 = Nan::ObjectWrap::Unwrap<Matrix>(info[0]->ToObject());
cv::Mat inputImage = m0->mat;
// Arg 1 is the distance type (CV_DIST_L1, CV_DIST_L2, etc.)
int distType = info[1]->IntegerValue();;
// Make a mat to hold the result image
cv::Mat outputImage;
// Perform distance transform
cv::distanceTransform(inputImage, outputImage, distType, 0);
// Wrap the output image
Local<Object> outMatrixWrap = Nan::New(Matrix::constructor)->GetFunction()->NewInstance();
Matrix *outMatrix = Nan::ObjectWrap::Unwrap<Matrix>(outMatrixWrap);
outMatrix->mat = outputImage;
// Return the output image
info.GetReturnValue().Set(outMatrixWrap);
} catch (cv::Exception &e) {
const char *err_msg = e.what();
Nan::ThrowError(err_msg);
return;
}
}
// cv::undistort
NAN_METHOD(ImgProc::Undistort) {
Nan::EscapableHandleScope scope;

View File

@ -9,6 +9,7 @@
class ImgProc: public Nan::ObjectWrap {
public:
static void Init(Local<Object> target);
static NAN_METHOD(DistanceTransform);
static NAN_METHOD(Undistort);
static NAN_METHOD(InitUndistortRectifyMap);
static NAN_METHOD(Remap);

View File

@ -1,8 +1,11 @@
#include "LDAWrap.h"
#include "OpenCV.h"
#if ((CV_MAJOR_VERSION >= 2) && (CV_MINOR_VERSION >=4) && (CV_SUBMINOR_VERSION>=4))
#if CV_MAJOR_VERSION >= 3
#warning TODO: port me to OpenCV 3
#endif
#if ((CV_MAJOR_VERSION == 2) && (CV_MINOR_VERSION >=4) && (CV_SUBMINOR_VERSION>=4))
#include "LDAWrap.h"
#include "Matrix.h"
#include <nan.h>
@ -17,8 +20,8 @@ void LDAWrap::Init(Local<Object> target) {
ctor->InstanceTemplate()->SetInternalFieldCount(1);
ctor->SetClassName(Nan::New("LDA").ToLocalChecked());
Nan::SetPrototypeMethod(ctor, "subspaceProject", SubspaceProject);
Nan::SetPrototypeMethod(ctor, "subspaceReconstruct", SubspaceReconstruct);
Nan::SetMethod(ctor, "subspaceProject", SubspaceProject);
Nan::SetMethod(ctor, "subspaceReconstruct", SubspaceReconstruct);
target->Set(Nan::New("LDA").ToLocalChecked(), ctor->GetFunction());
};

View File

@ -1,6 +1,6 @@
#include "OpenCV.h"
#if ((CV_MAJOR_VERSION >= 2) && (CV_MINOR_VERSION >=4))
#if ((CV_MAJOR_VERSION == 2) && (CV_MINOR_VERSION >=4))
#include "opencv2/contrib/contrib.hpp"

View File

@ -35,6 +35,7 @@ void Matrix::Init(Local<Object> target) {
Nan::SetPrototypeMethod(ctor, "pixel", Pixel);
Nan::SetPrototypeMethod(ctor, "width", Width);
Nan::SetPrototypeMethod(ctor, "height", Height);
Nan::SetPrototypeMethod(ctor, "type", Type);
Nan::SetPrototypeMethod(ctor, "size", Size);
Nan::SetPrototypeMethod(ctor, "clone", Clone);
Nan::SetPrototypeMethod(ctor, "crop", Crop);
@ -48,7 +49,6 @@ void Matrix::Init(Local<Object> target) {
Nan::SetPrototypeMethod(ctor, "saveAsync", SaveAsync);
Nan::SetPrototypeMethod(ctor, "resize", Resize);
Nan::SetPrototypeMethod(ctor, "rotate", Rotate);
Nan::SetPrototypeMethod(ctor, "getRotationMatrix2D", GetRotationMatrix2D);
Nan::SetPrototypeMethod(ctor, "warpAffine", WarpAffine);
Nan::SetPrototypeMethod(ctor, "copyTo", CopyTo);
Nan::SetPrototypeMethod(ctor, "convertTo", ConvertTo);
@ -60,16 +60,21 @@ void Matrix::Init(Local<Object> target) {
Nan::SetPrototypeMethod(ctor, "gaussianBlur", GaussianBlur);
Nan::SetPrototypeMethod(ctor, "medianBlur", MedianBlur);
Nan::SetPrototypeMethod(ctor, "bilateralFilter", BilateralFilter);
Nan::SetPrototypeMethod(ctor, "sobel", Sobel);
Nan::SetPrototypeMethod(ctor, "copy", Copy);
Nan::SetPrototypeMethod(ctor, "flip", Flip);
Nan::SetPrototypeMethod(ctor, "roi", ROI);
Nan::SetPrototypeMethod(ctor, "ptr", Ptr);
Nan::SetPrototypeMethod(ctor, "absDiff", AbsDiff);
Nan::SetPrototypeMethod(ctor, "dct", Dct);
Nan::SetPrototypeMethod(ctor, "idct", Idct);
Nan::SetPrototypeMethod(ctor, "addWeighted", AddWeighted);
Nan::SetPrototypeMethod(ctor, "add", Add);
Nan::SetPrototypeMethod(ctor, "bitwiseXor", BitwiseXor);
Nan::SetPrototypeMethod(ctor, "bitwiseNot", BitwiseNot);
Nan::SetPrototypeMethod(ctor, "bitwiseAnd", BitwiseAnd);
Nan::SetPrototypeMethod(ctor, "countNonZero", CountNonZero);
Nan::SetPrototypeMethod(ctor, "moments", Moments);
Nan::SetPrototypeMethod(ctor, "canny", Canny);
Nan::SetPrototypeMethod(ctor, "dilate", Dilate);
Nan::SetPrototypeMethod(ctor, "erode", Erode);
@ -78,7 +83,6 @@ void Matrix::Init(Local<Object> target) {
Nan::SetPrototypeMethod(ctor, "drawAllContours", DrawAllContours);
Nan::SetPrototypeMethod(ctor, "goodFeaturesToTrack", GoodFeaturesToTrack);
Nan::SetPrototypeMethod(ctor, "houghLinesP", HoughLinesP);
Nan::SetPrototypeMethod(ctor, "crop", Crop);
Nan::SetPrototypeMethod(ctor, "houghCircles", HoughCircles);
Nan::SetPrototypeMethod(ctor, "inRange", inRange);
Nan::SetPrototypeMethod(ctor, "adjustROI", AdjustROI);
@ -92,6 +96,7 @@ void Matrix::Init(Local<Object> target) {
Nan::SetPrototypeMethod(ctor, "equalizeHist", EqualizeHist);
Nan::SetPrototypeMethod(ctor, "floodFill", FloodFill);
Nan::SetPrototypeMethod(ctor, "matchTemplate", MatchTemplate);
Nan::SetPrototypeMethod(ctor, "matchTemplateByMatrix", MatchTemplateByMatrix);
Nan::SetPrototypeMethod(ctor, "templateMatches", TemplateMatches);
Nan::SetPrototypeMethod(ctor, "minMaxLoc", MinMaxLoc);
Nan::SetPrototypeMethod(ctor, "pushBack", PushBack);
@ -101,12 +106,15 @@ void Matrix::Init(Local<Object> target) {
Nan::SetMethod(ctor, "Zeros", Zeros);
Nan::SetMethod(ctor, "Ones", Ones);
Nan::SetMethod(ctor, "Eye", Eye);
Nan::SetMethod(ctor, "getRotationMatrix2D", GetRotationMatrix2D);
Nan::SetPrototypeMethod(ctor, "copyWithMask", CopyWithMask);
Nan::SetPrototypeMethod(ctor, "setWithMask", SetWithMask);
Nan::SetPrototypeMethod(ctor, "meanWithMask", MeanWithMask);
Nan::SetPrototypeMethod(ctor, "mean", Mean);
Nan::SetPrototypeMethod(ctor, "shift", Shift);
Nan::SetPrototypeMethod(ctor, "reshape", Reshape);
Nan::SetPrototypeMethod(ctor, "release", Release);
Nan::SetPrototypeMethod(ctor, "subtract", Subtract);
target->Set(Nan::New("Matrix").ToLocalChecked(), ctor->GetFunction());
};
@ -145,22 +153,22 @@ NAN_METHOD(Matrix::New) {
}
Matrix::Matrix() :
Nan::ObjectWrap() {
node_opencv::Matrix() {
mat = cv::Mat();
}
Matrix::Matrix(int rows, int cols) :
Nan::ObjectWrap() {
node_opencv::Matrix() {
mat = cv::Mat(rows, cols, CV_32FC3);
}
Matrix::Matrix(int rows, int cols, int type) :
Nan::ObjectWrap() {
node_opencv::Matrix() {
mat = cv::Mat(rows, cols, type);
}
Matrix::Matrix(cv::Mat m, cv::Rect roi) :
Nan::ObjectWrap() {
node_opencv::Matrix() {
mat = cv::Mat(m, roi);
}
@ -193,7 +201,7 @@ double Matrix::DblGet(cv::Mat mat, int i, int j) {
switch (mat.type()) {
case CV_32FC3:
pix = mat.at<cv::Vec3b>(i, j);
pix = mat.at<cv::Vec3f>(i, j);
pint |= (uchar) pix.val[2];
pint |= ((uchar) pix.val[1]) << 8;
pint |= ((uchar) pix.val[0]) << 16;
@ -202,6 +210,9 @@ double Matrix::DblGet(cv::Mat mat, int i, int j) {
case CV_64FC1:
val = mat.at<double>(i, j);
break;
case CV_32FC1:
val = mat.at<float>(i, j);
break;
default:
val = mat.at<double>(i, j);
break;
@ -276,11 +287,14 @@ NAN_METHOD(Matrix::Set) {
switch (self->mat.type()) {
case CV_32FC3:
vint = static_cast<unsigned int>(val + 0.5);
self->mat.at<cv::Vec3b>(i, j)[0] = (uchar) (vint >> 16) & 0xff;
self->mat.at<cv::Vec3b>(i, j)[1] = (uchar) (vint >> 8) & 0xff;
self->mat.at<cv::Vec3b>(i, j)[2] = (uchar) (vint) & 0xff;
self->mat.at<cv::Vec3f>(i, j)[0] = (uchar) (vint >> 16) & 0xff;
self->mat.at<cv::Vec3f>(i, j)[1] = (uchar) (vint >> 8) & 0xff;
self->mat.at<cv::Vec3f>(i, j)[2] = (uchar) (vint) & 0xff;
// printf("!!!i %x, %x, %x", (vint >> 16) & 0xff, (vint >> 8) & 0xff, (vint) & 0xff);
break;
case CV_32FC1:
self->mat.at<float>(i, j) = val;
break;
default:
self->mat.at<double>(i, j) = val;
}
@ -313,10 +327,16 @@ NAN_METHOD(Matrix::GetData) {
Nan::HandleScope scope;
Matrix *self = Nan::ObjectWrap::Unwrap<Matrix>(info.This());
int size = self->mat.rows * self->mat.cols * self->mat.elemSize1();
int size = self->mat.rows * self->mat.cols * self->mat.elemSize();
Local<Object> buf = Nan::NewBuffer(size).ToLocalChecked();
uchar* data = (uchar*) Buffer::Data(buf);
// if there is padding after each row, clone first to get rid of it
if (self->mat.dims == 2 && self->mat.step[0] != size_t(self->mat.size[1])) {
cv::Mat copy = self->mat.clone();
memcpy(data, copy.data, size);
} else {
memcpy(data, self->mat.data, size);
}
v8::Local<v8::Object> globalObj = Nan::GetCurrentContext()->Global();
v8::Local<v8::Function> bufferConstructor = v8::Local<v8::Function>::Cast(globalObj->Get(Nan::New<String>("Buffer").ToLocalChecked()));
@ -482,6 +502,12 @@ NAN_METHOD(Matrix::Size) {
info.GetReturnValue().Set(arr);
}
NAN_METHOD(Matrix::Type) {
SETUP_FUNCTION(Matrix)
info.GetReturnValue().Set(Nan::New<Int32>(self->mat.type()));
}
NAN_METHOD(Matrix::Clone) {
SETUP_FUNCTION(Matrix)
@ -666,8 +692,8 @@ NAN_METHOD(Matrix::ToBuffer) {
class AsyncToBufferWorker: public Nan::AsyncWorker {
public:
AsyncToBufferWorker(Nan::Callback *callback, Matrix* matrix, string ext,
vector<int> params) :
AsyncToBufferWorker(Nan::Callback *callback, Matrix* matrix, std::string ext,
std::vector<int> params) :
Nan::AsyncWorker(callback),
matrix(matrix),
ext(ext),
@ -980,7 +1006,7 @@ public:
private:
Matrix* matrix;
char* filename;
std::string filename;
int res;
};
@ -1081,6 +1107,7 @@ NAN_METHOD(Matrix::GaussianBlur) {
cv::Mat blurred;
Matrix *self = Nan::ObjectWrap::Unwrap<Matrix>(info.This());
double sigma = 0;
if (info.Length() < 1) {
ksize = cv::Size(5, 5);
@ -1097,9 +1124,12 @@ NAN_METHOD(Matrix::GaussianBlur) {
Nan::ThrowTypeError("'ksize' argument must be a 2 double array");
}
ksize = cv::Size(x->NumberValue(), y->NumberValue());
if (info[1]->IsNumber()) {
sigma = info[1]->ToNumber()->Value();
}
}
cv::GaussianBlur(self->mat, blurred, ksize, 0);
cv::GaussianBlur(self->mat, blurred, ksize, sigma);
blurred.copyTo(self->mat);
info.GetReturnValue().Set(Nan::Null());
@ -1155,6 +1185,36 @@ NAN_METHOD(Matrix::BilateralFilter) {
info.GetReturnValue().Set(Nan::Null());
}
NAN_METHOD(Matrix::Sobel) {
Nan::HandleScope scope;
if (info.Length() < 3)
Nan::ThrowError("Need more arguments: sobel(ddepth, xorder, yorder, ksize=3, scale=1.0, delta=0.0, borderType=CV_BORDER_DEFAULT)");
int ddepth = info[0]->IntegerValue();
int xorder = info[1]->IntegerValue();
int yorder = info[2]->IntegerValue();
int ksize = 3;
if (info.Length() > 3) ksize = info[3]->IntegerValue();
double scale = 1;
if (info.Length() > 4) scale = info[4]->NumberValue();
double delta = 0;
if (info.Length() > 5) delta = info[5]->NumberValue();
int borderType = cv::BORDER_DEFAULT;
if (info.Length() > 6) borderType = info[6]->IntegerValue();
Matrix *self = Nan::ObjectWrap::Unwrap<Matrix>(info.This());
Local<Object> result_to_return =
Nan::New(Matrix::constructor)->GetFunction()->NewInstance();
Matrix *result = Nan::ObjectWrap::Unwrap<Matrix>(result_to_return);
cv::Sobel(self->mat, result->mat, ddepth, xorder, yorder, ksize, scale, delta, borderType);
info.GetReturnValue().Set(result_to_return);
}
NAN_METHOD(Matrix::Copy) {
Nan::HandleScope scope;
@ -1236,6 +1296,38 @@ NAN_METHOD(Matrix::AbsDiff) {
info.GetReturnValue().Set(Nan::Null());
}
NAN_METHOD(Matrix::Dct) {
Nan::HandleScope scope;
Matrix *self = Nan::ObjectWrap::Unwrap<Matrix>(info.This());
int cols = self->mat.cols;
int rows = self->mat.rows;
Local<Object> out = Nan::New(Matrix::constructor)->GetFunction()->NewInstance();
Matrix *m_out = Nan::ObjectWrap::Unwrap<Matrix>(out);
m_out->mat.create(cols, rows, CV_32F);
cv::dct(self->mat, m_out->mat);
info.GetReturnValue().Set(out);
}
NAN_METHOD(Matrix::Idct) {
Nan::HandleScope scope;
Matrix *self = Nan::ObjectWrap::Unwrap<Matrix>(info.This());
int cols = self->mat.cols;
int rows = self->mat.rows;
Local<Object> out = Nan::New(Matrix::constructor)->GetFunction()->NewInstance();
Matrix *m_out = Nan::ObjectWrap::Unwrap<Matrix>(out);
m_out->mat.create(cols, rows, CV_32F);
cv::idct(self->mat, m_out->mat);
info.GetReturnValue().Set(out);
}
NAN_METHOD(Matrix::AddWeighted) {
Nan::HandleScope scope;
@ -1257,6 +1349,29 @@ NAN_METHOD(Matrix::AddWeighted) {
info.GetReturnValue().Set(Nan::Null());
}
NAN_METHOD(Matrix::Add) {
Nan::HandleScope scope;
Matrix *self = Nan::ObjectWrap::Unwrap<Matrix>(info.This());
int cols = self->mat.cols;
int rows = self->mat.rows;
Matrix *src1 = Nan::ObjectWrap::Unwrap<Matrix>(info[0]->ToObject());
Local<Object> out = Nan::New(Matrix::constructor)->GetFunction()->NewInstance();
Matrix *m_out = Nan::ObjectWrap::Unwrap<Matrix>(out);
m_out->mat.create(cols, rows, self->mat.type());
try {
cv::add(self->mat, src1->mat, m_out->mat);
} catch(cv::Exception& e ) {
const char* err_msg = e.what();
Nan::ThrowError(err_msg);
}
info.GetReturnValue().Set(out);
}
NAN_METHOD(Matrix::BitwiseXor) {
Nan::HandleScope scope;
@ -1323,6 +1438,45 @@ NAN_METHOD(Matrix::Split) {
info.GetReturnValue().Set(Nan::Null());
} */
NAN_METHOD(Matrix::Moments) {
Nan::HandleScope scope;
Matrix *self = Nan::ObjectWrap::Unwrap<Matrix>(info.This());
cv::Moments mo = moments( self->mat, false );
Local<Object> res = Nan::New<Object>();
res->Set(Nan::New("m00").ToLocalChecked(), Nan::New<Number>(mo.m00));
res->Set(Nan::New("m10").ToLocalChecked(), Nan::New<Number>(mo.m10));
res->Set(Nan::New("m01").ToLocalChecked(), Nan::New<Number>(mo.m01));
res->Set(Nan::New("m20").ToLocalChecked(), Nan::New<Number>(mo.m20));
res->Set(Nan::New("m11").ToLocalChecked(), Nan::New<Number>(mo.m11));
res->Set(Nan::New("m02").ToLocalChecked(), Nan::New<Number>(mo.m02));
res->Set(Nan::New("m30").ToLocalChecked(), Nan::New<Number>(mo.m30));
res->Set(Nan::New("m21").ToLocalChecked(), Nan::New<Number>(mo.m21));
res->Set(Nan::New("m12").ToLocalChecked(), Nan::New<Number>(mo.m12));
res->Set(Nan::New("m03").ToLocalChecked(), Nan::New<Number>(mo.m03));
res->Set(Nan::New("mu20").ToLocalChecked(), Nan::New<Number>(mo.mu20));
res->Set(Nan::New("mu11").ToLocalChecked(), Nan::New<Number>(mo.mu11));
res->Set(Nan::New("mu02").ToLocalChecked(), Nan::New<Number>(mo.mu02));
res->Set(Nan::New("mu30").ToLocalChecked(), Nan::New<Number>(mo.mu30));
res->Set(Nan::New("mu21").ToLocalChecked(), Nan::New<Number>(mo.mu21));
res->Set(Nan::New("mu12").ToLocalChecked(), Nan::New<Number>(mo.mu12));
res->Set(Nan::New("mu03").ToLocalChecked(), Nan::New<Number>(mo.mu03));
res->Set(Nan::New("nu20").ToLocalChecked(), Nan::New<Number>(mo.nu20));
res->Set(Nan::New("nu11").ToLocalChecked(), Nan::New<Number>(mo.nu11));
res->Set(Nan::New("nu02").ToLocalChecked(), Nan::New<Number>(mo.nu02));
res->Set(Nan::New("nu30").ToLocalChecked(), Nan::New<Number>(mo.nu30));
res->Set(Nan::New("nu21").ToLocalChecked(), Nan::New<Number>(mo.nu21));
res->Set(Nan::New("nu12").ToLocalChecked(), Nan::New<Number>(mo.nu12));
res->Set(Nan::New("nu03").ToLocalChecked(), Nan::New<Number>(mo.nu03));
info.GetReturnValue().Set(res);
}
NAN_METHOD(Matrix::Canny) {
Nan::HandleScope scope;
@ -1406,7 +1560,16 @@ NAN_METHOD(Matrix::DrawContour) {
}
int thickness = info.Length() < 4 ? 1 : info[3]->NumberValue();
cv::drawContours(self->mat, cont->contours, pos, color, thickness);
int lineType = info.Length() < 5 ? 8 : info[4]->NumberValue();
int maxLevel = info.Length() < 6 ? 0 : info[5]->NumberValue();
cv::Point offset;
if (info.Length() == 6) {
Local<Array> _offset = Local<Array>::Cast(info[5]);
offset = cv::Point(_offset->Get(0)->ToNumber()->Value(), _offset->Get(1)->ToNumber()->Value());
}
cv::drawContours(self->mat, cont->contours, pos, color, thickness, lineType, cont->hierarchy, maxLevel, offset);
return;
}
@ -1517,13 +1680,27 @@ NAN_METHOD(Matrix::HoughCircles) {
}
cv::Scalar setColor(Local<Object> objColor) {
Local<Value> valB = objColor->Get(0);
Local<Value> valG = objColor->Get(1);
Local<Value> valR = objColor->Get(2);
int64_t channels[4] = { 0, 0, 0, 0 };
cv::Scalar color = cv::Scalar(valB->IntegerValue(), valG->IntegerValue(),
valR->IntegerValue());
return color;
// We'll accomodate a channel count up to 4 and fall back to the old
// "assume it's always 3" in the default case
if (!objColor->HasRealIndexedProperty(1)) {
channels[0] = objColor->Get(0)->IntegerValue();
} else if (!objColor->HasRealIndexedProperty(2)) {
channels[0] = objColor->Get(0)->IntegerValue();
channels[1] = objColor->Get(1)->IntegerValue();
} else if (!objColor->HasRealIndexedProperty(4)) {
channels[0] = objColor->Get(0)->IntegerValue();
channels[1] = objColor->Get(1)->IntegerValue();
channels[2] = objColor->Get(2)->IntegerValue();
channels[3] = objColor->Get(3)->IntegerValue();
} else {
channels[0] = objColor->Get(0)->IntegerValue();
channels[1] = objColor->Get(1)->IntegerValue();
channels[2] = objColor->Get(2)->IntegerValue();
}
return cv::Scalar(channels[0], channels[1], channels[2], channels[3]);
}
cv::Point setPoint(Local<Object> objPoint) {
@ -1625,24 +1802,23 @@ NAN_METHOD(Matrix::Rotate) {
NAN_METHOD(Matrix::GetRotationMatrix2D) {
Nan::HandleScope scope;
Matrix *self = Nan::ObjectWrap::Unwrap<Matrix>(info.This());
cv::Mat res;
if (info.Length() < 3) {
JSTHROW("Invalid number of arguments");
}
float angle = info[0]->ToNumber()->Value();
int x = info[1]->IsUndefined() ? round(self->mat.size().width / 2) :
info[1]->Uint32Value();
int y = info[2]->IsUndefined() ? round(self->mat.size().height / 2) :
info[2]->Uint32Value();
int x = info[1]->Uint32Value();
int y = info[2]->Uint32Value();
double scale = info[3]->IsUndefined() ? 1.0 : info[3]->NumberValue();
Local<Object> img_to_return =
Nan::New(Matrix::constructor)->GetFunction()->NewInstance();
Matrix *img = Nan::ObjectWrap::Unwrap<Matrix>(img_to_return);
cv::Point center = cv::Point(x,y);
res = getRotationMatrix2D(center, angle, scale);
img->mat = getRotationMatrix2D(center, angle, scale);
~self->mat;
self->mat = res;
return;
info.GetReturnValue().Set(img_to_return);
}
NAN_METHOD(Matrix::WarpAffine) {
@ -1985,7 +2161,7 @@ NAN_METHOD(Matrix::Split) {
Matrix * self = Nan::ObjectWrap::Unwrap<Matrix>(info.This());
unsigned int size = self->mat.channels();
vector<cv::Mat> channels;
std::vector<cv::Mat> channels;
// Split doesn't seem to work on empty vectors
for (unsigned int i = 0; i < size; i++) {
@ -2018,7 +2194,7 @@ NAN_METHOD(Matrix::Merge) {
v8::Local<v8::Array> jsChannels = v8::Local<v8::Array>::Cast(info[0]);
unsigned int L = jsChannels->Length();
vector<cv::Mat> vChannels(L);
std::vector<cv::Mat> vChannels(L);
for (unsigned int i = 0; i < L; i++) {
Matrix * matObject = Nan::ObjectWrap::Unwrap<Matrix>(jsChannels->Get(i)->ToObject());
vChannels[i] = matObject->mat;
@ -2132,14 +2308,14 @@ NAN_METHOD(Matrix::TemplateMatches) {
cv::Size maxSize = hit_mask.size();
int max_x = maxSize.width - 1;
int max_y = maxSize.height - 1;
cv::Point top_left = cv::Point(max(0, pt.x - min_x_distance),
max(0, pt.y - min_y_distance));
cv::Point top_right = cv::Point(min(max_x, pt.x + min_x_distance),
max(0, pt.y - min_y_distance));
cv::Point bottom_left = cv::Point(max(0, pt.x - min_x_distance),
min(max_y, pt.y + min_y_distance));
cv::Point bottom_right = cv::Point(min(max_x, pt.x + min_x_distance),
min(max_y, pt.y + min_y_distance));
cv::Point top_left = cv::Point(std::max(0, pt.x - min_x_distance),
std::max(0, pt.y - min_y_distance));
cv::Point top_right = cv::Point(std::min(max_x, pt.x + min_x_distance),
std::max(0, pt.y - min_y_distance));
cv::Point bottom_left = cv::Point(std::max(0, pt.x - min_x_distance),
std::min(max_y, pt.y + min_y_distance));
cv::Point bottom_right = cv::Point(std::min(max_x, pt.x + min_x_distance),
std::min(max_y, pt.y + min_y_distance));
if (hit_mask.at<double>(top_left.y, top_left.x) > 0)
continue;
if (hit_mask.at<double>(top_right.y, top_right.x) > 0)
@ -2168,6 +2344,36 @@ NAN_METHOD(Matrix::TemplateMatches) {
info.GetReturnValue().Set(probabilites_array);
}
// @author Evilcat325
// MatchTemplate accept a Matrix
// Usage: output = input.matchTemplateByMatrix(matrix. method);
NAN_METHOD(Matrix::MatchTemplateByMatrix) {
Nan::HandleScope scope;
Matrix *self = Nan::ObjectWrap::Unwrap<Matrix>(info.This());
Matrix *templ = Nan::ObjectWrap::Unwrap<Matrix>(info[0]->ToObject());
Local<Object> out = Nan::New(Matrix::constructor)->GetFunction()->NewInstance();
Matrix *m_out = Nan::ObjectWrap::Unwrap<Matrix>(out);
int cols = self->mat.cols - templ->mat.cols + 1;
int rows = self->mat.rows - templ->mat.rows + 1;
m_out->mat.create(cols, rows, CV_32FC1);
/*
TM_SQDIFF =0
TM_SQDIFF_NORMED =1
TM_CCORR =2
TM_CCORR_NORMED =3
TM_CCOEFF =4
TM_CCOEFF_NORMED =5
*/
int method = (info.Length() < 2) ? (int)cv::TM_CCORR_NORMED : info[1]->Uint32Value();
if (!(method >= 0 && method <= 5)) method = (int)cv::TM_CCORR_NORMED;
cv::matchTemplate(self->mat, templ->mat, m_out->mat, method);
info.GetReturnValue().Set(out);
}
// @author ytham
// Match Template filter
// Usage: output = input.matchTemplate("templateFileString", method);
@ -2179,7 +2385,7 @@ NAN_METHOD(Matrix::MatchTemplate) {
v8::String::Utf8Value args0(info[0]->ToString());
std::string filename = std::string(*args0);
cv::Mat templ;
templ = cv::imread(filename, CV_8S);
templ = cv::imread(filename, -1);
Local<Object> out = Nan::New(Matrix::constructor)->GetFunction()->NewInstance();
Matrix *m_out = Nan::ObjectWrap::Unwrap<Matrix>(out);
@ -2198,8 +2404,44 @@ NAN_METHOD(Matrix::MatchTemplate) {
int method = (info.Length() < 2) ? (int)cv::TM_CCORR_NORMED : info[1]->Uint32Value();
cv::matchTemplate(self->mat, templ, m_out->mat, method);
cv::normalize(m_out->mat, m_out->mat, 0, 1, cv::NORM_MINMAX, -1, cv::Mat());
double minVal;
double maxVal;
cv::Point minLoc;
cv::Point maxLoc;
cv::Point matchLoc;
info.GetReturnValue().Set(out);
minMaxLoc(m_out->mat, &minVal, &maxVal, &minLoc, &maxLoc, cv::Mat());
if(method == CV_TM_SQDIFF || method == CV_TM_SQDIFF_NORMED) {
matchLoc = minLoc;
}
else {
matchLoc = maxLoc;
}
//detected ROI
unsigned int roi_x = matchLoc.x;
unsigned int roi_y = matchLoc.y;
unsigned int roi_width = templ.cols;
unsigned int roi_height = templ.rows;
//draw rectangle
if(info.Length() >= 3) {
cv::Rect roi(roi_x,roi_y,roi_width,roi_height);
cv::rectangle(self->mat, roi, cv::Scalar(0,0,255));
}
m_out->mat.convertTo(m_out->mat, CV_8UC1, 255, 0);
v8::Local <v8::Array> arr = Nan::New<v8::Array>(5);
arr->Set(0, out);
arr->Set(1, Nan::New<Number>(roi_x));
arr->Set(2, Nan::New<Number>(roi_y));
arr->Set(3, Nan::New<Number>(roi_width));
arr->Set(4, Nan::New<Number>(roi_height));
info.GetReturnValue().Set(arr);
}
// @author ytham
@ -2377,10 +2619,24 @@ NAN_METHOD(Matrix::MeanWithMask) {
Matrix *mask = Nan::ObjectWrap::Unwrap<Matrix>(info[0]->ToObject());
cv::Scalar means = cv::mean(self->mat, mask->mat);
v8::Local < v8::Array > arr = Nan::New<Array>(3);
v8::Local < v8::Array > arr = Nan::New<Array>(4);
arr->Set(0, Nan::New<Number>(means[0]));
arr->Set(1, Nan::New<Number>(means[1]));
arr->Set(2, Nan::New<Number>(means[2]));
arr->Set(3, Nan::New<Number>(means[3]));
info.GetReturnValue().Set(arr);
}
NAN_METHOD(Matrix::Mean) {
SETUP_FUNCTION(Matrix)
cv::Scalar means = cv::mean(self->mat);
v8::Local<v8::Array> arr = Nan::New<Array>(4);
arr->Set(0, Nan::New<Number>(means[0]));
arr->Set(1, Nan::New<Number>(means[1]));
arr->Set(2, Nan::New<Number>(means[2]));
arr->Set(3, Nan::New<Number>(means[3]));
info.GetReturnValue().Set(arr);
}
@ -2463,3 +2719,17 @@ NAN_METHOD(Matrix::Release) {
return;
}
NAN_METHOD(Matrix::Subtract) {
SETUP_FUNCTION(Matrix)
if (info.Length() < 1) {
Nan::ThrowTypeError("Invalid number of arguments");
}
Matrix *other = Nan::ObjectWrap::Unwrap<Matrix>(info[0]->ToObject());
self->mat -= other->mat;
return;
}

View File

@ -1,9 +1,9 @@
#include "OpenCV.h"
#include "../inc/Matrix.h"
class Matrix: public Nan::ObjectWrap {
class Matrix: public node_opencv::Matrix{
public:
cv::Mat mat;
static Nan::Persistent<FunctionTemplate> constructor;
static void Init(Local<Object> target);
static NAN_METHOD(New);
@ -36,6 +36,7 @@ public:
JSFUNC(Size)
JSFUNC(Width)
JSFUNC(Height)
JSFUNC(Type)
JSFUNC(Channels)
JSFUNC(Clone)
JSFUNC(Ellipse)
@ -62,17 +63,22 @@ public:
JSFUNC(GaussianBlur)
JSFUNC(MedianBlur)
JSFUNC(BilateralFilter)
JSFUNC(Sobel)
JSFUNC(Copy)
JSFUNC(Flip)
JSFUNC(ROI)
JSFUNC(Ptr)
JSFUNC(AbsDiff)
JSFUNC(Dct)
JSFUNC(Idct)
JSFUNC(AddWeighted)
JSFUNC(Add)
JSFUNC(BitwiseXor)
JSFUNC(BitwiseNot)
JSFUNC(BitwiseAnd)
JSFUNC(CountNonZero)
//JSFUNC(Split)
JSFUNC(Moments)
JSFUNC(Canny)
JSFUNC(Dilate)
JSFUNC(Erode)
@ -107,6 +113,7 @@ public:
JSFUNC(FloodFill)
JSFUNC(MatchTemplate)
JSFUNC(MatchTemplateByMatrix)
JSFUNC(TemplateMatches)
JSFUNC(MinMaxLoc)
@ -119,10 +126,13 @@ public:
JSFUNC(CopyWithMask)
JSFUNC(SetWithMask)
JSFUNC(MeanWithMask)
JSFUNC(Mean)
JSFUNC(Shift)
JSFUNC(Reshape)
JSFUNC(Release)
JSFUNC(Subtract)
/*
static Handle<Value> Val(const Arguments& info);
static Handle<Value> RowRange(const Arguments& info);

View File

@ -11,6 +11,7 @@ void OpenCV::Init(Local<Object> target) {
target->Set(Nan::New<String>("version").ToLocalChecked(), Nan::New<String>(out, n).ToLocalChecked());
Nan::SetMethod(target, "readImage", ReadImage);
Nan::SetMethod(target, "readImageMulti", ReadImageMulti);
}
NAN_METHOD(OpenCV::ReadImage) {
@ -37,14 +38,14 @@ NAN_METHOD(OpenCV::ReadImage) {
} else if (info[0]->IsString()) {
std::string filename = std::string(*Nan::Utf8String(info[0]->ToString()));
mat = cv::imread(filename);
mat = cv::imread(filename, CV_LOAD_IMAGE_UNCHANGED);
} else if (Buffer::HasInstance(info[0])) {
uint8_t *buf = (uint8_t *) Buffer::Data(info[0]->ToObject());
unsigned len = Buffer::Length(info[0]->ToObject());
cv::Mat *mbuf = new cv::Mat(len, 1, CV_64FC1, buf);
mat = cv::imdecode(*mbuf, -1);
mat = cv::imdecode(*mbuf, CV_LOAD_IMAGE_UNCHANGED);
if (mat.empty()) {
argv[0] = Nan::Error("Error loading file");
@ -66,3 +67,54 @@ NAN_METHOD(OpenCV::ReadImage) {
return;
}
#if CV_MAJOR_VERSION >= 3
NAN_METHOD(OpenCV::ReadImageMulti) {
Nan::EscapableHandleScope scope;
REQ_FUN_ARG(1, cb);
Local<Value> argv[2];
argv[0] = Nan::Null();
std::vector<cv::Mat> mats;
try {
if (info[0]->IsString()) {
std::string filename = std::string(*Nan::Utf8String(info[0]->ToString()));
cv::imreadmulti(filename, mats);
if (mats.empty()) {
argv[0] = Nan::Error("Error loading file");
}
}
} catch (cv::Exception& e) {
argv[0] = Nan::Error(e.what());
argv[1] = Nan::Null();
}
Local <Array> output = Nan::New<Array>(mats.size());
argv[1] = output;
for (std::vector<cv::Mat>::size_type i = 0; i < mats.size(); i ++) {
Local<Object> im_h = Nan::New(Matrix::constructor)->GetFunction()->NewInstance();
Matrix *img = Nan::ObjectWrap::Unwrap<Matrix>(im_h);
img->mat = mats[i];
output->Set(i, im_h);
}
Nan::TryCatch try_catch;
cb->Call(Nan::GetCurrentContext()->Global(), 2, argv);
if (try_catch.HasCaught()) {
Nan::FatalException(try_catch);
}
return;
}
#else
NAN_METHOD(OpenCV::ReadImageMulti) {
info.GetReturnValue().Set(Nan::New<Boolean>(false));
return;
}
#endif

View File

@ -1,6 +1,16 @@
#ifndef __NODE_OPENCV_H__
#define __NODE_OPENCV_H__
#ifdef WIN
/*
This is needed on Windows for Visual Studio to not throw an error in the
build/include/opencv2/flann/any.h file in OpenCV.
*/
namespace std{ typedef type_info type_info; }
#endif
#include <v8.h>
#include <node.h>
#include <node_object_wrap.h>
@ -8,6 +18,16 @@
#include <node_buffer.h>
#include <opencv/cv.h>
#include <opencv/highgui.h>
#if CV_MAJOR_VERSION >= 3
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/opencv_modules.hpp>
#endif
#if ((CV_MAJOR_VERSION == 2) && (CV_MINOR_VERSION >=4) && (CV_SUBMINOR_VERSION>=4))
#define HAVE_OPENCV_FACE
#endif
#include <string.h>
#include <nan.h>
@ -47,6 +67,7 @@ public:
static void Init(Local<Object> target);
static NAN_METHOD(ReadImage);
static NAN_METHOD(ReadImageMulti);
};
#endif

View File

@ -1,4 +1,11 @@
#include "Stereo.h"
#if CV_MAJOR_VERSION >= 3
#warning TODO: port me to OpenCV 3
#endif
#if CV_MAJOR_VERSION < 3
#include "Matrix.h"
#include <opencv2/legacy/legacy.hpp>
@ -312,3 +319,5 @@ NAN_METHOD(StereoGC::Compute) {
return;
}
}
#endif

View File

@ -3,6 +3,8 @@
#include "OpenCV.h"
#if CV_MAJOR_VERSION < 3
class StereoBM: public Nan::ObjectWrap {
public:
cv::StereoBM stereo;
@ -51,3 +53,4 @@ public:
};
#endif
#endif // __NODE_STEREO_H

View File

@ -3,7 +3,6 @@
#include "OpenCV.h"
#include <iostream>
using namespace std;
Nan::Persistent<FunctionTemplate> VideoCaptureWrap::constructor;
@ -32,7 +31,9 @@ void VideoCaptureWrap::Init(Local<Object> target) {
Nan::SetPrototypeMethod(ctor, "setWidth", SetWidth);
Nan::SetPrototypeMethod(ctor, "setHeight", SetHeight);
Nan::SetPrototypeMethod(ctor, "setPosition", SetPosition);
Nan::SetPrototypeMethod(ctor, "close", Close);
Nan::SetPrototypeMethod(ctor, "getFrameAt", GetFrameAt);
Nan::SetPrototypeMethod(ctor, "getFrameCount", GetFrameCount);
Nan::SetPrototypeMethod(ctor, "release", Release);
Nan::SetPrototypeMethod(ctor, "ReadSync", ReadSync);
Nan::SetPrototypeMethod(ctor, "grab", Grab);
Nan::SetPrototypeMethod(ctor, "retrieve", Retrieve);
@ -93,6 +94,15 @@ NAN_METHOD(VideoCaptureWrap::SetWidth) {
return;
}
NAN_METHOD(VideoCaptureWrap::GetFrameCount) {
Nan::HandleScope scope;
VideoCaptureWrap *v = Nan::ObjectWrap::Unwrap<VideoCaptureWrap>(info.This());
int cnt = int(v->cap.get(CV_CAP_PROP_FRAME_COUNT));
info.GetReturnValue().Set(Nan::New<Number>(cnt));
}
NAN_METHOD(VideoCaptureWrap::SetHeight) {
Nan::HandleScope scope;
VideoCaptureWrap *v = Nan::ObjectWrap::Unwrap<VideoCaptureWrap>(info.This());
@ -121,7 +131,21 @@ NAN_METHOD(VideoCaptureWrap::SetPosition) {
return;
}
NAN_METHOD(VideoCaptureWrap::Close) {
NAN_METHOD(VideoCaptureWrap::GetFrameAt) {
Nan::HandleScope scope;
VideoCaptureWrap *v = Nan::ObjectWrap::Unwrap<VideoCaptureWrap>(info.This());
if(info.Length() != 1)
return;
int pos = info[0]->IntegerValue();
v->cap.set(CV_CAP_PROP_POS_MSEC, pos);
return;
}
NAN_METHOD(VideoCaptureWrap::Release) {
Nan::HandleScope scope;
VideoCaptureWrap *v = Nan::ObjectWrap::Unwrap<VideoCaptureWrap>(info.This());

View File

@ -23,10 +23,10 @@ public:
// to set frame position
static NAN_METHOD(SetPosition);
static NAN_METHOD(GetFrameCount);
static NAN_METHOD(GetFrameAt);
//close the stream
static NAN_METHOD(Close);
// release the stream
static NAN_METHOD(Release);
};

View File

@ -30,16 +30,19 @@ extern "C" void init(Local<Object> target) {
Constants::Init(target);
Calib3D::Init(target);
ImgProc::Init(target);
#if CV_MAJOR_VERSION < 3
StereoBM::Init(target);
StereoSGBM::Init(target);
StereoGC::Init(target);
#if CV_MAJOR_VERSION >= 2 && CV_MINOR_VERSION >=4
#if CV_MAJOR_VERSION == 2 && CV_MINOR_VERSION >=4
BackgroundSubtractorWrap::Init(target);
Features::Init(target);
FaceRecognizerWrap::Init(target);
LDAWrap::Init(target);
#endif
#endif
#ifdef HAVE_OPENCV_FACE
FaceRecognizerWrap::Init(target);
#endif
};
NODE_MODULE(opencv, init)

Binary file not shown.

20
test/nativemat.cc Normal file
View File

@ -0,0 +1,20 @@
#include <nan.h>
#include <Matrix.h>
void Size(const Nan::FunctionCallbackInfo<v8::Value>& info) {
// Unwrap the node-opencv Matrix object into a normal cv::Mat
cv::Mat mat = Nan::ObjectWrap::Unwrap<node_opencv::Matrix>(info[0]->ToObject())->mat;
v8::Local < v8::Array > arr = Nan::New<v8::Array>(2);
arr->Set(0, Nan::New<v8::Number>(mat.size().height));
arr->Set(1, Nan::New<v8::Number>(mat.size().width));
info.GetReturnValue().Set(arr);
}
void Init(v8::Local<v8::Object> exports) {
exports->Set(Nan::New("size").ToLocalChecked(),
Nan::New<v8::FunctionTemplate>(Size)->GetFunction());
}
NODE_MODULE(test_nativemat, Init)

View File

@ -61,8 +61,8 @@ test('Matrix constructor', function(assert){
test('Matrix accessors', function(assert){
var mat = new cv.Matrix(1, 2);
mat.set(0,0,3)
mat.set(0,1,5000)
mat.set(0,0,3);
mat.set(0,1,5000);
assert.deepEqual(mat.row(0), [3,5000]);
mat = new cv.Matrix(1,2);
@ -103,8 +103,10 @@ test('Matrix functions', function(assert) {
// convertTo
var mat = new cv.Matrix(75, 75, cv.Constants.CV_32F, [2.0]);
var matNew = new cv.Matrix(75, 75, cv.Constants.CV_8U);
mat.convertTo(matNew, cv.Constants.CV_8U, 2, 1);
assert.equal(matNew.pixel(0, 0), 5);
var alpha = 2;
var beta = 1;
mat.convertTo(matNew, cv.Constants.CV_8U, alpha, beta);
assert.equal(matNew.pixel(0, 0), mat.get(0, 0)*alpha + beta);
// reshape
mat = new cv.Matrix(75, 75, cv.Constants.CV_8UC1);
@ -112,6 +114,10 @@ test('Matrix functions', function(assert) {
assert.equal(matNew.height(), 1);
assert.equal(matNew.width(), 5625);
// GetRotationMatrix2D
mat = cv.Matrix.getRotationMatrix2D(0, 0, 90, 1.0);
assert.deepEqual(mat.size(), [2,3], 'GetRotationMatrix2D');
assert.end();
})
@ -123,7 +129,6 @@ test(".norm", function(assert){
var errorL2 = im.norm(im2, cv.Constants.NORM_L2);
assert.equal(errorL2, 7295.591339980605);
errorL2 = im.norm(im, cv.Constants.NORM_L2);
assert.equal(errorL2, 0);
assert.end();
@ -201,23 +206,55 @@ test(".bitwiseXor", function(assert){
test("Image read from file", function(assert){
cv.readImage("./examples/files/mona.png", function(err, im){
cv.readImage("./examples/files/opencv.png", function(err, im){
assert.ok(im);
assert.equal(im.width(), 500);
assert.equal(im.height(), 756)
assert.equal(im.empty(), false)
assert.end()
assert.equal(im.width(), 82);
assert.equal(im.height(), 99);
assert.equal(im.channels(), 4);
assert.equal(im.empty(), false);
assert.end();
})
})
test("Multi-page image read from file", function(assert){
if (parseInt(cv.version) >= 3) {
cv.readImageMulti("./examples/files/multipage.tif", function(err, imgs){
assert.ok(imgs);
assert.equal(imgs.length, 10);
for (var i = 0; i < imgs.length; i++) {
assert.ok(imgs[i]);
assert.equal(imgs[i].width(), 800);
assert.equal(imgs[i].height(), 600);
assert.equal(imgs[i].channels(), 3);
assert.equal(imgs[i].empty(), false);
}
assert.end();
})
} else {
assert.equal(cv.readImageMulti("./examples/files/multipage.tif"), false);
assert.end();
}
})
test("Distance transform", function(assert){
cv.readImage("./examples/files/distanceTransform.png", function(err, img){
assert.ok(img);
// 50px image with single black pixel on right side
var result = cv.imgproc.distanceTransform(img, cv.Constants.CV_DIST_L2, cv.Constants.CV_DIST_MASK_PRECISE);
assert.equal(result.get(0,0), 49);
assert.end();
})
})
test("read Image from buffer", function(assert){
cv.readImage(fs.readFileSync('./examples/files/mona.png'), function(err, im){
cv.readImage(fs.readFileSync('./examples/files/opencv.png'), function(err, im){
assert.ok(im);
assert.equal(im.width(), 500);
assert.equal(im.height(), 756)
assert.equal(im.empty(), false)
assert.end()
assert.equal(im.width(), 82);
assert.equal(im.height(), 99);
assert.equal(im.channels(), 4);
assert.equal(im.empty(), false);
assert.end();
})
})
@ -310,7 +347,107 @@ test("fonts", function(t) {
});
})
test('LDA Wrap', function(assert) {
if (cv.LDA === undefined) {
console.log('TODO: Please port LDAWrap.cc to OpenCV 3')
assert.end();
return;
}
// subspaceProject
var mat = cv.LDA.subspaceProject(new cv.Matrix(1, 2, cv.Constants.CV_64F), new cv.Matrix(), new cv.Matrix(2, 1, cv.Constants.CV_8UC1));
assert.deepEqual(mat.size(), [2,2], 'subspaceProject');
// subspaceReconstruct
mat = cv.LDA.subspaceReconstruct(new cv.Matrix(1, 2, cv.Constants.CV_64F), new cv.Matrix(), new cv.Matrix(1, 2, cv.Constants.CV_8UC1));
assert.deepEqual(mat.size(), [1,1], 'subspaceReconstruct');
assert.end();
})
test('Native Matrix', function(assert) {
var nativemat = require('../build/' + (!!process.env.NODE_OPENCV_DEBUG ? 'Debug' : 'Release') + '/test_nativemat.node');
var mat = new cv.Matrix(42, 8);
assert.deepEqual(mat.size(), nativemat.size(mat), 'nativemat');
assert.end();
})
test('Subtract', function(assert) {
var a = new cv.Matrix.Zeros(1,1);
a.set(0, 0, 3);
var b = new cv.Matrix.Zeros(1,1);
b.set(0, 0, 1);
a.subtract(b);
assert.deepEqual(a.get(0, 0), 2);
assert.end();
});
test('Mean', function(assert) {
var a = new cv.Matrix.Zeros(2, 2, cv.Constants.CV_8UC3);
// Set [0, 0] element to 1 for all three channels
a.set(0, 0, 1, 0);
a.set(0, 0, 1, 1);
a.set(0, 0, 1, 2);
var means = a.mean();
assert.deepEqual(means, [0.25, 0.25, 0.25, 0]);
assert.end();
});
test('MatchTemplateByMatrix', function(assert) {
var cv = require('../lib/opencv');
var targetFilename = "./examples/files/car1.jpg";
var templateFilename = "./examples/files/car1_template.jpg";
cv.readImage(targetFilename, function(err, target){
cv.readImage(templateFilename, function(err, template){
var TM_CCORR_NORMED = 3;
var res = target.matchTemplateByMatrix(template, TM_CCORR_NORMED);
var minMax = res.minMaxLoc();
var topLeft = minMax.maxLoc;
assert.ok(topLeft, "RGB Found Match");
assert.equal(topLeft.x, 42, "match location x === 42");
assert.equal(topLeft.y, 263, "match location y === 263");
target.canny(5,300);
template.canny(5,300);
res = target.matchTemplateByMatrix(template, TM_CCORR_NORMED);
minMax = res.minMaxLoc();
topLeft = minMax.maxLoc;
assert.ok(topLeft, "Canny edge Found Match");
assert.equal(topLeft.x, 42, "match location x === 42");
assert.equal(topLeft.y, 263, "match location y === 263");
assert.end();
});
})
});
test('setColor works will alpha channels', function(assert) {
var cv = require('../lib/opencv');
var mat = new cv.Matrix(100, 100, cv.Constants.CV_8UC4);
var SQUARE = [ 50, 50 ];
mat.rectangle([ 0, 0 ], SQUARE, [ 0, 187, 255, 255 ], -1);
mat.rectangle([ 0, 50 ], SQUARE, [ 0, 187, 124, 200 ], -1);
mat.rectangle([ 50, 0 ], SQUARE, [ 241, 161, 0, 128 ], -1);
mat.rectangle([ 50, 50 ], SQUARE, [ 20, 83, 246, 70 ], -1);
cv.readImage('./examples/files/alpha-test.png', function(err, imgMat) {
if (!err) {
var diff = new cv.Matrix();
diff.absDiff(mat, imgMat);
// We'll verify that each channel is 0
var channels = diff.split();
for (var i = 0; i < 4; i++) {
assert.equal(channels[i].countNonZero(), 0);
}
} else {
throw err;
}
assert.end();
});
});
// Test the examples folder.
require('./examples')()

81
utils/find-opencv.js Normal file
View File

@ -0,0 +1,81 @@
"use strict";
var exec = require("child_process").exec;
var fs = require("fs");
var flag = process.argv[2] || "--exists";
// Normally |pkg-config opencv ...| could report either OpenCV 2.x or OpenCV 3.y
// depending on what is installed. To enable both 2.x and 3.y to co-exist on
// the same machine, the opencv.pc for 3.y can be installed as opencv3.pc and
// then selected by |export PKG_CONFIG_OPENCV3=1| before building node-opencv.
var opencv = process.env.PKG_CONFIG_OPENCV3 === "1" ? "opencv3" : '"opencv >= 2.3.1"';
function main(){
//Try using pkg-config, but if it fails and it is on Windows, try the fallback
exec("pkg-config " + opencv + " " + flag, function(error, stdout, stderr){
if(error){
if(process.platform === "win32"){
fallback();
}
else{
throw new Error("ERROR: failed to run: pkg-config", opencv, flag);
}
}
else{
console.log(stdout);
}
});
}
//======================Windows Specific=======================================
function fallback(){
exec("echo %OPENCV_DIR%", function(error, stdout, stderr){
stdout = cleanupEchoOutput(stdout);
if(error){
throw new Error("ERROR: There was an error reading OPENCV_DIR");
}
else if(stdout === "%OPENCV_DIR%") {
throw new Error("ERROR: OPENCV_DIR doesn't seem to be defined");
}
else {
printPaths(stdout);
}
});
}
function printPaths(opencvPath){
if(flag === "--cflags") {
console.log("\"" + opencvPath + "\\..\\..\\include\"");
console.log("\"" + opencvPath + "\\..\\..\\include\\opencv\"");
}
else if(flag === "--libs") {
var libPath = opencvPath + "\\lib\\";
fs.readdir(libPath, function(err, files){
if(err){
throw new Error("ERROR: couldn't read the lib directory " + err);
}
var libs = "";
for(var i = 0; i < files.length; i++){
if(getExtension(files[i]) === "lib"){
libs = libs + " \"" + libPath + files[i] + "\" \r\n ";
}
}
console.log(libs);
});
}
else {
throw new Error("Error: unknown argument '" + flag + "'");
}
}
function cleanupEchoOutput(s){
return s.slice(0, s.length - 2);
}
function getExtension(s){
return s.substr(s.lastIndexOf(".") + 1);
}
main();