From ee4d63463943f13b99d3860c88b8f897b824eec1 Mon Sep 17 00:00:00 2001 From: Dmitry Ivanovm Date: Wed, 8 Mar 2017 16:07:28 -0500 Subject: [PATCH 1/7] +CalcOpticalFlowPyrLK method ~GoodFeaturesToTrack hardcoded vars replaced with actual parameters --- examples/optical-flow.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100755 examples/optical-flow.js diff --git a/examples/optical-flow.js b/examples/optical-flow.js new file mode 100755 index 0000000..96ce808 --- /dev/null +++ b/examples/optical-flow.js @@ -0,0 +1,20 @@ +var cv = require('../lib/opencv'); + +try { + var camera = new cv.VideoCapture(0); + var window = new cv.NamedWindow('Video', 0) + /* + setInterval(function() { + camera.read(function(err, im) { + if (err) throw err; + console.log(im.size()) + if (im.size()[0] > 0 && im.size()[1] > 0){ + window.show(im); + } + window.blockingWaitKey(0, 50); + }); + }, 20); + */ +} catch (e){ + console.log("Couldn't start camera:", e) +} From eccd861a8a8b8b832067e8c840e4a034ff0a2dd4 Mon Sep 17 00:00:00 2001 From: Dmitry Ivanovm Date: Wed, 8 Mar 2017 16:08:58 -0500 Subject: [PATCH 2/7] ~cleanup --- .idea/.name | 1 + .idea/encodings.xml | 6 + .idea/jsLibraryMappings.xml | 6 + .idea/misc.xml | 13 + .idea/modules.xml | 8 + .idea/node-opencv.iml | 8 + .idea/vcs.xml | 6 + .idea/workspace.xml | 723 ++++++++++++++++++++++++++++++++++++ examples/optical-flow.js | 64 +++- src/Matrix.cc | 84 ++++- src/Matrix.h | 1 + src/OpenCV.cc | 2 + 12 files changed, 907 insertions(+), 15 deletions(-) create mode 100644 .idea/.name create mode 100644 .idea/encodings.xml create mode 100644 .idea/jsLibraryMappings.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/node-opencv.iml create mode 100644 .idea/vcs.xml create mode 100644 .idea/workspace.xml diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..f86a829 --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +node-opencv \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..97626ba --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/jsLibraryMappings.xml b/.idea/jsLibraryMappings.xml new file mode 100644 index 0000000..d23208f --- /dev/null +++ b/.idea/jsLibraryMappings.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..72abef0 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..b0727cb --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/node-opencv.iml b/.idea/node-opencv.iml new file mode 100644 index 0000000..c956989 --- /dev/null +++ b/.idea/node-opencv.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000..950cc5f --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,723 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $PROJECT_DIR$ + true + + bdd + + DIRECTORY + + false + + + + + + + + + + + 1488943347282 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/optical-flow.js b/examples/optical-flow.js index 96ce808..9efbd1c 100755 --- a/examples/optical-flow.js +++ b/examples/optical-flow.js @@ -1,20 +1,56 @@ var cv = require('../lib/opencv'); +var path = require('path'); -try { - var camera = new cv.VideoCapture(0); - var window = new cv.NamedWindow('Video', 0) - /* - setInterval(function() { - camera.read(function(err, im) { +var cap = new cv.VideoCapture(path.join(__dirname, 'files', 'motion.mov')); +var window = new cv.NamedWindow('Video', 0); + +// Parameters for lucas kanade optical flow +var lk_params = { + winSize: [15, 15], + maxLevel: 2, + criteria: [cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, 30, 0.03] +}; + +feature_params = { + maxCorners: 100, + qualityLevel: 0.1, + minDistance: 10 +}; + +// Create some random colors +var color = [255, 0, 0]; + +// Take first frame and find corners in it +cap.read(function(err, firstFrame) { + if (err) throw err; + + var old_frame = firstFrame; + + // Create a mask image for drawing purposes + function read() { + var out = old_frame.copy(); + cap.read(function(err, newFrame) { if (err) throw err; - console.log(im.size()) - if (im.size()[0] > 0 && im.size()[1] > 0){ - window.show(im); + + var goodFeatures = old_frame.goodFeaturesToTrack(feature_params.maxCorners, feature_params.qualityLevel, feature_params.minDistance); + + // calculate optical flow + var flow = old_frame.calcOpticalFlowPyrLK(newFrame, goodFeatures, lk_params.winSize, lk_params.maxLevel, lk_params.criteria); + + // Select good points + + // draw the tracks + for(var i = 0; i < flow.old_points.length; i++){ + if(flow.found[i]){ + out.line(flow.old_points[i], flow.new_points[i], color); + } } + window.show(out); window.blockingWaitKey(0, 50); + old_frame = newFrame.copy(); + read(); }); - }, 20); - */ -} catch (e){ - console.log("Couldn't start camera:", e) -} + } + + read(); +}); \ No newline at end of file diff --git a/src/Matrix.cc b/src/Matrix.cc index f0134aa..cda5221 100755 --- a/src/Matrix.cc +++ b/src/Matrix.cc @@ -82,6 +82,7 @@ void Matrix::Init(Local target) { Nan::SetPrototypeMethod(ctor, "drawContour", DrawContour); Nan::SetPrototypeMethod(ctor, "drawAllContours", DrawAllContours); Nan::SetPrototypeMethod(ctor, "goodFeaturesToTrack", GoodFeaturesToTrack); + Nan::SetPrototypeMethod(ctor, "calcOpticalFlowPyrLK", CalcOpticalFlowPyrLK); Nan::SetPrototypeMethod(ctor, "houghLinesP", HoughLinesP); Nan::SetPrototypeMethod(ctor, "houghCircles", HoughCircles); Nan::SetPrototypeMethod(ctor, "inRange", inRange); @@ -1596,13 +1597,17 @@ NAN_METHOD(Matrix::GoodFeaturesToTrack) { Nan::HandleScope scope; Matrix *self = Nan::ObjectWrap::Unwrap(info.This()); + int maxCorners = info.Length() >= 1 ? info[0]->IntegerValue() : 500; + double qualityLevel = info.Length() >= 2 ? (double) info[1]->NumberValue() : 0.01; + double minDistance = info.Length() >= 3 ? (double) info[2]->NumberValue() : 10; + std::vector corners; cv::Mat gray; cvtColor(self->mat, gray, CV_BGR2GRAY); equalizeHist(gray, gray); - cv::goodFeaturesToTrack(gray, corners, 500, 0.01, 10); + cv::goodFeaturesToTrack(gray, corners, maxCorners, qualityLevel, minDistance); v8::Local arr = Nan::New(corners.size()); for (unsigned int i=0; i(info.This()); + Matrix *newMatrix = Nan::ObjectWrap::Unwrap(info[0]->ToObject()); + Local points = Local::Cast(info[1]->ToObject()); + std::vector old_points; + + for (unsigned int i=0; iLength(); i++) { + Local pt = points->Get(i)->ToObject(); + old_points.push_back(cv::Point2f(pt->Get(0)->NumberValue(), pt->Get(1)->NumberValue())); + } + + cv::Size winSize; + if (info.Length() >= 3 && info[2]->IsArray()) { + Local winSizeObj = info[2]->ToObject(); + winSize = cv::Size(winSizeObj->Get(0)->IntegerValue(), winSizeObj->Get(1)->IntegerValue()); + } else { + winSize = cv::Size(21, 21); + } + + int maxLevel = info.Length() >= 4 ? info[3]->IntegerValue() : 3; + + cv::TermCriteria criteria; + if (info.Length() >= 5 && info[4]->IsArray()) { + Local criteriaObj = info[4]->ToObject(); + criteria = cv::TermCriteria(criteriaObj->Get(0)->IntegerValue(), criteriaObj->Get(1)->IntegerValue(), (double) criteriaObj->Get(2)->NumberValue()); + } else { + criteria = cv::TermCriteria(cv::TermCriteria::COUNT + cv::TermCriteria::EPS, 30, 0.01); + } + + int flags = info.Length() >= 6 ? info[5]->IntegerValue() : 0; + double minEigThreshold = info.Length() >= 7 ? info[6]->NumberValue() : 1e-4; + + cv::Mat old_gray; + cv::cvtColor(self->mat, old_gray, CV_BGR2GRAY); + + cv::Mat new_gray; + cv::cvtColor(newMatrix->mat, new_gray, CV_BGR2GRAY); + + std::vector new_points; + std::vector status; + std::vector err; + + cv::calcOpticalFlowPyrLK(old_gray, new_gray, old_points, new_points, status, err, winSize, maxLevel, criteria, flags, minEigThreshold); + + v8::Local old_arr = Nan::New(old_points.size()); + v8::Local new_arr = Nan::New(new_points.size()); + v8::Local found = Nan::New(status.size()); + + for (unsigned int i=0; i pt = Nan::New(2); + pt->Set(0, Nan::New((double) old_points[i].x)); + pt->Set(1, Nan::New((double) old_points[i].y)); + old_arr->Set(i, pt); + } + + for (unsigned int i=0; i pt = Nan::New(2); + pt->Set(0, Nan::New((double) new_points[i].x)); + pt->Set(1, Nan::New((double) new_points[i].y)); + new_arr->Set(i, pt); + } + + for (unsigned int i=0; i pt = Nan::New((int)status[i]); + found->Set(i, pt); + } + + Local data = Nan::New(); + data->Set(Nan::New("old_points").ToLocalChecked(), old_arr); + data->Set(Nan::New("new_points").ToLocalChecked(), new_arr); + data->Set(Nan::New("found").ToLocalChecked(), found); + + info.GetReturnValue().Set(data); +} + NAN_METHOD(Matrix::HoughLinesP) { Nan::HandleScope scope; diff --git a/src/Matrix.h b/src/Matrix.h index b672879..c9a9875 100755 --- a/src/Matrix.h +++ b/src/Matrix.h @@ -89,6 +89,7 @@ public: // Feature Detection JSFUNC(GoodFeaturesToTrack) + JSFUNC(CalcOpticalFlowPyrLK) JSFUNC(HoughLinesP) JSFUNC(HoughCircles) diff --git a/src/OpenCV.cc b/src/OpenCV.cc index c0e666b..9ac5f24 100755 --- a/src/OpenCV.cc +++ b/src/OpenCV.cc @@ -9,6 +9,8 @@ void OpenCV::Init(Local target) { char out [21]; int n = sprintf(out, "%i.%i", CV_MAJOR_VERSION, CV_MINOR_VERSION); target->Set(Nan::New("version").ToLocalChecked(), Nan::New(out, n).ToLocalChecked()); + target->Set(Nan::New("TERM_CRITERIA_EPS").ToLocalChecked(), Nan::New((int)cv::TermCriteria::EPS)); + target->Set(Nan::New("TERM_CRITERIA_COUNT").ToLocalChecked(), Nan::New((int)cv::TermCriteria::COUNT)); Nan::SetMethod(target, "readImage", ReadImage); Nan::SetMethod(target, "readImageMulti", ReadImageMulti); From 2664334a25ab624f33dd2de07623c49377b2874d Mon Sep 17 00:00:00 2001 From: Dmitry Ivanovm Date: Wed, 8 Mar 2017 16:11:31 -0500 Subject: [PATCH 3/7] -.idea --- .idea/.name | 1 - .idea/encodings.xml | 6 - .idea/jsLibraryMappings.xml | 6 - .idea/misc.xml | 13 - .idea/modules.xml | 8 - .idea/node-opencv.iml | 8 - .idea/vcs.xml | 6 - .idea/workspace.xml | 723 ------------------------------------ 8 files changed, 771 deletions(-) delete mode 100644 .idea/.name delete mode 100644 .idea/encodings.xml delete mode 100644 .idea/jsLibraryMappings.xml delete mode 100644 .idea/misc.xml delete mode 100644 .idea/modules.xml delete mode 100644 .idea/node-opencv.iml delete mode 100644 .idea/vcs.xml delete mode 100644 .idea/workspace.xml diff --git a/.idea/.name b/.idea/.name deleted file mode 100644 index f86a829..0000000 --- a/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -node-opencv \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml deleted file mode 100644 index 97626ba..0000000 --- a/.idea/encodings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/jsLibraryMappings.xml b/.idea/jsLibraryMappings.xml deleted file mode 100644 index d23208f..0000000 --- a/.idea/jsLibraryMappings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 72abef0..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index b0727cb..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/node-opencv.iml b/.idea/node-opencv.iml deleted file mode 100644 index c956989..0000000 --- a/.idea/node-opencv.iml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 94a25f7..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml deleted file mode 100644 index 950cc5f..0000000 --- a/.idea/workspace.xml +++ /dev/null @@ -1,723 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - $PROJECT_DIR$ - true - - bdd - - DIRECTORY - - false - - - - - - - - - - - 1488943347282 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file From 6ae96cae3d506557e11ff9da8722f4193fcfd602 Mon Sep 17 00:00:00 2001 From: Dmitry Ivanovm Date: Wed, 8 Mar 2017 16:12:13 -0500 Subject: [PATCH 4/7] +.idea to gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 382b1ae..5639a1e 100755 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ examples/*.avi examples/tmp/* vagrant/.vagrant coverage/ +.idea From 9edf312229fb5da00600a468afed3fa79ee05ba0 Mon Sep 17 00:00:00 2001 From: Dmitry Ivanovm Date: Wed, 8 Mar 2017 16:30:31 -0500 Subject: [PATCH 5/7] ~commented out calls to window functions, trying to fix tests --- examples/optical-flow.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/examples/optical-flow.js b/examples/optical-flow.js index 9efbd1c..9e4b3b3 100755 --- a/examples/optical-flow.js +++ b/examples/optical-flow.js @@ -2,7 +2,6 @@ var cv = require('../lib/opencv'); var path = require('path'); var cap = new cv.VideoCapture(path.join(__dirname, 'files', 'motion.mov')); -var window = new cv.NamedWindow('Video', 0); // Parameters for lucas kanade optical flow var lk_params = { @@ -20,6 +19,10 @@ feature_params = { // Create some random colors var color = [255, 0, 0]; +/* +var window = new cv.NamedWindow('Video', 0); +*/ + // Take first frame and find corners in it cap.read(function(err, firstFrame) { if (err) throw err; @@ -45,8 +48,10 @@ cap.read(function(err, firstFrame) { out.line(flow.old_points[i], flow.new_points[i], color); } } +/* window.show(out); window.blockingWaitKey(0, 50); +*/ old_frame = newFrame.copy(); read(); }); From 833c81d5966ae1570d1d705d60264c5bef3fa147 Mon Sep 17 00:00:00 2001 From: Dmitry Ivanovm Date: Wed, 8 Mar 2017 16:40:59 -0500 Subject: [PATCH 6/7] ~example fixed --- examples/optical-flow.js | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/examples/optical-flow.js b/examples/optical-flow.js index 9e4b3b3..3e2f48b 100755 --- a/examples/optical-flow.js +++ b/examples/optical-flow.js @@ -35,25 +35,31 @@ cap.read(function(err, firstFrame) { cap.read(function(err, newFrame) { if (err) throw err; - var goodFeatures = old_frame.goodFeaturesToTrack(feature_params.maxCorners, feature_params.qualityLevel, feature_params.minDistance); + var frameSize = newFrame.size(); - // calculate optical flow - var flow = old_frame.calcOpticalFlowPyrLK(newFrame, goodFeatures, lk_params.winSize, lk_params.maxLevel, lk_params.criteria); + if ( frameSize[0] > 0 && frameSize[1] > 0) { + var goodFeatures = old_frame.goodFeaturesToTrack(feature_params.maxCorners, feature_params.qualityLevel, feature_params.minDistance); - // Select good points + // calculate optical flow + var flow = old_frame.calcOpticalFlowPyrLK(newFrame, goodFeatures, lk_params.winSize, lk_params.maxLevel, lk_params.criteria); - // draw the tracks - for(var i = 0; i < flow.old_points.length; i++){ - if(flow.found[i]){ - out.line(flow.old_points[i], flow.new_points[i], color); + // Select good points + + // draw the tracks + for(var i = 0; i < flow.old_points.length; i++){ + if(flow.found[i]){ + out.line(flow.old_points[i], flow.new_points[i], color); + } } - } + /* - window.show(out); - window.blockingWaitKey(0, 50); + window.show(out); + window.blockingWaitKey(0, 50); */ - old_frame = newFrame.copy(); - read(); + + old_frame = newFrame.copy(); + read(); + } }); } From dc00de8e2270f66b088cc34379370d94cbf470b3 Mon Sep 17 00:00:00 2001 From: Dmitry Ivanovm Date: Thu, 9 Mar 2017 09:33:01 -0500 Subject: [PATCH 7/7] ~moved TERM constants to constants.cc --- src/Constants.cc | 3 +++ src/OpenCV.cc | 2 -- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Constants.cc b/src/Constants.cc index d6f0ff1..b2ab548 100644 --- a/src/Constants.cc +++ b/src/Constants.cc @@ -101,6 +101,9 @@ void Constants::Init(Local target) { CONST_INT(CV_DIST_MASK_5); CONST_INT(CV_DIST_MASK_PRECISE); + target->Set(Nan::New("TERM_CRITERIA_EPS").ToLocalChecked(), Nan::New((int)cv::TermCriteria::EPS)); + target->Set(Nan::New("TERM_CRITERIA_COUNT").ToLocalChecked(), Nan::New((int)cv::TermCriteria::COUNT)); + target->Set(Nan::New("Constants").ToLocalChecked(), obj); } diff --git a/src/OpenCV.cc b/src/OpenCV.cc index 9ac5f24..c0e666b 100755 --- a/src/OpenCV.cc +++ b/src/OpenCV.cc @@ -9,8 +9,6 @@ void OpenCV::Init(Local target) { char out [21]; int n = sprintf(out, "%i.%i", CV_MAJOR_VERSION, CV_MINOR_VERSION); target->Set(Nan::New("version").ToLocalChecked(), Nan::New(out, n).ToLocalChecked()); - target->Set(Nan::New("TERM_CRITERIA_EPS").ToLocalChecked(), Nan::New((int)cv::TermCriteria::EPS)); - target->Set(Nan::New("TERM_CRITERIA_COUNT").ToLocalChecked(), Nan::New((int)cv::TermCriteria::COUNT)); Nan::SetMethod(target, "readImage", ReadImage); Nan::SetMethod(target, "readImageMulti", ReadImageMulti);