From 056b6cd68e5c80c86b1877fe8234fd7acc0a6190 Mon Sep 17 00:00:00 2001 From: Oskar Dahlberg Date: Thu, 11 Sep 2014 16:59:22 +0200 Subject: [PATCH 01/83] New method for filtering template matches --- src/Matrix.cc | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++- src/Matrix.h | 1 + 2 files changed, 84 insertions(+), 1 deletion(-) diff --git a/src/Matrix.cc b/src/Matrix.cc index 8dfc6697..e3384499 100755 --- a/src/Matrix.cc +++ b/src/Matrix.cc @@ -96,7 +96,8 @@ Matrix::Init(Handle target) { NODE_SET_PROTOTYPE_METHOD(constructor, "floodFill", FloodFill); - NODE_SET_PROTOTYPE_METHOD(constructor, "matchTemplate", MatchTemplate); + NODE_SET_PROTOTYPE_METHOD(constructor, "matchTemplate", MatchTemplate); + NODE_SET_PROTOTYPE_METHOD(constructor, "templateMatches", TemplateMatches); NODE_SET_PROTOTYPE_METHOD(constructor, "minMaxLoc", MinMaxLoc); NODE_SET_PROTOTYPE_METHOD(constructor, "pushBack", PushBack); @@ -1719,6 +1720,87 @@ Matrix::FloodFill(const Arguments& args){ return scope.Close(Number::New( ret )); } +// @author olfox +// Returns an array of the most probable positions +// Usage: output = input.templateMatches(min_probability, max_probability, limit, ascending, min_x_distance, min_y_distance); +Handle +Matrix::TemplateMatches(const v8::Arguments& args) { + HandleScope scope; + + Matrix *self = ObjectWrap::Unwrap(args.This()); + + bool filter_min_probability = (args.Length() >= 1) ? args[0]->IsNumber() : false; + bool filter_max_probability = (args.Length() >= 2) ? args[1]->IsNumber() : false; + double min_probability = filter_min_probability ? args[0]->NumberValue() : 0; + double max_probability = filter_max_probability ? args[1]->NumberValue() : 0; + int limit = (args.Length() >= 3) ? args[2]->IntegerValue() : 0; + bool ascending = (args.Length() >= 4) ? args[3]->BooleanValue() : false; + int min_x_distance = (args.Length() >= 5) ? args[4]->IntegerValue() : 0; + int min_y_distance = (args.Length() >= 6) ? args[5]->IntegerValue() : 0; + + cv::Mat_ indices; + + if (ascending) + cv::sortIdx(self->mat.reshape(0,1), indices, CV_SORT_ASCENDING + CV_SORT_EVERY_ROW); + else + cv::sortIdx(self->mat.reshape(0,1), indices, CV_SORT_DESCENDING + CV_SORT_EVERY_ROW); + + cv::Mat hit_mask = cv::Mat::zeros(self->mat.size(), CV_64F); + v8::Local probabilites_array = v8::Array::New(); + + cv::Mat_::const_iterator begin = self->mat.begin(); + cv::Mat_::const_iterator it = indices.begin(); + cv::Mat_::const_iterator end = indices.end(); + int index = 0; + for (; (limit == 0 || index < limit) && it != end; ++it) { + cv::Point pt = (begin + *it).pos(); + + float probability = self->mat.at(pt.y, pt.x); + + if (filter_min_probability && probability < min_probability) { + if (ascending) continue; + else break; + } + + if (filter_max_probability && probability > max_probability) { + if (ascending) break; + else continue; + } + + if (min_x_distance != 0 || min_y_distance != 0) { + // Check hit mask color for for every corner + + 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)); + if (hit_mask.at(top_left.y, top_left.x) > 0) continue; + if (hit_mask.at(top_right.y, top_right.x) > 0) continue; + if (hit_mask.at(bottom_left.y, bottom_left.x) > 0) continue; + if (hit_mask.at(bottom_right.y, bottom_right.x) > 0) continue; + cv::Scalar color(255.0); + cv::rectangle(hit_mask, top_left, bottom_right, color, CV_FILLED); + } + + Local x_value = v8::Number::New(pt.x); + Local y_value = v8::Number::New(pt.y); + Local probability_value = v8::Number::New(probability); + + Local probability_object = Object::New(); + probability_object->Set(String::NewSymbol("x"), x_value); + probability_object->Set(String::NewSymbol("y"), y_value); + probability_object->Set(String::NewSymbol("probability"), probability_value); + + probabilites_array->Set(index, probability_object); + index++; + } + + return scope.Close(probabilites_array); +} + // @author ytham // Match Template filter // Usage: output = input.matchTemplate(templateMatrix, method); diff --git a/src/Matrix.h b/src/Matrix.h index 3331e44e..083ac6a9 100755 --- a/src/Matrix.h +++ b/src/Matrix.h @@ -91,6 +91,7 @@ class Matrix: public node::ObjectWrap { JSFUNC(FloodFill) JSFUNC(MatchTemplate) + JSFUNC(TemplateMatches) JSFUNC(MinMaxLoc) JSFUNC(PushBack) From 18394814abe407fc7d71e3ba499a7053e1d422fb Mon Sep 17 00:00:00 2001 From: Peter Braden Date: Wed, 15 Oct 2014 20:01:44 +0200 Subject: [PATCH 02/83] Failing examples tests --- examples/addweighted.js | 4 ++-- package.json | 3 ++- test/examples.js | 16 ++++++++++++++++ test/unit.js | 4 ++++ 4 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 test/examples.js diff --git a/examples/addweighted.js b/examples/addweighted.js index dc9379ff..a8774dcb 100755 --- a/examples/addweighted.js +++ b/examples/addweighted.js @@ -1,9 +1,9 @@ var cv = require('../lib/opencv'); -cv.readImage("./files/mona.png", function(err, orig) { +cv.readImage("./examples/files/mona.png", function(err, orig) { if (err) throw err; - cv.readImage("./files/over_text.png", function(err, over_text) { + cv.readImage("./examples/over_text.png", function(err, over_text) { if (err) throw err; var result = new cv.Matrix(orig.width(), orig.height()); diff --git a/package.json b/package.json index 4405141d..551560f2 100755 --- a/package.json +++ b/package.json @@ -8,7 +8,8 @@ }, "version": "1.0.0", "devDependencies": { - "tape": "^3.0.0" + "tape": "^3.0.0", + "glob": "^4.0.6" }, "license": "MIT", "scripts": { diff --git a/test/examples.js b/test/examples.js new file mode 100644 index 00000000..b48a743c --- /dev/null +++ b/test/examples.js @@ -0,0 +1,16 @@ +var test = require('tape') + , glob = require('glob') + , exec = require('child_process').exec + +module.exports = function(){ + + glob.sync('./examples/*.js').forEach(function(example){ + test("Example: " + example, function(assert){ + exec('node ' + example, function(error, stdout, stderr){ + assert.error(error) + assert.end() + }) + }) + }) + +} diff --git a/test/unit.js b/test/unit.js index ac5609d2..5bb051f5 100755 --- a/test/unit.js +++ b/test/unit.js @@ -275,3 +275,7 @@ test("fonts", function(t) { }); }) +// Test the examples folder. +require('./examples')() + + From 7ebb4d70de563e049f33e807cd5c9500c0ec0e6c Mon Sep 17 00:00:00 2001 From: Peter Braden Date: Wed, 15 Oct 2014 20:04:03 +0200 Subject: [PATCH 03/83] fix warp image example --- examples/warp-image.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/warp-image.js b/examples/warp-image.js index 5b6d32d2..bcf13b86 100644 --- a/examples/warp-image.js +++ b/examples/warp-image.js @@ -1,6 +1,6 @@ var cv = require('../lib/opencv'); -cv.readImage("./mona.png", function(err, im) { +cv.readImage("./examples/files/mona.png", function(err, im) { if (err) throw err; var width = im.width(); @@ -11,6 +11,6 @@ cv.readImage("./mona.png", function(err, im) { var dstArray = [0, 0, width * 0.9, height * 0.1, width, height, width * 0.2, height * 0.8]; var xfrmMat = im.getPerspectiveTransform(srcArray, dstArray); im.warpPerspective(xfrmMat, width, height, [255, 255, 255]); - im.save("./warp-image.png"); + im.save("./examples/tmp/warp-image.png"); console.log('Image saved to ./tmp/warp-image.png'); }); From c42422a71554a767a2a9cdd4c05cba4abc308b2b Mon Sep 17 00:00:00 2001 From: Peter Braden Date: Wed, 15 Oct 2014 20:13:29 +0200 Subject: [PATCH 04/83] Catch OpenCV exception in nodeland --- src/Matrix.cc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Matrix.cc b/src/Matrix.cc index 49789531..05312c9d 100755 --- a/src/Matrix.cc +++ b/src/Matrix.cc @@ -1013,7 +1013,12 @@ NAN_METHOD(Matrix::AddWeighted) { float beta = args[3]->NumberValue(); int gamma = 0; - cv::addWeighted(src1->mat, alpha, src2->mat, beta, gamma, self->mat); + try{ + cv::addWeighted(src1->mat, alpha, src2->mat, beta, gamma, self->mat); + } catch(cv::Exception& e ){ + const char* err_msg = e.what(); + NanThrowError(err_msg); + } NanReturnNull(); From ea7f25962c5d050839234637eae4d8dfb863546e Mon Sep 17 00:00:00 2001 From: Peter Braden Date: Wed, 15 Oct 2014 20:15:29 +0200 Subject: [PATCH 05/83] Fix addweighted --- examples/addweighted.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/addweighted.js b/examples/addweighted.js index a8774dcb..ac6c309d 100755 --- a/examples/addweighted.js +++ b/examples/addweighted.js @@ -3,12 +3,12 @@ var cv = require('../lib/opencv'); cv.readImage("./examples/files/mona.png", function(err, orig) { if (err) throw err; - cv.readImage("./examples/over_text.png", function(err, over_text) { + cv.readImage("./examples/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("./tmp/weighted.png"); - console.log('Image saved to ./tmp/weighted.png'); + result.save("./examples/tmp/weighted.png"); + console.log('Image saved to ./examples/tmp/weighted.png'); }); }); From a4af50daf7bebc49bb4216813bd5064163975cd0 Mon Sep 17 00:00:00 2001 From: Peter Braden Date: Wed, 15 Oct 2014 20:17:31 +0200 Subject: [PATCH 06/83] fix face-proxy --- examples/face-proxy.js | 7 +++++-- package.json | 3 ++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/examples/face-proxy.js b/examples/face-proxy.js index 541ba7b4..307c64fe 100755 --- a/examples/face-proxy.js +++ b/examples/face-proxy.js @@ -3,7 +3,7 @@ var http = require('http'), request = require('request'), cv = require('../lib/opencv'); -http.createServer(function(req, resp){ +var server = http.createServer(function(req, resp){ var url = req.url.slice(1); request({uri:url, encoding:'binary'}, function(err, r, body){ if (err) return resp.end(err.stack); @@ -27,4 +27,7 @@ http.createServer(function(req, resp){ }); }); -}).listen(3000, function(){ console.log('Listening on http://localhost:3000'); }) +}) + + +//server.listen(3000, function(){ console.log('Listening on http://localhost:3000'); }) diff --git a/package.json b/package.json index 551560f2..4438fcad 100755 --- a/package.json +++ b/package.json @@ -9,7 +9,8 @@ "version": "1.0.0", "devDependencies": { "tape": "^3.0.0", - "glob": "^4.0.6" + "glob": "^4.0.6", + "request": "^2.45.0" }, "license": "MIT", "scripts": { From 97875da492c6f64b00441206c4b0df51dbd91c38 Mon Sep 17 00:00:00 2001 From: Peter Braden Date: Wed, 15 Oct 2014 20:31:19 +0200 Subject: [PATCH 07/83] fix window error --- examples/camera.js | 8 ++++++-- examples/face-detection-rectangle.js | 8 ++++---- src/HighGUI.cc | 8 +++++++- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/examples/camera.js b/examples/camera.js index abe885bb..25b02464 100755 --- a/examples/camera.js +++ b/examples/camera.js @@ -2,11 +2,15 @@ var cv = require('../lib/opencv'); var camera = new cv.VideoCapture(0); var window = new cv.NamedWindow('Video', 0) - +/* setInterval(function() { camera.read(function(err, im) { if (err) throw err; - window.show(im); + console.log(im.size()) + if (im.size()[0] > 0 && im.size()[1] > 0){ + window.show(im); + } window.blockingWaitKey(0, 50); }); }, 20); +*/ diff --git a/examples/face-detection-rectangle.js b/examples/face-detection-rectangle.js index f108eee9..e2d4f873 100755 --- a/examples/face-detection-rectangle.js +++ b/examples/face-detection-rectangle.js @@ -3,11 +3,11 @@ var cv = require('../lib/opencv'); var COLOR = [0, 255, 0]; // default red var thickness = 2; // default 1 -cv.readImage('./files/mona.png', function(err, im) { +cv.readImage('./examples/files/mona.png', function(err, im) { if (err) throw err; if (im.width() < 1 || im.height() < 1) throw new Error('Image has no size'); - im.detectObject('../data/haarcascade_frontalface_alt2.xml', {}, function(err, faces) { + im.detectObject('./data/haarcascade_frontalface_alt2.xml', {}, function(err, faces) { if (err) throw err; for (var i = 0; i < faces.length; i++) { @@ -15,8 +15,8 @@ cv.readImage('./files/mona.png', function(err, im) { im.rectangle([face.x, face.y], [face.x + face.width, face.y + face.height], COLOR, 2); } - im.save('./tmp/face-detection-rectangle.png'); - console.log('Image saved to ./tmp/face-detection-rectangle.png'); + im.save('./examples/tmp/face-detection-rectangle.png'); + console.log('Image saved to ./examples/tmp/face-detection-rectangle.png'); }); }); diff --git a/src/HighGUI.cc b/src/HighGUI.cc index bb1197b4..3b99c9ef 100644 --- a/src/HighGUI.cc +++ b/src/HighGUI.cc @@ -53,7 +53,13 @@ NamedWindow::NamedWindow(const std::string& name, int f){ NAN_METHOD(NamedWindow::Show){ SETUP_FUNCTION(NamedWindow) Matrix *im = ObjectWrap::Unwrap(args[0]->ToObject()); - cv::imshow(self->winname, im->mat); + + try{ + cv::imshow(self->winname, im->mat); + } catch(cv::Exception& e ){ + const char* err_msg = e.what(); + NanThrowError(err_msg); + } NanReturnValue(args.Holder()); } From d5021b1bcccba00ae60c7dff3ab305dc608cc383 Mon Sep 17 00:00:00 2001 From: Peter Braden Date: Wed, 15 Oct 2014 20:33:49 +0200 Subject: [PATCH 08/83] quad crossess example fixed --- examples/quad-crosses.js | 2 +- examples/take-face-pics.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/quad-crosses.js b/examples/quad-crosses.js index 341631f2..e56f4cbf 100755 --- a/examples/quad-crosses.js +++ b/examples/quad-crosses.js @@ -12,7 +12,7 @@ var RED = [0, 0, 255]; //B, G, R var GREEN = [0, 255, 0]; //B, G, R var WHITE = [255, 255, 255]; //B, G, R -cv.readImage('./files/quads.jpg', function(err, im) { +cv.readImage('./examples/files/quads.jpg', function(err, im) { if (err) throw err; if (im.width() < 1 || im.height() < 1) throw new Error('Image has no size'); diff --git a/examples/take-face-pics.js b/examples/take-face-pics.js index 418809b4..36e8831f 100644 --- a/examples/take-face-pics.js +++ b/examples/take-face-pics.js @@ -18,7 +18,7 @@ vid.read(function(err, im){ , -face.x , (face.x + face.width) - ims[1]) */ - im2.save('./tmp/take-face-pics.jpg') + im2.save('./examples/tmp/take-face-pics.jpg') console.log('Image saved to ./tmp/take-face-pics.jpg'); }) }); From 9b3b82fbbee838160c39c9816befa86cc3590a6a Mon Sep 17 00:00:00 2001 From: Peter Braden Date: Wed, 15 Oct 2014 20:38:17 +0200 Subject: [PATCH 09/83] fix convert image (crop was missing) and other file paths --- examples/convert-image.js | 12 ++++++------ examples/detect-shapes.js | 6 +++--- examples/face-detection.js | 8 ++++---- examples/quad-crosses.js | 4 ++-- src/Matrix.cc | 1 + 5 files changed, 16 insertions(+), 15 deletions(-) diff --git a/examples/convert-image.js b/examples/convert-image.js index 7f62ff3d..dbc9f0c2 100755 --- a/examples/convert-image.js +++ b/examples/convert-image.js @@ -1,6 +1,6 @@ var cv = require('../lib/opencv'); -cv.readImage('./files/mona.png', function(err, im) { +cv.readImage('./examples/files/mona.png', function(err, im) { if (err) throw err; if (im.width() < 1 || im.height() < 1) throw new Error('Image has no size'); @@ -10,12 +10,12 @@ cv.readImage('./files/mona.png', function(err, im) { img_hsv.convertHSVscale(); img_gray.convertGrayscale(); - im.save('./tmp/nor.png'); - img_hsv.save('./tmp/hsv.png'); - img_gray.save('./tmp/gray.png'); + im.save('./examples/tmp/nor.png'); + img_hsv.save('./examples/tmp/hsv.png'); + img_gray.save('./examples/tmp/gray.png'); img_crop = im.crop(50,50,250,250); - img_crop.save('./tmp/crop.png'); + img_crop.save('./examples/tmp/crop.png'); - console.log('Image saved to ./tmp/{crop|nor|hsv|gray}.png'); + console.log('Image saved to ./examples/tmp/{crop|nor|hsv|gray}.png'); }); diff --git a/examples/detect-shapes.js b/examples/detect-shapes.js index f465d235..63269959 100755 --- a/examples/detect-shapes.js +++ b/examples/detect-shapes.js @@ -12,7 +12,7 @@ var GREEN = [0, 255, 0]; // B, G, R var WHITE = [255, 255, 255]; // B, G, R -cv.readImage('./files/shapes.jpg', function(err, im) { +cv.readImage('./examples/files/shapes.jpg', function(err, im) { if (err) throw err; width = im.width() @@ -46,6 +46,6 @@ cv.readImage('./files/shapes.jpg', function(err, im) { } } - out.save('./tmp/detect-shapes.png'); - console.log('Image saved to ./tmp/detect-shapes.png'); + out.save('./examples/tmp/detect-shapes.png'); + console.log('Image saved to ./examples/tmp/detect-shapes.png'); }); diff --git a/examples/face-detection.js b/examples/face-detection.js index 0cc5fee1..185a78b5 100755 --- a/examples/face-detection.js +++ b/examples/face-detection.js @@ -1,10 +1,10 @@ var cv = require('../lib/opencv'); -cv.readImage("./files/mona.png", function(err, im){ +cv.readImage("./examples/files/mona.png", function(err, im){ if (err) throw err; if (im.width() < 1 || im.height() < 1) throw new Error('Image has no size'); - im.detectObject("../data/haarcascade_frontalface_alt.xml", {}, function(err, faces){ + im.detectObject("./data/haarcascade_frontalface_alt.xml", {}, function(err, faces){ if (err) throw err; for (var i = 0; i < faces.length; i++){ @@ -12,7 +12,7 @@ cv.readImage("./files/mona.png", function(err, im){ im.ellipse(face.x + face.width / 2, face.y + face.height / 2, face.width / 2, face.height / 2); } - im.save('./tmp/face-detection.png'); - console.log('Image saved to ./tmp/face-detection.png'); + im.save('./examples/tmp/face-detection.png'); + console.log('Image saved to ./examples/tmp/face-detection.png'); }); }); diff --git a/examples/quad-crosses.js b/examples/quad-crosses.js index e56f4cbf..1a3a558c 100755 --- a/examples/quad-crosses.js +++ b/examples/quad-crosses.js @@ -47,6 +47,6 @@ cv.readImage('./examples/files/quads.jpg', function(err, im) { out.line([points[1].x,points[1].y], [points[3].x, points[3].y], RED); } - out.save('./tmp/quad-crosses.png'); - console.log('Image saved to ./tmp/quad-crosses.png'); + out.save('./examples/tmp/quad-crosses.png'); + console.log('Image saved to ./examples/tmp/quad-crosses.png'); }); diff --git a/src/Matrix.cc b/src/Matrix.cc index 05312c9d..9f57b481 100755 --- a/src/Matrix.cc +++ b/src/Matrix.cc @@ -68,6 +68,7 @@ Matrix::Init(Handle target) { NODE_SET_PROTOTYPE_METHOD(ctor, "drawAllContours", DrawAllContours); NODE_SET_PROTOTYPE_METHOD(ctor, "goodFeaturesToTrack", GoodFeaturesToTrack); NODE_SET_PROTOTYPE_METHOD(ctor, "houghLinesP", HoughLinesP); + NODE_SET_PROTOTYPE_METHOD(ctor, "crop", Crop); NODE_SET_PROTOTYPE_METHOD(ctor, "inRange", inRange); NODE_SET_PROTOTYPE_METHOD(ctor, "adjustROI", AdjustROI); NODE_SET_PROTOTYPE_METHOD(ctor, "locateROI", LocateROI); From 1659f7ef1aa36e685f317826ad4e1846127327fa Mon Sep 17 00:00:00 2001 From: Peter Braden Date: Wed, 15 Oct 2014 20:42:44 +0200 Subject: [PATCH 10/83] All examples now run without erroring --- README.md | 1 + examples/car-detection.js | 8 ++++---- examples/color-filter.js | 4 ++-- examples/contours.js | 8 ++++---- examples/take-face-pics.js | 37 +++++++++++++++++++++---------------- 5 files changed, 32 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 80607586..babcb83d 100755 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ $ npm install opencv ``` ## Examples +Run the examples from the parent directory. ### Face Detection diff --git a/examples/car-detection.js b/examples/car-detection.js index 58c2d61f..95a5afa8 100644 --- a/examples/car-detection.js +++ b/examples/car-detection.js @@ -1,10 +1,10 @@ var cv = require('../lib/opencv'); -cv.readImage("./files/car1.jpg", function(err, im){ +cv.readImage("./examples/files/car1.jpg", function(err, im){ if (err) throw err; if (im.width() < 1 || im.height() < 1) throw new Error('Image has no size'); - im.detectObject("../data/hogcascade_cars_sideview.xml", {}, function(err, cars){ + im.detectObject("./data/hogcascade_cars_sideview.xml", {}, function(err, cars){ if (err) throw err; for (var i=0; i < cars.length; i++){ @@ -12,7 +12,7 @@ cv.readImage("./files/car1.jpg", function(err, im){ im.rectangle([x.x, x.y], [x.width, x.height]); } - im.save('./tmp/car-detection.jpg'); - console.log('Image saved to ./tmp/car-detection.jpg'); + im.save('./examples/tmp/car-detection.jpg'); + console.log('Image saved to ./examples/tmp/car-detection.jpg'); }); }); diff --git a/examples/color-filter.js b/examples/color-filter.js index b7c5d6a9..031b65d2 100644 --- a/examples/color-filter.js +++ b/examples/color-filter.js @@ -4,11 +4,11 @@ var cv = require('../lib/opencv'); var lower_threshold = [46, 57, 83]; var upper_threshold = [80, 96, 115]; -cv.readImage('./files/coin1.jpg', function(err, im) { +cv.readImage('./examples/files/coin1.jpg', function(err, im) { if (err) throw err; if (im.width() < 1 || im.height() < 1) throw new Error('Image has no size'); im.inRange(lower_threshold, upper_threshold); - im.save('./tmp/coin_detected.jpg'); + im.save('./examples/tmp/coin_detected.jpg'); console.log('Image saved to ./tmp/coin_detected.jpg'); }); diff --git a/examples/contours.js b/examples/contours.js index 43bb0ac4..842011e3 100755 --- a/examples/contours.js +++ b/examples/contours.js @@ -9,7 +9,7 @@ var GREEN = [0, 255, 0]; // B, G, R var WHITE = [255, 255, 255]; // B, G, R var RED = [0, 0, 255]; // B, G, R -cv.readImage('./files/stuff.png', function(err, im) { +cv.readImage('./examples/files/stuff.png', function(err, im) { if (err) throw err; var width = im.width(); var height = im.height(); @@ -39,7 +39,7 @@ cv.readImage('./files/stuff.png', function(err, im) { all.drawAllContours(contours, WHITE); - big.save('./tmp/big.png'); - all.save('./tmp/all.png'); - console.log('Image saved to ./tmp/big.png && ./tmp/all.png'); + big.save('./examples/tmp/big.png'); + all.save('./examples/tmp/all.png'); + console.log('Image saved to ./examples/tmp/big.png && ./tmp/all.png'); }); diff --git a/examples/take-face-pics.js b/examples/take-face-pics.js index 36e8831f..2c61ebe5 100644 --- a/examples/take-face-pics.js +++ b/examples/take-face-pics.js @@ -4,21 +4,26 @@ var vid = new cv.VideoCapture(0); vid.read(function(err, im){ if (err) throw err; - im.detectObject(cv.FACE_CASCADE, {}, function(err, faces){ - if (err) throw err; - if (!faces.length) return console.log("No Faces"); + if (im.size()[0] > 0 && im.size()[1] > 0){ - var face = faces[0]; - var ims = im.size(); - var im2 = im.roi(face.x, face.y, face.width, face.height) - /* - im.adjustROI( - -face.y - , (face.y + face.height) - ims[0] - , -face.x - , (face.x + face.width) - ims[1]) - */ - im2.save('./examples/tmp/take-face-pics.jpg') - console.log('Image saved to ./tmp/take-face-pics.jpg'); - }) + im.detectObject(cv.FACE_CASCADE, {}, function(err, faces){ + if (err) throw err; + if (!faces.length) return console.log("No Faces"); + + var face = faces[0]; + var ims = im.size(); + var im2 = im.roi(face.x, face.y, face.width, face.height) + /* + im.adjustROI( + -face.y + , (face.y + face.height) - ims[0] + , -face.x + , (face.x + face.width) - ims[1]) + */ + im2.save('./examples/tmp/take-face-pics.jpg') + console.log('Image saved to ./tmp/take-face-pics.jpg'); + }) + } else { + console.log("Camera didn't return image") + } }); From a62456f47bdd0e07220f9dfde547d3366ff162a2 Mon Sep 17 00:00:00 2001 From: Peter Braden Date: Wed, 15 Oct 2014 20:59:46 +0200 Subject: [PATCH 11/83] Don't assume a camera --- examples/camera.js | 32 +++++++++++++---------- examples/take-face-pics.js | 53 ++++++++++++++++++++------------------ 2 files changed, 46 insertions(+), 39 deletions(-) diff --git a/examples/camera.js b/examples/camera.js index 25b02464..96ce8086 100755 --- a/examples/camera.js +++ b/examples/camera.js @@ -1,16 +1,20 @@ var cv = require('../lib/opencv'); -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); -*/ +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) +} diff --git a/examples/take-face-pics.js b/examples/take-face-pics.js index 2c61ebe5..79167d67 100644 --- a/examples/take-face-pics.js +++ b/examples/take-face-pics.js @@ -1,29 +1,32 @@ var cv = require('../lib/opencv'); -var vid = new cv.VideoCapture(0); +try { + var vid = new cv.VideoCapture(0); -vid.read(function(err, im){ - if (err) throw err; + vid.read(function(err, im){ + if (err) throw err; + if (im.size()[0] > 0 && im.size()[1] > 0){ - if (im.size()[0] > 0 && im.size()[1] > 0){ + im.detectObject(cv.FACE_CASCADE, {}, function(err, faces){ + if (err) throw err; + if (!faces.length) return console.log("No Faces"); - im.detectObject(cv.FACE_CASCADE, {}, function(err, faces){ - if (err) throw err; - if (!faces.length) return console.log("No Faces"); - - var face = faces[0]; - var ims = im.size(); - var im2 = im.roi(face.x, face.y, face.width, face.height) - /* - im.adjustROI( - -face.y - , (face.y + face.height) - ims[0] - , -face.x - , (face.x + face.width) - ims[1]) - */ - im2.save('./examples/tmp/take-face-pics.jpg') - console.log('Image saved to ./tmp/take-face-pics.jpg'); - }) - } else { - console.log("Camera didn't return image") - } -}); + var face = faces[0]; + var ims = im.size(); + var im2 = im.roi(face.x, face.y, face.width, face.height) + /* + im.adjustROI( + -face.y + , (face.y + face.height) - ims[0] + , -face.x + , (face.x + face.width) - ims[1]) + */ + im2.save('./examples/tmp/take-face-pics.jpg') + console.log('Image saved to ./tmp/take-face-pics.jpg'); + }) + } else { + console.log("Camera didn't return image") + } + }); +} catch (e){ + console.log("Couldn't start camera", e) +} From a903162a5cca1e37d0b4064ece993f2723e6d134 Mon Sep 17 00:00:00 2001 From: edgarsilva Date: Mon, 3 Nov 2014 11:09:08 -0600 Subject: [PATCH 12/83] Add pre compiled binaries for all 3 major platforms. --- .travis.yml | 64 +++++++++++++++++++++++++-- appveyor.yml | 103 ++++++++++++++++++++++++++++++++++++++++++++ binding.gyp | 21 +++++++++ lib/bindings.js | 8 +++- package.json | 15 ++++++- utils/opencv_x64.pc | 12 ++++++ utils/opencv_x86.pc | 12 ++++++ 7 files changed, 229 insertions(+), 6 deletions(-) create mode 100644 appveyor.yml create mode 100644 utils/opencv_x64.pc create mode 100644 utils/opencv_x86.pc diff --git a/.travis.yml b/.travis.yml index eae5110b..d9cfb7ce 100755 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,68 @@ language: node_js + node_js: - - "0.10" - - "0.11" + - '0.10' + - '0.11' + +compiler: clang + +env: + global: + - secure: v7yz4KwR5+Iv7+oPs54wAK6/fYp7xnEDmbbr2z5F2i8NaG5Qvi4AGwfRuPTLNAeFhpapzL8wk8LI4NfxChUe2S1Rj9ytpW350wtHNcIEBiJXsbfKBeHCZQcZnlx+KofmuP//BRjO3kiVgilOxuLvVbdA9Ob/6ixAdKTHl0yk+NA= + - secure: ehjkxVYyBwL9dZAD1w/D3oEN2lWQebN44CnrftTYw0xVPiYsNeCKV0SpTs/RIlhhiVlQjZRmZbt+My213q32vYdKGEv4TGyyiSfy3BQz+hkXb5vCtxS0WZjfQpxcApYlh9bLh4LzvCcEXe6RrdLSApTXVh9PPiKVGBPtZjLXfZU= before_install: - - sudo apt-get update + # Fix a problem with apt-get failing later, see http://docs.travis-ci.com/user/installing-dependencies/#Installing-Ubuntu-packages + - sudo apt-get update -qq - sudo apt-get install libcv-dev - sudo apt-get install libopencv-dev - sudo apt-get install libhighgui-dev + # get commit message + - COMMIT_MESSAGE=$(git show -s --format=%B $TRAVIS_COMMIT | tr -d '\n') + # put local node-pre-gyp on PATH + - export PATH=./node_modules/.bin/:$PATH + # install node-pre-gyp so it is available for packaging and publishing + - npm install node-gyp -g + # install node-pre-gyp so it is available for packaging and publishing + - npm install node-pre-gyp + # install aws-sdk so it is available for publishing to AS3 + - npm install aws-sdk + # figure out if we should publish + - PUBLISH_BINARY=false + # if we are building a tag then publish + - if [[ $TRAVIS_BRANCH == `git describe --tags --always HEAD` ]]; then PUBLISH_BINARY=true; fi; + # or if we put [publish binary] in the commit message + - if test "${COMMIT_MESSAGE#*'[publish binary]'}" != "$COMMIT_MESSAGE"; then PUBLISH_BINARY=true; fi; + - 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 + +before_script: + - echo "Publishing native platform Binary Package? ->" $PUBLISH_BINARY + # if publishing, do it + - if [[ $PUBLISH_BINARY == true ]]; then node-pre-gyp package publish; fi; + # cleanup + - node-pre-gyp clean + - node-gyp clean + - sudo apt-get purge libcv-dev + - sudo apt-get purge libopencv-dev + - sudo apt-get purge libhighgui-dev + +script: + # if publishing, test installing from remote + - INSTALL_RESULT=0 + - if [[ $PUBLISH_BINARY == true ]]; then INSTALL_RESULT=$(npm install --fallback-to-build=false > /dev/null)$? || true; fi; + # if install returned non zero (errored) then we first unpublish and then call false so travis will bail at this line + - if [[ $INSTALL_RESULT != 0 ]]; then echo "returned $INSTALL_RESULT";node-pre-gyp unpublish;false; fi + # If success then we arrive here so lets clean up + - node-pre-gyp clean + # Can't compile opencv 32bit in 64 bit env. + +after_success: + # if success then query and display all published binaries + - node-pre-gyp info diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 00000000..256371e4 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,103 @@ +# environment variables +environment: + node_pre_gyp_accessKeyId: + secure: hTQMi31kndQOPU0AZVkVXgH7Vc3EjJmvThFwMYhkno4= + node_pre_gyp_secretAccessKey: + secure: ZOsWmB5rxfiPgPW5bCuvkK1UUEupssSoHfK5jWcJBJsPuPWQHEWOr1lUteVbx2NV + +# try on unstable version of the server to build node-opencv +os: unstable + +# to add several platforms to build matrix: +platform: + - x64 + +install: + - cmd: ECHO "INSTALL OPENCV:" + - cmd: choco install OpenCV + - cmd: ECHO "APPVEYOR_REPO_COMMIT_MESSAGE ->" + - cmd: ECHO %APPVEYOR_REPO_COMMIT_MESSAGE% + - cmd: SET COMMIT_MSG="%APPVEYOR_REPO_COMMIT_MESSAGE%" + - cmd: SET PUBLISH_BINARY=false + # Check to verify the branch is the same than latest tag, if so + # then we publish the binaries if everything else is successful. + - cmd: git describe --tags --always HEAD > _git_tag.tmp + - cmd: SET /p GIT_TAG=<_git_tag.tmp + - cmd: ECHO "LATEST LOCAL TAG:" + - cmd: ECHO %GIT_TAG% + - cmd: ECHO "APPVEYOR REPO BRANCH/TAG:" + - cmd: ECHO %APPVEYOR_REPO_BRANCH% + - cmd: DEL _git_tag.tmp + - cmd: IF x%APPVEYOR_REPO_BRANCH%==x%GIT_TAG% SET PUBLISH_BINARY=true + # Or look for commit message containing `[publish binary]` + - cmd: IF not x%COMMIT_MSG:[publish binary]=%==x%COMMIT_MSG% SET PUBLISH_BINARY=true + - cmd: ECHO "Env Var PUBLISH_BINARY:" + - cmd: ECHO %PUBLISH_BINARY% + - cmd: git clone https://github.com/marcelklehr/nodist.git c:\nodist 2>&1 + - cmd: SET PATH=C:\nodist\bin;%PATH% + - cmd: SET NODIST_PREFIX=C:\nodist + +before_build: + - cmd: SET ARCH=x64 + - cmd: SET NODIST_X64=1 + - cmd: call nodist update + - cmd: call nodist stable + - cmd: npm install -g node-gyp + - cmd: SET APP_PATH=%CD% + - cmd: IF EXIST C:\OpenCV* CD C:\OpenCV* + - cmd: SET OPENCV_ROOT_PATH=%CD%\opencv + - cmd: CD %APP_PATH% + - cmd: SET OPENCV_DIR=%OPENCV_ROOT_PATH%\build\%ARCH%\vc12\bin + - cmd: SET PATH=%cd%\node_modules\.bin\;C:\MinGW\bin;C:\GTK\bin;C:\msys\1.0\bin;%OPENCV_DIR%;%PATH% + - cmd: SET PKG_CONFIG_PATH=C:\GTK\lib\pkgconfig + # Here we need to copy the opencv.pc file from the repo into PKG_CONFIG_PATH + # trick part is to check for the vc12 folder and use that one + - cmd: copy .\utils\opencv_x64.pc C:\GTK\lib\pkgconfig\opencv.pc + +# to run your custom scripts instead of automatic MSBuild +build_script: + - cmd: ECHO "BUILDING x64 binary package:" + - cmd: npm install --build-from-source --msvs_version=2013 + - cmd: npm test + - cmd: node lib/opencv.js + - cmd: ECHO "PUBLISH x64 binary package:" + - cmd: npm install aws-sdk + - cmd: IF %PUBLISH_BINARY%==true (node-pre-gyp package publish 2>&1) + - cmd: node-pre-gyp clean + - cmd: node-gyp clean + - cmd: npm uninstall -g node-gyp + - cmd: rmdir /q /s node_modules + - cmd: DEL C:\GTK\lib\pkgconfig\opencv.pc + +after_build: + - cmd: SET ARCH=x86 + - cmd: SET OPENCV_DIR=%OPENCV_ROOT_PATH%\build\%ARCH%\vc12\bin + - cmd: SET PATH=%OPENCV_DIR%;%PATH% + - cmd: SET NODIST_X64=0 + - cmd: call nodist update + - cmd: call nodist stable + - cmd: npm install -g node-gyp + - cmd: copy .\utils\opencv_x86.pc C:\GTK\lib\pkgconfig\opencv.pc + - cmd: ECHO "BUILDING x86 binary package:" + - cmd: npm install --build-from-source --msvs_version=2013 + - cmd: npm test + - cmd: node lib/opencv.js + - cmd: ECHO "PUBLISH x86 binary package:" + - cmd: npm install aws-sdk + - cmd: IF %PUBLISH_BINARY%==true (node-pre-gyp package publish 2>&1) + - cmd: node-pre-gyp clean + - cmd: node-gyp clean + - cmd: rmdir /q /s node_modules + +on_success: + # test installing from binary package works + - cmd: ECHO "ON SUCCESS:" + - cmd: ECHO "Try installing from binary:" + #- cmd: IF %PUBLISH_BINARY%==true npm install --fallback-to-build=false + - cmd: npm install --fallback-to-build=false + # Print Available Binaries + - cmd: node-pre-gyp info + +test: OFF + +deploy: OFF diff --git a/binding.gyp b/binding.gyp index aa089a68..f5b41684 100755 --- a/binding.gyp +++ b/binding.gyp @@ -32,6 +32,16 @@ , 'cflags!' : [ '-fno-exceptions'] , 'cflags_cc!': [ '-fno-rtti', '-fno-exceptions'] , "conditions": [ + ['OS=="win"', + { + 'msvs_settings': { + 'VCCLCompilerTool': { + 'ExceptionHandling': '2', + 'DisableSpecificWarnings': [ '4530', '4506', '4244' ], + }, + }, + }, + ], ['OS=="mac"', { # cflags on OS X are stupid and have to be defined like this 'xcode_settings': { @@ -47,5 +57,16 @@ }] ] + }, + { + "target_name": "action_after_build", + "type": "none", + "dependencies": [ "<(module_name)" ], + "copies": [ + { + "files": [ "<(PRODUCT_DIR)/<(module_name).node" ], + "destination": "<(module_path)" + } + ] }] } diff --git a/lib/bindings.js b/lib/bindings.js index 83e0b2e8..4acd6c2f 100755 --- a/lib/bindings.js +++ b/lib/bindings.js @@ -1 +1,7 @@ -module.exports = require('../build/Release/opencv.node'); +var binary = require('node-pre-gyp'); +var path = require('path'); +var binding_path = binary.find(path.resolve(path.join(__dirname,'../package.json'))); +var binding = require(binding_path); + +//module.exports = require('../build/Release/opencv.node'); +module.exports = binding; diff --git a/package.json b/package.json index 4405141d..b6998649 100755 --- a/package.json +++ b/package.json @@ -3,17 +3,21 @@ "description": "Node Bindings to OpenCV", "author": "Peter Braden ", "dependencies": { + "node-pre-gyp": "0.5.31", "buffers": "0.1.1", "nan": "^1.3.0" }, "version": "1.0.0", "devDependencies": { - "tape": "^3.0.0" + "tape": "^3.0.0", + "aws-sdk": "~2.0.21" }, + "bundledDependencies":["node-pre-gyp"], "license": "MIT", "scripts": { "build": "node-gyp build", - "test": "node test/unit.js" + "test": "node test/unit.js", + "install": "node-pre-gyp install --fallback-to-build" }, "keywords": [ "opencv", @@ -28,5 +32,12 @@ }, "engines": { "node": ">=0.10" + }, + "binary": { + "module_name" : "opencv", + "module_path" : "./build/{module_name}/v{version}/{configuration}/{node_abi}-{platform}-{arch}/", + "remote_path" : "./{module_name}/v{version}/{configuration}/", + "package_name": "{node_abi}-{platform}-{arch}.tar.gz", + "host" : "https://node-opencv.s3.amazonaws.com" } } diff --git a/utils/opencv_x64.pc b/utils/opencv_x64.pc new file mode 100644 index 00000000..cf1fa63a --- /dev/null +++ b/utils/opencv_x64.pc @@ -0,0 +1,12 @@ +# Package Information for pkg-config +opencv_prefix=C:/OpenCV249/opencv/build/x64/vc12 +exec_prefix=${opencv_prefix}/bin +libdir=${opencv_prefix}/lib +includedir=C:/OpenCV249/opencv/build/include + +Name: OpenCV +Description: Open Source Computer Vision Library +Version: 2.4.9 + +Cflags: ${includedir} ${includedir}/opencv +Libs: ${libdir}/opencv_core249 ${libdir}/opencv_imgproc249 ${libdir}/opencv_highgui249 ${libdir}/opencv_ml249 ${libdir}/opencv_video249 ${libdir}/opencv_features2d249 ${libdir}/opencv_calib3d249 ${libdir}/opencv_objdetect249 ${libdir}/opencv_contrib249 ${libdir}/opencv_legacy249 ${libdir}/opencv_flann249 ${libdir}/opencv_core249 diff --git a/utils/opencv_x86.pc b/utils/opencv_x86.pc new file mode 100644 index 00000000..7b993fc2 --- /dev/null +++ b/utils/opencv_x86.pc @@ -0,0 +1,12 @@ +# Package Information for pkg-config +opencv_prefix=C:/OpenCV249/opencv/build/x86/vc12 +exec_prefix=${opencv_prefix}/bin +libdir=${opencv_prefix}/lib +includedir=C:/OpenCV249/opencv/build/include + +Name: OpenCV +Description: Open Source Computer Vision Library +Version: 2.4.9 + +Cflags: ${includedir} ${includedir}/opencv +Libs: ${libdir}/opencv_core249 ${libdir}/opencv_imgproc249 ${libdir}/opencv_highgui249 ${libdir}/opencv_ml249 ${libdir}/opencv_video249 ${libdir}/opencv_features2d249 ${libdir}/opencv_calib3d249 ${libdir}/opencv_objdetect249 ${libdir}/opencv_contrib249 ${libdir}/opencv_legacy249 ${libdir}/opencv_flann249 ${libdir}/opencv_core249 From ce159e15e00ef92ad13607818ab7bde8341ac334 Mon Sep 17 00:00:00 2001 From: edgarsilva Date: Mon, 3 Nov 2014 18:33:34 -0600 Subject: [PATCH 13/83] Added new release make task to simplify publishing binaries and releasing to npm. Added publish-binary.md file to have as a reference on the process of making a release and publishing the binaries. --- Makefile | 30 +++++++++++++++++++++ publish-binaries.md | 64 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 Makefile create mode 100644 publish-binaries.md diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..129b06f6 --- /dev/null +++ b/Makefile @@ -0,0 +1,30 @@ +VERSION := $(shell node -e "console.log(require('./package.json').version)") + +.PHONY: default release + +# Add a default task so we don't release just because someone ran 'make' +default: + @echo "Did you mean to release a new version?" + @echo "If so, run 'make release'." + +release: + @echo "Tagging release $(VERSION)" + @git tag -m "$(VERSION)" v$(VERSION) + + @echo "Pushing tags to GitHub" + @git push --tags + + @echo "Switching to osx-binaries branch" + @git checkout osx-binaries + + @echo "Merging master into osx-binaries" + @git merge --no-ff --commit -m "Merge master into osx-binaries [publish binary]" master + + @echo "Pushing osx-binaries" + @git push + + @echo "Switching to master branch" + @git checkout master + + @echo "Publishing to NPM" + @npm publish diff --git a/publish-binaries.md b/publish-binaries.md new file mode 100644 index 00000000..0a441a89 --- /dev/null +++ b/publish-binaries.md @@ -0,0 +1,64 @@ +How to publish the pre compiled binaries. +========================================= + +## Setup for Linux, Windows and OSX + +Every time a new tag for the latest release is pushed to github the continous integration +builds in Travis-CI and AppVeyor will generate the binaries for each platform and architecture, +package and publish to the AS3 bucket. + +This can be checked in the .travis.yml file and appveyor.yml file. Within the files there are two +methods for publishing new binaries for each version, one is if a `git tag` is detected; the other +can be triggered by passing the string `[publish binary]` in the commit message itself. + +We also have an automated make task, we should always use this task to avoid forgetting any steps +(like merging into the `osx-binaries` branch). + +The process for generating the binaries, publishing and releasing the npm module should be as follows: + +1. Merge all changes and new features into master. +2. Bump up version of npm module in `package.json`. +3. execute make task: `make release` + +This task will do the following for you: + +1. Generate new tags based on package.json version number +2. Push tags to Github +3. Checkout into `osx-binaries` branch +4. Merge `master` into `osx-binaries` +5. Push `osx-binaries` +6. Checkout master +7. Finally it will run `npm publish` + +With this we will make sure the binaries for all platforms and architectures will be generated each time +a new version is released. + + +## Config Travis, AppVeyor and Github to generate all of the binaries. + +Before we are able to run everything stated above some steps need to be taken. +Specifically for being able to publish the pre compiled binaries to AWS-S3. The +correct keys need to be setup in the travis and appveyor `.yml` files. This needs +to be done by the admin of the repo, in the case of Travis, and the owner of the account, +in the case of appveyor. + +### Setting up secure keys in Travis. + +Setting up the keys in Travis is easy if you have ruby and ruby gems installed and working then install: + +`gem install travis` + +After the travis gem is installed run the following command for each of the required keys: + +`travis encrypt SOMEVAR=secretvalue` + +And substitute the values in the `.travis.yml` file for the new ones. Detailed instructions can +be found here: http://docs.travis-ci.com/user/environment-variables/#Secure-Variables + +### Setting up secure keys in AppVeyor + +It is even easier than Travis, you do not need to install anything, just go to your account and +click in `encrypt tool`, there enter the values in the input field and click encrypt. Same as with +Travis we then need to substitute the newly generated values for the old ones. + +Detaild instructions can be found here: http://www.appveyor.com/docs/build-configuration#secure-variables From 74cc0546a8d466188f97f9650ddfdf6eeb1caa7d Mon Sep 17 00:00:00 2001 From: edgarsilva Date: Mon, 3 Nov 2014 18:43:48 -0600 Subject: [PATCH 14/83] Added info on how to create and name the branch to generate the OSX binaries --- publish-binaries.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/publish-binaries.md b/publish-binaries.md index 0a441a89..d2ea375f 100644 --- a/publish-binaries.md +++ b/publish-binaries.md @@ -61,4 +61,11 @@ It is even easier than Travis, you do not need to install anything, just go to y click in `encrypt tool`, there enter the values in the input field and click encrypt. Same as with Travis we then need to substitute the newly generated values for the old ones. -Detaild instructions can be found here: http://www.appveyor.com/docs/build-configuration#secure-variables +Detailed instructions can be found here: http://www.appveyor.com/docs/build-configuration#secure-variables + +### OSX binaries + +Since Travis does not support config file for multiple OSs we need to create a new branch that contains +a slightly different version of the .travis.yml file to compile for OSX. The branch needs to be called +`osx-binaries` and be based of `master` once the pre-compiled binaries PR has been merged in. + From f90d623adc65bfda240446b502894f83c894c942 Mon Sep 17 00:00:00 2001 From: Pieter De Bruyne Date: Tue, 9 Dec 2014 19:59:56 +0100 Subject: [PATCH 15/83] fixed Crop prototype --- src/Matrix.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Matrix.cc b/src/Matrix.cc index 4e97c645..4cad4173 100755 --- a/src/Matrix.cc +++ b/src/Matrix.cc @@ -32,6 +32,7 @@ Matrix::Init(Handle target) { NODE_SET_PROTOTYPE_METHOD(ctor, "height", Height); NODE_SET_PROTOTYPE_METHOD(ctor, "size", Size); NODE_SET_PROTOTYPE_METHOD(ctor, "clone", Clone); + NODE_SET_PROTOTYPE_METHOD(ctor, "crop", Crop); NODE_SET_PROTOTYPE_METHOD(ctor, "toBuffer", ToBuffer); NODE_SET_PROTOTYPE_METHOD(ctor, "toBufferAsync", ToBufferAsync); NODE_SET_PROTOTYPE_METHOD(ctor, "ellipse", Ellipse); From 094d91eeceea3617ce3ffd0c6f0635a1b26c96f6 Mon Sep 17 00:00:00 2001 From: edgarsilva Date: Tue, 23 Dec 2014 12:45:33 -0600 Subject: [PATCH 16/83] update cflags opencv version in bindings.gyp --- binding.gyp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/binding.gyp b/binding.gyp index f5b41684..3d16eedf 100755 --- a/binding.gyp +++ b/binding.gyp @@ -26,7 +26,7 @@ ] , 'cflags': [ - '= 2.3.1" )' + '= 2.4.9" )' , '-Wall' ] , 'cflags!' : [ '-fno-exceptions'] From 73cddc81de423cc44943169aaf737ebd59d99ac7 Mon Sep 17 00:00:00 2001 From: Micah Elizabeth Scott Date: Fri, 16 Jan 2015 12:11:05 -0800 Subject: [PATCH 17/83] In setRect(), don't return a pointer to stack memory Noticed a compiler warning for this during build, and the code looks like the sort of thing that may often work accidentally, but is not at all guaranteed to work. This is the simplest fix I could imagine; keep the logic about whether to return NULL or not in setRect(), but pass it a reference to some memory in the caller's stack frame to use for the result. This fixes the warning, but I haven't had a chance to verify functionality. --- src/Matrix.cc | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Matrix.cc b/src/Matrix.cc index 4cad4173..fbee02cd 100755 --- a/src/Matrix.cc +++ b/src/Matrix.cc @@ -7,7 +7,7 @@ v8::Persistent Matrix::constructor; cv::Scalar setColor(Local objColor); cv::Point setPoint(Local objPoint); -cv::Rect* setRect(Local objRect); +cv::Rect* setRect(Local objRect, cv::Rect &result); void Matrix::Init(Handle target) { @@ -1310,7 +1310,7 @@ cv::Point setPoint(Local objPoint) { return cv::Point( objPoint->Get(0)->IntegerValue(), objPoint->Get(1)->IntegerValue() ); } -cv::Rect* setRect(Local objRect) { +cv::Rect* setRect(Local objRect, cv::Rect &result) { if(!objRect->IsArray() || !objRect->Get(0)->IsArray() || !objRect->Get(0)->IsArray() ){ printf("error"); @@ -1319,14 +1319,13 @@ cv::Rect* setRect(Local objRect) { Local point = objRect->Get(0)->ToObject(); Local size = objRect->Get(1)->ToObject(); - cv::Rect ret; - ret.x = point->Get(0)->IntegerValue(); - ret.y = point->Get(1)->IntegerValue(); - ret.width = size->Get(0)->IntegerValue(); - ret.height = size->Get(1)->IntegerValue(); + result.x = point->Get(0)->IntegerValue(); + result.y = point->Get(1)->IntegerValue(); + result.width = size->Get(0)->IntegerValue(); + result.height = size->Get(1)->IntegerValue(); - return (cv::Rect*) &ret; + return &result; } @@ -1714,10 +1713,11 @@ NAN_METHOD(Matrix::FloodFill){ Local obj = args[0]->ToObject(); + cv::Rect rect; int ret = cv::floodFill(self->mat, setPoint(obj->Get(NanNew("seedPoint"))->ToObject()) , setColor(obj->Get(NanNew("newColor"))->ToObject()) - , obj->Get(NanNew("rect"))->IsUndefined() ? 0 : setRect(obj->Get(NanNew("rect"))->ToObject()) + , obj->Get(NanNew("rect"))->IsUndefined() ? 0 : setRect(obj->Get(NanNew("rect"))->ToObject(), rect) , setColor(obj->Get(NanNew("loDiff"))->ToObject()) , setColor(obj->Get(NanNew("upDiff"))->ToObject()) , 4 ); From 85c3a90db71d8498c3728e3b4244da0fd20f6737 Mon Sep 17 00:00:00 2001 From: Micah Elizabeth Scott Date: Fri, 16 Jan 2015 12:13:45 -0800 Subject: [PATCH 18/83] Fix compile errors with ambiguous signedness in NanNew param This fixes two instances of a compile error I'd been getting with OpenCV 2.4.9 (via Homebrew) on Mac OS: ../node_modules/nan/nan_new.h:184:10: error: call to 'New' is ambiguous return NanIntern::Factory::New(arg0); ^~~~~~~~~~~~~~~~~~~~~~~~~~ ../src/Matrix.cc:453:51: note: in instantiation of function template specialization 'NanNew' requested here v8::Handle constructorArgs[3] = {buf, NanNew(vec.size()), NanNew(0)}; ^ ../node_modules/nan/nan_new.h:86:26: note: candidate function static inline return_t New(int32_t value); ^ ../node_modules/nan/nan_new.h:87:26: note: candidate function static inline return_t New(uint32_t value); --- src/Matrix.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Matrix.cc b/src/Matrix.cc index fbee02cd..91faa07e 100755 --- a/src/Matrix.cc +++ b/src/Matrix.cc @@ -452,7 +452,7 @@ NAN_METHOD(Matrix::ToBuffer){ v8::Local globalObj = NanGetCurrentContext()->Global(); v8::Local bufferConstructor = v8::Local::Cast(globalObj->Get(NanNew("Buffer"))); - v8::Handle constructorArgs[3] = {buf, NanNew(vec.size()), NanNew(0)}; + v8::Handle constructorArgs[3] = {buf, NanNew((unsigned)vec.size()), NanNew(0)}; v8::Local actualBuffer = bufferConstructor->NewInstance(3, constructorArgs); NanReturnValue(actualBuffer); @@ -485,7 +485,7 @@ class AsyncToBufferWorker : public NanAsyncWorker { v8::Local globalObj = NanGetCurrentContext()->Global(); v8::Local bufferConstructor = v8::Local::Cast(globalObj->Get(NanNew("Buffer"))); - v8::Handle constructorArgs[3] = {buf, NanNew(res.size()), NanNew(0)}; + v8::Handle constructorArgs[3] = {buf, NanNew((unsigned)res.size()), NanNew(0)}; v8::Local actualBuffer = bufferConstructor->NewInstance(3, constructorArgs); From 702cd7a992f49d5d6356b75e5d64c893056a37b9 Mon Sep 17 00:00:00 2001 From: Fille Date: Sat, 17 Jan 2015 23:08:18 +0100 Subject: [PATCH 19/83] Forced nan to 1.4.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4405141d..7ce4b0a6 100755 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "author": "Peter Braden ", "dependencies": { "buffers": "0.1.1", - "nan": "^1.3.0" + "nan": "1.4.3" }, "version": "1.0.0", "devDependencies": { From 97715a8048aa8be714451d578cc29cbf0190eff6 Mon Sep 17 00:00:00 2001 From: Max Ehrlich Date: Mon, 19 Jan 2015 15:15:05 -0500 Subject: [PATCH 20/83] Added findChessboardCorners function --- src/OpenCV.cc | 94 +++++++++++++++++++++++++++++++++++++++++++++------ src/OpenCV.h | 3 +- 2 files changed, 86 insertions(+), 11 deletions(-) diff --git a/src/OpenCV.cc b/src/OpenCV.cc index 4ed6c43f..24f594b8 100755 --- a/src/OpenCV.cc +++ b/src/OpenCV.cc @@ -5,48 +5,49 @@ void OpenCV::Init(Handle target) { NanScope(); - + // Version string. char out [21]; int n = sprintf(out, "%i.%i", CV_MAJOR_VERSION, CV_MINOR_VERSION); target->Set(NanNew("version"), NanNew(out, n)); NODE_SET_METHOD(target, "readImage", ReadImage); + NODE_SET_METHOD(target, "findChessboardCorners", FindChessboardCorners); -} +} NAN_METHOD(OpenCV::ReadImage) { NanEscapableScope(); try{ - + Local im_h = NanNew(Matrix::constructor)->GetFunction()->NewInstance(); Matrix *img = ObjectWrap::Unwrap(im_h); - + cv::Mat mat; REQ_FUN_ARG(1, cb); - + if (args[0]->IsNumber() && args[1]->IsNumber()){ int width, height; width = args[0]->Uint32Value(); - height = args[1]->Uint32Value(); + height = args[1]->Uint32Value(); mat = *(new cv::Mat(width, height, CV_64FC1)); } else if (args[0]->IsString()) { - + std::string filename = std::string(*NanAsciiString(args[0]->ToString())); mat = cv::imread(filename); } else if (Buffer::HasInstance(args[0])){ uint8_t *buf = (uint8_t *) Buffer::Data(args[0]->ToObject()); unsigned len = Buffer::Length(args[0]->ToObject()); - + cv::Mat *mbuf = new cv::Mat(len, 1, CV_64FC1, buf); mat = cv::imdecode(*mbuf, -1); - + if (mat.empty()){ NanThrowTypeError("Error loading file"); } @@ -74,4 +75,77 @@ NAN_METHOD(OpenCV::ReadImage) { NanThrowError(err_msg); NanReturnUndefined(); } -}; +}; + +NAN_METHOD(OpenCV::FindChessboardCorners) { + NanEscapableScope(); + + try { + // Get the arguments from javascript + + // Arg 0 is the image + Matrix* m = ObjectWrap::Unwrap(args[0]->ToObject()); + cv::Mat mat = m->mat; + + // Arg 1 is the pattern size + cv::Size patternSize; + if (args[1]->IsArray()) { + Local v8sz = args[1]->ToObject(); + + patternSize = cv::Size(v8sz->Get(0)->IntegerValue(), v8sz->Get(1)->IntegerValue()); + } else { + JSTHROW_TYPE("Must pass pattern size"); + } + + // Arg 2 would normally be the flags, ignoring this for now and using the default flags + + // Final argument is the callback function + REQ_FUN_ARG(2, cb); + + // Find the corners + std::vector corners; + bool found = cv::findChessboardCorners(mat, patternSize, corners); + + // Make the callback arguments + Local argv[2]; + + argv[0] = NanNull(); + argv[1] = NanNull(); // This will be replaced by the corners array if corners were found + + // Further processing if we found corners + Local cornersArray; + if(found) + { + // Convert the return value to a javascript array + cornersArray = Array::New(corners.size()); + for(int i = 0; i < corners.size(); i++) + { + Local point_data = NanNew(); + point_data->Set(NanNew("x"), NanNew(corners[i].x)); + point_data->Set(NanNew("y"), NanNew(corners[i].y)); + + cornersArray->Set(Number::New(i), point_data); + } + + argv[1] = cornersArray; + } + + // Callback + TryCatch try_catch; + + cb->Call(NanGetCurrentContext()->Global(), 2, argv); + + if(try_catch.HasCaught()) { + FatalException(try_catch); + } + + NanReturnUndefined(); + + + } catch (cv::Exception &e) { + const char *err_msg = e.what(); + NanThrowError(err_msg); + NanReturnUndefined(); + } + +}; diff --git a/src/OpenCV.h b/src/OpenCV.h index ea1ca835..b8a53ab1 100755 --- a/src/OpenCV.h +++ b/src/OpenCV.h @@ -50,9 +50,10 @@ class OpenCV: public node::ObjectWrap{ static void Init(Handle target); static NAN_METHOD(ReadImage); + + static NAN_METHOD(FindChessboardCorners); }; #endif - From e35698ac16913569c7daf05b09f68ec1c771acdb Mon Sep 17 00:00:00 2001 From: Max Ehrlich Date: Tue, 20 Jan 2015 09:37:52 -0500 Subject: [PATCH 21/83] Moved findChessboardCorners to calib3d source file --- binding.gyp | 1 + src/Calib3D.cc | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/Calib3D.h | 15 +++++++++ src/OpenCV.cc | 75 ------------------------------------------ src/OpenCV.h | 2 -- src/init.cc | 7 ++-- 6 files changed, 108 insertions(+), 80 deletions(-) create mode 100644 src/Calib3D.cc create mode 100644 src/Calib3D.h diff --git a/binding.gyp b/binding.gyp index aa089a68..6e56fc9a 100755 --- a/binding.gyp +++ b/binding.gyp @@ -14,6 +14,7 @@ , "src/FaceRecognizer.cc" , "src/BackgroundSubtractor.cc" , "src/Constants.cc" + , "src/Calib3D.cc" ] , 'libraries': [ ' target) +{ + Persistent inner; + Local obj = NanNew(); + NanAssignPersistent(inner, obj); + + NODE_SET_METHOD(obj, "findChessboardCorners", FindChessboardCorners); + + target->Set(NanNew("calib3d"), obj); +} + +// cv::findChessboardCorners +NAN_METHOD(Calib3D::FindChessboardCorners) +{ + NanEscapableScope(); + + try { + // Get the arguments from javascript + + // Arg 0 is the image + Matrix* m = ObjectWrap::Unwrap(args[0]->ToObject()); + cv::Mat mat = m->mat; + + // Arg 1 is the pattern size + cv::Size patternSize; + if (args[1]->IsArray()) { + Local v8sz = args[1]->ToObject(); + + patternSize = cv::Size(v8sz->Get(0)->IntegerValue(), v8sz->Get(1)->IntegerValue()); + } else { + JSTHROW_TYPE("Must pass pattern size"); + } + + // Arg 2 would normally be the flags, ignoring this for now and using the default flags + + // Final argument is the callback function + REQ_FUN_ARG(2, cb); + + // Find the corners + std::vector corners; + bool found = cv::findChessboardCorners(mat, patternSize, corners); + + // Make the callback arguments + Local argv[2]; + + argv[0] = NanNull(); + argv[1] = NanNull(); // This will be replaced by the corners array if corners were found + + // Further processing if we found corners + Local cornersArray; + if(found) + { + // Convert the return value to a javascript array + cornersArray = Array::New(corners.size()); + for(unsigned int i = 0; i < corners.size(); i++) + { + Local point_data = NanNew(); + point_data->Set(NanNew("x"), NanNew(corners[i].x)); + point_data->Set(NanNew("y"), NanNew(corners[i].y)); + + cornersArray->Set(Number::New(i), point_data); + } + + argv[1] = cornersArray; + } + + // Callback + TryCatch try_catch; + + cb->Call(NanGetCurrentContext()->Global(), 2, argv); + + if(try_catch.HasCaught()) { + FatalException(try_catch); + } + + NanReturnUndefined(); + + + } catch (cv::Exception &e) { + const char *err_msg = e.what(); + NanThrowError(err_msg); + NanReturnUndefined(); + } + +}; diff --git a/src/Calib3D.h b/src/Calib3D.h new file mode 100644 index 00000000..e8bba46f --- /dev/null +++ b/src/Calib3D.h @@ -0,0 +1,15 @@ +#ifndef __NODE_CALIB3D_H +#define __NODE_CALIB3D_H + +#include "OpenCV.h" + +// Implementation of calib3d.hpp functions + +class Calib3D: public node::ObjectWrap { +public: + static void Init(Handle target); + + static NAN_METHOD(FindChessboardCorners); +}; + +#endif diff --git a/src/OpenCV.cc b/src/OpenCV.cc index 24f594b8..6ebdf018 100755 --- a/src/OpenCV.cc +++ b/src/OpenCV.cc @@ -12,8 +12,6 @@ OpenCV::Init(Handle target) { target->Set(NanNew("version"), NanNew(out, n)); NODE_SET_METHOD(target, "readImage", ReadImage); - NODE_SET_METHOD(target, "findChessboardCorners", FindChessboardCorners); - } @@ -76,76 +74,3 @@ NAN_METHOD(OpenCV::ReadImage) { NanReturnUndefined(); } }; - -NAN_METHOD(OpenCV::FindChessboardCorners) { - NanEscapableScope(); - - try { - // Get the arguments from javascript - - // Arg 0 is the image - Matrix* m = ObjectWrap::Unwrap(args[0]->ToObject()); - cv::Mat mat = m->mat; - - // Arg 1 is the pattern size - cv::Size patternSize; - if (args[1]->IsArray()) { - Local v8sz = args[1]->ToObject(); - - patternSize = cv::Size(v8sz->Get(0)->IntegerValue(), v8sz->Get(1)->IntegerValue()); - } else { - JSTHROW_TYPE("Must pass pattern size"); - } - - // Arg 2 would normally be the flags, ignoring this for now and using the default flags - - // Final argument is the callback function - REQ_FUN_ARG(2, cb); - - // Find the corners - std::vector corners; - bool found = cv::findChessboardCorners(mat, patternSize, corners); - - // Make the callback arguments - Local argv[2]; - - argv[0] = NanNull(); - argv[1] = NanNull(); // This will be replaced by the corners array if corners were found - - // Further processing if we found corners - Local cornersArray; - if(found) - { - // Convert the return value to a javascript array - cornersArray = Array::New(corners.size()); - for(int i = 0; i < corners.size(); i++) - { - Local point_data = NanNew(); - point_data->Set(NanNew("x"), NanNew(corners[i].x)); - point_data->Set(NanNew("y"), NanNew(corners[i].y)); - - cornersArray->Set(Number::New(i), point_data); - } - - argv[1] = cornersArray; - } - - // Callback - TryCatch try_catch; - - cb->Call(NanGetCurrentContext()->Global(), 2, argv); - - if(try_catch.HasCaught()) { - FatalException(try_catch); - } - - NanReturnUndefined(); - - - } catch (cv::Exception &e) { - const char *err_msg = e.what(); - NanThrowError(err_msg); - NanReturnUndefined(); - } - -}; diff --git a/src/OpenCV.h b/src/OpenCV.h index b8a53ab1..2dc32e56 100755 --- a/src/OpenCV.h +++ b/src/OpenCV.h @@ -50,8 +50,6 @@ class OpenCV: public node::ObjectWrap{ static void Init(Handle target); static NAN_METHOD(ReadImage); - - static NAN_METHOD(FindChessboardCorners); }; diff --git a/src/init.cc b/src/init.cc index eb8b79ac..2486e075 100755 --- a/src/init.cc +++ b/src/init.cc @@ -9,21 +9,22 @@ #include "HighGUI.h" #include "FaceRecognizer.h" #include "Constants.h" - +#include "Calib3D.h" extern "C" void init(Handle target) { NanScope(); OpenCV::Init(target); - + Point::Init(target); Matrix::Init(target); CascadeClassifierWrap::Init(target); VideoCaptureWrap::Init(target); Contour::Init(target); - TrackedObject::Init(target); + TrackedObject::Init(target); NamedWindow::Init(target); Constants::Init(target); + Calib3D::Init(target); #if CV_MAJOR_VERSION >= 2 && CV_MINOR_VERSION >=4 From 088b44bdeb31d780defc23304e4cc0aac1ac1c30 Mon Sep 17 00:00:00 2001 From: Max Ehrlich Date: Tue, 20 Jan 2015 10:19:28 -0500 Subject: [PATCH 22/83] Added drawChessboardCorners --- src/Calib3D.cc | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/Calib3D.h | 2 ++ 2 files changed, 72 insertions(+) diff --git a/src/Calib3D.cc b/src/Calib3D.cc index 240c431a..512b5249 100644 --- a/src/Calib3D.cc +++ b/src/Calib3D.cc @@ -8,6 +8,7 @@ void Calib3D::Init(Handle target) NanAssignPersistent(inner, obj); NODE_SET_METHOD(obj, "findChessboardCorners", FindChessboardCorners); + NODE_SET_METHOD(obj, "drawChessboardCorners", DrawChessboardCorners); target->Set(NanNew("calib3d"), obj); } @@ -86,3 +87,72 @@ NAN_METHOD(Calib3D::FindChessboardCorners) } }; + +// cv::drawChessboardCorners +NAN_METHOD(Calib3D::DrawChessboardCorners) +{ + NanEscapableScope(); + + try { + // Get the arguments + + // Arg 0 is the image + Matrix* m = ObjectWrap::Unwrap(args[0]->ToObject()); + cv::Mat mat = m->mat; + + // Arg 1 is the pattern size + cv::Size patternSize; + if (args[1]->IsArray()) { + Local v8sz = args[1]->ToObject(); + + patternSize = cv::Size(v8sz->Get(0)->IntegerValue(), v8sz->Get(1)->IntegerValue()); + } else { + JSTHROW_TYPE("Must pass pattern size"); + } + + // Arg 2 is the corners array + std::vector corners; + if(args[2]->IsArray()) { + Local cornersArray = Local::Cast(args[2]); + + for(unsigned int i = 0; i < cornersArray->Length(); i++) + { + Local pt = cornersArray->Get(i)->ToObject(); + corners.push_back(cv::Point2f(pt->Get(NanNew("x"))->ToNumber()->Value(), + pt->Get(NanNew("y"))->ToNumber()->Value())); + } + } else { + JSTHROW_TYPE("Must pass corners array"); + } + + // Arg 3, pattern found boolean + bool patternWasFound = args[3]->ToBoolean()->Value(); + + // Final argument is the callback + REQ_FUN_ARG(4, cb); + + // Draw the corners + cv::drawChessboardCorners(mat, patternSize, corners, patternWasFound); + + // Make the callback arguments (same image that was passed, now with corners drawn on it) + Local argv[2]; + argv[0] = NanNull(); + argv[1] = args[0]; + + // Callback + TryCatch try_catch; + + cb->Call(NanGetCurrentContext()->Global(), 2, argv); + + if(try_catch.HasCaught()) { + FatalException(try_catch); + } + + NanReturnUndefined(); + + } catch (cv::Exception &e) { + const char *err_msg = e.what(); + NanThrowError(err_msg); + NanReturnUndefined(); + } +} diff --git a/src/Calib3D.h b/src/Calib3D.h index e8bba46f..14ecc99b 100644 --- a/src/Calib3D.h +++ b/src/Calib3D.h @@ -10,6 +10,8 @@ class Calib3D: public node::ObjectWrap { static void Init(Handle target); static NAN_METHOD(FindChessboardCorners); + + static NAN_METHOD(DrawChessboardCorners); }; #endif From 0c3597695005055f608ae1e80c4eaa699e979cef Mon Sep 17 00:00:00 2001 From: Max Ehrlich Date: Tue, 20 Jan 2015 13:04:22 -0500 Subject: [PATCH 23/83] Added calibrateCamera function --- src/Calib3D.cc | 108 +++++++++++++++++++++++++++++++++++++++++++++++++ src/Calib3D.h | 2 + 2 files changed, 110 insertions(+) diff --git a/src/Calib3D.cc b/src/Calib3D.cc index 512b5249..f8a1fcc1 100644 --- a/src/Calib3D.cc +++ b/src/Calib3D.cc @@ -9,6 +9,7 @@ void Calib3D::Init(Handle target) NODE_SET_METHOD(obj, "findChessboardCorners", FindChessboardCorners); NODE_SET_METHOD(obj, "drawChessboardCorners", DrawChessboardCorners); + NODE_SET_METHOD(obj, "calibrateCamera", CalibrateCamera); target->Set(NanNew("calib3d"), obj); } @@ -156,3 +157,110 @@ NAN_METHOD(Calib3D::DrawChessboardCorners) NanReturnUndefined(); } } + +// cv::calibrateCamera +NAN_METHOD(Calib3D::CalibrateCamera) +{ + NanEscapableScope(); + + try { + // Get the arguments + + // Arg 0, the array of object points, an array of arrays + std::vector > objectPoints; + if(args[0]->IsArray()) { + Local objectPointsArray = Local::Cast(args[0]); + + for(unsigned int i = 0; i < objectPointsArray->Length(); i++) + { + std::vector points; + + Local pointsArray = Local::Cast(objectPointsArray->Get(i)); + for(unsigned int j = 0; j < pointsArray->Length(); j++) + { + Local pt = pointsArray->Get(j)->ToObject(); + points.push_back(cv::Point3f(pt->Get(NanNew("x"))->ToNumber()->Value(), + pt->Get(NanNew("y"))->ToNumber()->Value(), + pt->Get(NanNew("z"))->ToNumber()->Value())); + } + + objectPoints.push_back(points); + } + } else { + JSTHROW_TYPE("Must pass array of object points for each frame") + } + + // Arg 1, the image points, another array of arrays =( + std::vector > imagePoints; + if(args[1]->IsArray()) { + Local imagePointsArray = Local::Cast(args[1]); + + for(unsigned int i = 0; i < imagePointsArray->Length(); i++) + { + std::vector points; + + Local pointsArray = Local::Cast(imagePointsArray->Get(i)); + for(unsigned int j = 0; j < pointsArray->Length(); j++) + { + Local pt = pointsArray->Get(j)->ToObject(); + points.push_back(cv::Point2f(pt->Get(NanNew("x"))->ToNumber()->Value(), + pt->Get(NanNew("y"))->ToNumber()->Value())); + } + + imagePoints.push_back(points); + } + } else { + JSTHROW_TYPE("Must pass array of object points for each frame") + } + + // Arg 2, the image size + cv::Size imageSize; + if (args[2]->IsArray()) { + Local v8sz = args[2]->ToObject(); + + imageSize = cv::Size(v8sz->Get(0)->IntegerValue(), v8sz->Get(1)->IntegerValue()); + } else { + JSTHROW_TYPE("Must pass pattern size"); + } + + // Arg 3, 4, input guesses for the camrea matrix and distortion coefficients, skipping for now + cv::Mat K, dist; + + // Arg 5, 6 flags and termination criteria, skipping for now + + // Calibrate the camera + std::vector rvecs, tvecs; + + double error = cv::calibrateCamera(objectPoints, imagePoints, imageSize, K, dist, rvecs, tvecs); + + // make the return values + Local ret = NanNew(); + + // Reprojection error + ret->Set(NanNew("reprojectionError"), NanNew(error)); + + // K + Local KMatrixWrap = NanNew(Matrix::constructor)->GetFunction()->NewInstance(); + Matrix *KMatrix = ObjectWrap::Unwrap(KMatrixWrap); + KMatrix->mat = K; + + ret->Set(NanNew("K"), KMatrixWrap); + + // dist + Local distMatrixWrap = NanNew(Matrix::constructor)->GetFunction()->NewInstance(); + Matrix *distMatrix = ObjectWrap::Unwrap(distMatrixWrap); + distMatrix->mat = dist; + + ret->Set(NanNew("distortion"), distMatrixWrap); + + // Per frame R and t, skiping for now + + // Return + NanReturnValue(ret); + + } catch (cv::Exception &e) { + const char *err_msg = e.what(); + NanThrowError(err_msg); + NanReturnUndefined(); + } +} diff --git a/src/Calib3D.h b/src/Calib3D.h index 14ecc99b..e42df5c9 100644 --- a/src/Calib3D.h +++ b/src/Calib3D.h @@ -12,6 +12,8 @@ class Calib3D: public node::ObjectWrap { static NAN_METHOD(FindChessboardCorners); static NAN_METHOD(DrawChessboardCorners); + + static NAN_METHOD(CalibrateCamera); }; #endif From 024d8e5ee55cfc63c91dad7e4d1f44eac7a4d0e8 Mon Sep 17 00:00:00 2001 From: Max Ehrlich Date: Tue, 20 Jan 2015 13:26:37 -0500 Subject: [PATCH 24/83] Changed to non-callback API since all methods are synchronous --- src/Calib3D.cc | 62 +++++++++++--------------------------------------- 1 file changed, 13 insertions(+), 49 deletions(-) diff --git a/src/Calib3D.cc b/src/Calib3D.cc index f8a1fcc1..3519470f 100644 --- a/src/Calib3D.cc +++ b/src/Calib3D.cc @@ -38,47 +38,27 @@ NAN_METHOD(Calib3D::FindChessboardCorners) // Arg 2 would normally be the flags, ignoring this for now and using the default flags - // Final argument is the callback function - REQ_FUN_ARG(2, cb); - // Find the corners std::vector corners; bool found = cv::findChessboardCorners(mat, patternSize, corners); - // Make the callback arguments - Local argv[2]; - - argv[0] = NanNull(); - argv[1] = NanNull(); // This will be replaced by the corners array if corners were found + // Make the return value + Local ret = NanNew(); + ret->Set(NanNew("found"), NanNew(found)); - // Further processing if we found corners - Local cornersArray; - if(found) + Local cornersArray = Array::New(corners.size()); + for(unsigned int i = 0; i < corners.size(); i++) { - // Convert the return value to a javascript array - cornersArray = Array::New(corners.size()); - for(unsigned int i = 0; i < corners.size(); i++) - { - Local point_data = NanNew(); - point_data->Set(NanNew("x"), NanNew(corners[i].x)); - point_data->Set(NanNew("y"), NanNew(corners[i].y)); + Local point_data = NanNew(); + point_data->Set(NanNew("x"), NanNew(corners[i].x)); + point_data->Set(NanNew("y"), NanNew(corners[i].y)); - cornersArray->Set(Number::New(i), point_data); - } - - argv[1] = cornersArray; + cornersArray->Set(Number::New(i), point_data); } - // Callback - TryCatch try_catch; - - cb->Call(NanGetCurrentContext()->Global(), 2, argv); - - if(try_catch.HasCaught()) { - FatalException(try_catch); - } + ret->Set(NanNew("corners"), cornersArray); - NanReturnUndefined(); + NanReturnValue(ret); } catch (cv::Exception &e) { @@ -129,27 +109,11 @@ NAN_METHOD(Calib3D::DrawChessboardCorners) // Arg 3, pattern found boolean bool patternWasFound = args[3]->ToBoolean()->Value(); - // Final argument is the callback - REQ_FUN_ARG(4, cb); - // Draw the corners cv::drawChessboardCorners(mat, patternSize, corners, patternWasFound); - // Make the callback arguments (same image that was passed, now with corners drawn on it) - Local argv[2]; - argv[0] = NanNull(); - argv[1] = args[0]; - - // Callback - TryCatch try_catch; - - cb->Call(NanGetCurrentContext()->Global(), 2, argv); - - if(try_catch.HasCaught()) { - FatalException(try_catch); - } - - NanReturnUndefined(); + // Return the passed image, now with corners drawn on it + NanReturnValue(args[0]); } catch (cv::Exception &e) { const char *err_msg = e.what(); From 9e04f9570371bbd30ff196eeb085c4ff1571c53d Mon Sep 17 00:00:00 2001 From: Max Ehrlich Date: Tue, 20 Jan 2015 14:05:58 -0500 Subject: [PATCH 25/83] Added solvePnP --- src/Calib3D.cc | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/Calib3D.h | 2 ++ 2 files changed, 86 insertions(+) diff --git a/src/Calib3D.cc b/src/Calib3D.cc index 3519470f..b0319658 100644 --- a/src/Calib3D.cc +++ b/src/Calib3D.cc @@ -10,6 +10,7 @@ void Calib3D::Init(Handle target) NODE_SET_METHOD(obj, "findChessboardCorners", FindChessboardCorners); NODE_SET_METHOD(obj, "drawChessboardCorners", DrawChessboardCorners); NODE_SET_METHOD(obj, "calibrateCamera", CalibrateCamera); + NODE_SET_METHOD(obj, "solvePnP", SolvePnP); target->Set(NanNew("calib3d"), obj); } @@ -228,3 +229,86 @@ NAN_METHOD(Calib3D::CalibrateCamera) NanReturnUndefined(); } } + +// cv::solvePnP +NAN_METHOD(Calib3D::SolvePnP) +{ + NanEscapableScope(); + + try { + // Get the arguments + + // Arg 0, the array of object points + std::vector objectPoints; + if(args[0]->IsArray()) { + Local objectPointsArray = Local::Cast(args[0]); + + for(unsigned int i = 0; i < objectPointsArray->Length(); i++) + { + Local pt = objectPointsArray->Get(i)->ToObject(); + objectPoints.push_back(cv::Point3f(pt->Get(NanNew("x"))->ToNumber()->Value(), + pt->Get(NanNew("y"))->ToNumber()->Value(), + pt->Get(NanNew("z"))->ToNumber()->Value())); + } + } else { + JSTHROW_TYPE("Must pass array of object points for each frame") + } + + // Arg 1, the image points + std::vector imagePoints; + if(args[1]->IsArray()) { + Local imagePointsArray = Local::Cast(args[1]); + + for(unsigned int i = 0; i < imagePointsArray->Length(); i++) + { + Local pt = imagePointsArray->Get(i)->ToObject(); + imagePoints.push_back(cv::Point2f(pt->Get(NanNew("x"))->ToNumber()->Value(), + pt->Get(NanNew("y"))->ToNumber()->Value())); + } + } else { + JSTHROW_TYPE("Must pass array of object points for each frame") + } + + // Arg 2, the camera matrix + Matrix* kWrap = ObjectWrap::Unwrap(args[2]->ToObject()); + cv::Mat K = kWrap->mat; + + // Arg 3, the distortion coefficients + Matrix* distWrap = ObjectWrap::Unwrap(args[3]->ToObject()); + cv::Mat dist = distWrap->mat; + + // Arg 4, use extrinsic guess, skipped for now + + // Arg 5, flags, skip for now + + // solve for r and t + cv::Mat rvec, tvec; + + cv::solvePnP(objectPoints, imagePoints, K, dist, rvec, tvec); + + // make the return values + Local ret = NanNew(); + + // rvec + Local rMatrixWrap = NanNew(Matrix::constructor)->GetFunction()->NewInstance(); + Matrix *rMatrix = ObjectWrap::Unwrap(rMatrixWrap); + rMatrix->mat = rvec; + + ret->Set(NanNew("rvec"), rMatrixWrap); + + // tvec + Local tMatrixWrap = NanNew(Matrix::constructor)->GetFunction()->NewInstance(); + Matrix *tMatrix = ObjectWrap::Unwrap(tMatrixWrap); + tMatrix->mat = tvec; + + ret->Set(NanNew("tvec"), tMatrixWrap); + + // Return + NanReturnValue(ret); + + } catch (cv::Exception &e) { + const char *err_msg = e.what(); + NanThrowError(err_msg); + NanReturnUndefined(); + } +} diff --git a/src/Calib3D.h b/src/Calib3D.h index e42df5c9..67bf2c70 100644 --- a/src/Calib3D.h +++ b/src/Calib3D.h @@ -14,6 +14,8 @@ class Calib3D: public node::ObjectWrap { static NAN_METHOD(DrawChessboardCorners); static NAN_METHOD(CalibrateCamera); + + static NAN_METHOD(SolvePnP); }; #endif From 9e9bf23e95134f4ed11bd23c3eee2bb9d5876349 Mon Sep 17 00:00:00 2001 From: Max Ehrlich Date: Wed, 21 Jan 2015 10:56:16 -0500 Subject: [PATCH 26/83] Switched to NaNNew functions to avoid compile errors on differing node versions --- src/Calib3D.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Calib3D.cc b/src/Calib3D.cc index b0319658..6f078a81 100644 --- a/src/Calib3D.cc +++ b/src/Calib3D.cc @@ -47,14 +47,14 @@ NAN_METHOD(Calib3D::FindChessboardCorners) Local ret = NanNew(); ret->Set(NanNew("found"), NanNew(found)); - Local cornersArray = Array::New(corners.size()); + Local cornersArray = NanNew(corners.size()); for(unsigned int i = 0; i < corners.size(); i++) { Local point_data = NanNew(); point_data->Set(NanNew("x"), NanNew(corners[i].x)); point_data->Set(NanNew("y"), NanNew(corners[i].y)); - cornersArray->Set(Number::New(i), point_data); + cornersArray->Set(NanNew(i), point_data); } ret->Set(NanNew("corners"), cornersArray); From 176887e3ba8c9a7a98b2f7e1ac408e8a7560a1d6 Mon Sep 17 00:00:00 2001 From: Peter Braden Date: Mon, 26 Jan 2015 17:41:14 +0100 Subject: [PATCH 27/83] Update README.md --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 80607586..a698e34a 100755 --- a/README.md +++ b/README.md @@ -172,13 +172,13 @@ See [relevant source code](src/Contours.cc) and [examples](examples/) ```javascript var contours = im.findContours; -# Count of contours in the Contours object +// Count of contours in the Contours object contours.size(); -# Count of corners(verticies) of contour `index` +// Count of corners(verticies) of contour `index` contours.cornerCount(index); -# Access vertex data of contours +// Access vertex data of contours for(var c = 0; c < contours.size(); ++c) { console.log("Contour " + c); for(var i = 0; i < contours.cornerCount(c); ++i) { @@ -187,14 +187,14 @@ for(var c = 0; c < contours.size(); ++c) { } } -# Computations of contour `index` +// Computations of contour `index` contours.area(index); contours.arcLength(index, isClosed); contours.boundingRect(index); contours.minAreaRect(index); contours.isConvex(index); -# Destructively alter contour `index` +// Destructively alter contour `index` contours.approxPolyDP(index, epsilon, isClosed); contours.convexHull(index, clockwise); ``` From 52a45179267abcbe1e609c3cd1eb9eb1c749eeb7 Mon Sep 17 00:00:00 2001 From: Peter Braden Date: Mon, 26 Jan 2015 17:42:14 +0100 Subject: [PATCH 28/83] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a698e34a..37d61ef3 100755 --- a/README.md +++ b/README.md @@ -183,7 +183,7 @@ for(var c = 0; c < contours.size(); ++c) { console.log("Contour " + c); for(var i = 0; i < contours.cornerCount(c); ++i) { var point = contours.point(c, i); - console.log("(" + point.x + "," + point.y + ")");" + console.log("(" + point.x + "," + point.y + ")"); } } From 96068dd7a935f37bac8a42fef31dc6e7fff92e9f Mon Sep 17 00:00:00 2001 From: Max Ehrlich Date: Tue, 27 Jan 2015 10:53:06 -0500 Subject: [PATCH 29/83] Added stub imgproc source file --- binding.gyp | 1 + src/ImgProc.cc | 10 ++++++++++ src/ImgProc.h | 13 +++++++++++++ src/init.cc | 2 ++ 4 files changed, 26 insertions(+) create mode 100644 src/ImgProc.cc create mode 100644 src/ImgProc.h diff --git a/binding.gyp b/binding.gyp index 6e56fc9a..449c0880 100755 --- a/binding.gyp +++ b/binding.gyp @@ -15,6 +15,7 @@ , "src/BackgroundSubtractor.cc" , "src/Constants.cc" , "src/Calib3D.cc" + , "src/ImgProc.cc" ] , 'libraries': [ ' target) +{ + Persistent inner; + Local obj = NanNew(); + NanAssignPersistent(inner, obj); + + target->Set(NanNew("imgproc"), obj); +} diff --git a/src/ImgProc.h b/src/ImgProc.h new file mode 100644 index 00000000..140b0567 --- /dev/null +++ b/src/ImgProc.h @@ -0,0 +1,13 @@ +#ifndef __NODE_IMGPROC_H +#define __NODE_IMGPROC_H + +#include "OpenCV.h" + +// Implementation of imgproc.hpp functions + +class ImgProc: public node::ObjectWrap { +public: + static void Init(Handle target); +}; + +#endif diff --git a/src/init.cc b/src/init.cc index 2486e075..95eef1af 100755 --- a/src/init.cc +++ b/src/init.cc @@ -10,6 +10,7 @@ #include "FaceRecognizer.h" #include "Constants.h" #include "Calib3D.h" +#include "ImgProc.h" extern "C" void init(Handle target) { @@ -25,6 +26,7 @@ init(Handle target) { NamedWindow::Init(target); Constants::Init(target); Calib3D::Init(target); + ImgProc::Init(target); #if CV_MAJOR_VERSION >= 2 && CV_MINOR_VERSION >=4 From 92f0bf80e575376b74d766d2699baef81d37be96 Mon Sep 17 00:00:00 2001 From: Max Ehrlich Date: Tue, 27 Jan 2015 11:16:36 -0500 Subject: [PATCH 30/83] Added cv::undistort --- src/ImgProc.cc | 44 ++++++++++++++++++++++++++++++++++++++++++++ src/ImgProc.h | 2 ++ 2 files changed, 46 insertions(+) diff --git a/src/ImgProc.cc b/src/ImgProc.cc index 7945d937..d0b1ea6a 100644 --- a/src/ImgProc.cc +++ b/src/ImgProc.cc @@ -1,4 +1,5 @@ #include "ImgProc.h" +#include "Matrix.h" void ImgProc::Init(Handle target) { @@ -6,5 +7,48 @@ void ImgProc::Init(Handle target) Local obj = NanNew(); NanAssignPersistent(inner, obj); + NODE_SET_METHOD(obj, "undistort", Undistort); + target->Set(NanNew("imgproc"), obj); } + +// cv::undistort +NAN_METHOD(ImgProc::Undistort) +{ + NanEscapableScope(); + + try { + // Get the arguments + + // Arg 0 is the image + Matrix* m0 = ObjectWrap::Unwrap(args[0]->ToObject()); + cv::Mat inputImage = m0->mat; + + // Arg 1 is the camera matrix + Matrix* m1 = ObjectWrap::Unwrap(args[1]->ToObject()); + cv::Mat K = m1->mat; + + // Arg 2 is the distortion coefficents + Matrix* m2 = ObjectWrap::Unwrap(args[2]->ToObject()); + cv::Mat dist = m2->mat; + + // Make an mat to hold the result image + cv::Mat outputImage; + + // Undistort + cv::undistort(inputImage, outputImage, K, dist); + + // Wrap the output image + Local outMatrixWrap = NanNew(Matrix::constructor)->GetFunction()->NewInstance(); + Matrix *outMatrix = ObjectWrap::Unwrap(outMatrixWrap); + outMatrix->mat = outputImage; + + // Return the output image + NanReturnValue(outMatrixWrap); + + } catch (cv::Exception &e) { + const char *err_msg = e.what(); + NanThrowError(err_msg); + NanReturnUndefined(); + } +} diff --git a/src/ImgProc.h b/src/ImgProc.h index 140b0567..c00393f2 100644 --- a/src/ImgProc.h +++ b/src/ImgProc.h @@ -8,6 +8,8 @@ class ImgProc: public node::ObjectWrap { public: static void Init(Handle target); + + static NAN_METHOD(Undistort); }; #endif From b76c39a42e090d6adaf951f4d6c00250bbe5396a Mon Sep 17 00:00:00 2001 From: Max Ehrlich Date: Tue, 27 Jan 2015 11:49:01 -0500 Subject: [PATCH 31/83] Added getOptimalNewCameraMatrix --- src/Calib3D.cc | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/Calib3D.h | 2 ++ 2 files changed, 63 insertions(+) diff --git a/src/Calib3D.cc b/src/Calib3D.cc index 6f078a81..274844ed 100644 --- a/src/Calib3D.cc +++ b/src/Calib3D.cc @@ -11,6 +11,7 @@ void Calib3D::Init(Handle target) NODE_SET_METHOD(obj, "drawChessboardCorners", DrawChessboardCorners); NODE_SET_METHOD(obj, "calibrateCamera", CalibrateCamera); NODE_SET_METHOD(obj, "solvePnP", SolvePnP); + NODE_SET_METHOD(obj, "getOptimalNewCameraMatrix", GetOptimalNewCameraMatrix); target->Set(NanNew("calib3d"), obj); } @@ -312,3 +313,63 @@ NAN_METHOD(Calib3D::SolvePnP) NanReturnUndefined(); } } + +// cv::solvePnP +NAN_METHOD(Calib3D::GetOptimalNewCameraMatrix) +{ + NanEscapableScope(); + + try { + // Get the arguments + + // Arg 0 is the original camera matrix + Matrix* m0 = ObjectWrap::Unwrap(args[0]->ToObject()); + cv::Mat Kin = m0->mat; + + // Arg 1 is the distortion coefficients + Matrix* m1 = ObjectWrap::Unwrap(args[1]->ToObject()); + cv::Mat dist = m1->mat; + + // Arg 2, the image size + cv::Size imageSize; + if (args[2]->IsArray()) { + Local v8sz = args[2]->ToObject(); + + imageSize = cv::Size(v8sz->Get(0)->IntegerValue(), v8sz->Get(1)->IntegerValue()); + } else { + JSTHROW_TYPE("Must pass pattern size"); + } + + // Arg 3 is the alpha free scaling parameter + double alpha = args[3]->ToNumber()->Value(); + + // Arg 4, the new image size + cv::Size newImageSize; + if (args[4]->IsArray()) { + Local v8sz = args[4]->ToObject(); + + newImageSize = cv::Size(v8sz->Get(0)->IntegerValue(), v8sz->Get(1)->IntegerValue()); + } else { + JSTHROW_TYPE("Must pass pattern size"); + } + + // Arg 5, valid ROI, skip for now + // Arg 6, center principal point, skip for now + + // Get the optimal new camera matrix + cv::Mat Kout = cv::getOptimalNewCameraMatrix(Kin, dist, imageSize, alpha, newImageSize); + + // Wrap the output K + Local KMatrixWrap = NanNew(Matrix::constructor)->GetFunction()->NewInstance(); + Matrix *KMatrix = ObjectWrap::Unwrap(KMatrixWrap); + KMatrix->mat = Kout; + + // Return the new K matrix + NanReturnValue(KMatrixWrap); + + } catch (cv::Exception &e) { + const char *err_msg = e.what(); + NanThrowError(err_msg); + NanReturnUndefined(); + } +} diff --git a/src/Calib3D.h b/src/Calib3D.h index 67bf2c70..ab5669e6 100644 --- a/src/Calib3D.h +++ b/src/Calib3D.h @@ -16,6 +16,8 @@ class Calib3D: public node::ObjectWrap { static NAN_METHOD(CalibrateCamera); static NAN_METHOD(SolvePnP); + + static NAN_METHOD(GetOptimalNewCameraMatrix); }; #endif From a66d95b53715e1bdf10ca3b49f23f29516d01af7 Mon Sep 17 00:00:00 2001 From: Max Ehrlich Date: Tue, 27 Jan 2015 12:02:08 -0500 Subject: [PATCH 32/83] Added initUndistortRectifyMap --- src/ImgProc.cc | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/ImgProc.h | 2 ++ 2 files changed, 70 insertions(+) diff --git a/src/ImgProc.cc b/src/ImgProc.cc index d0b1ea6a..4291e171 100644 --- a/src/ImgProc.cc +++ b/src/ImgProc.cc @@ -8,6 +8,7 @@ void ImgProc::Init(Handle target) NanAssignPersistent(inner, obj); NODE_SET_METHOD(obj, "undistort", Undistort); + NODE_SET_METHOD(obj, "initUndistortRectifyMap", InitUndistortRectifyMap); target->Set(NanNew("imgproc"), obj); } @@ -52,3 +53,70 @@ NAN_METHOD(ImgProc::Undistort) NanReturnUndefined(); } } + +// cv::initUndistortRectifyMap +NAN_METHOD(ImgProc::InitUndistortRectifyMap) +{ + NanEscapableScope(); + + try { + + // Arg 0 is the camera matrix + Matrix* m0 = ObjectWrap::Unwrap(args[0]->ToObject()); + cv::Mat K = m0->mat; + + // Arg 1 is the distortion coefficents + Matrix* m1 = ObjectWrap::Unwrap(args[1]->ToObject()); + cv::Mat dist = m1->mat; + + // Arg 2 is the recification transformation + Matrix* m2 = ObjectWrap::Unwrap(args[2]->ToObject()); + cv::Mat R = m2->mat; + + // Arg 3 is the new camera matrix + Matrix* m3 = ObjectWrap::Unwrap(args[3]->ToObject()); + cv::Mat newK = m3->mat; + + // Arg 4 is the image size + cv::Size imageSize; + if (args[4]->IsArray()) { + Local v8sz = args[4]->ToObject(); + + imageSize = cv::Size(v8sz->Get(0)->IntegerValue(), v8sz->Get(1)->IntegerValue()); + } else { + JSTHROW_TYPE("Must pass pattern size"); + } + + // Arg 5 is the first map type, skip for now + int m1type = CV_16SC2; + + // Make matrices to hold the output maps + cv::Mat map1, map2; + + // Compute the rectification map + cv::initUndistortRectifyMap(K, dist, R, newK, imageSize, m1type, map1, map2); + + // Wrap the output maps + Local map1Wrap = NanNew(Matrix::constructor)->GetFunction()->NewInstance(); + Matrix *map1Matrix = ObjectWrap::Unwrap(map1Wrap); + map1Matrix->mat = map1; + + Local map2Wrap = NanNew(Matrix::constructor)->GetFunction()->NewInstance(); + Matrix *map2Matrix = ObjectWrap::Unwrap(map2Wrap); + map2Matrix->mat = map2; + + // Make a return object with the two maps + Local ret = NanNew(); + ret->Set(NanNew("map1"), map1Wrap); + ret->Set(NanNew("map2"), map2Wrap); + + // Return the maps + NanReturnValue(ret); + + + } catch (cv::Exception &e) { + const char *err_msg = e.what(); + NanThrowError(err_msg); + NanReturnUndefined(); + } +} diff --git a/src/ImgProc.h b/src/ImgProc.h index c00393f2..96894039 100644 --- a/src/ImgProc.h +++ b/src/ImgProc.h @@ -10,6 +10,8 @@ class ImgProc: public node::ObjectWrap { static void Init(Handle target); static NAN_METHOD(Undistort); + + static NAN_METHOD(InitUndistortRectifyMap); }; #endif From 51be174b6e5056004f70a866d6346f50ad615718 Mon Sep 17 00:00:00 2001 From: Max Ehrlich Date: Tue, 27 Jan 2015 12:22:05 -0500 Subject: [PATCH 33/83] Added interpolation constants --- src/Constants.cc | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Constants.cc b/src/Constants.cc index e5b3b689..1d9696b7 100644 --- a/src/Constants.cc +++ b/src/Constants.cc @@ -4,6 +4,9 @@ #define CONST(C) \ obj->Set(NanNew(#C), NanNew(C)); +#define CONST_ENUM(C) \ + obj->Set(NanNew(#C), NanNew((int)(cv::C))); + void Constants::Init(Handle target) { Persistent inner; @@ -54,6 +57,12 @@ Constants::Init(Handle target) { CONST(CV_64FC3); CONST(CV_64FC4); + CONST_ENUM(INTER_NEAREST); + CONST_ENUM(INTER_LINEAR); + CONST_ENUM(INTER_AREA); + CONST_ENUM(INTER_CUBIC); + CONST_ENUM(INTER_LANCZOS4); + target->Set(NanNew("Constants"), obj); } From 3d09bb30ea87bdd11f7fa3a30f30acc8777e57a5 Mon Sep 17 00:00:00 2001 From: Max Ehrlich Date: Tue, 27 Jan 2015 12:55:32 -0500 Subject: [PATCH 34/83] Added remap --- src/ImgProc.cc | 51 ++++++++++++++++++++++++++++++++++++++++++++++++-- src/ImgProc.h | 2 ++ 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/src/ImgProc.cc b/src/ImgProc.cc index 4291e171..4c090a6d 100644 --- a/src/ImgProc.cc +++ b/src/ImgProc.cc @@ -9,6 +9,7 @@ void ImgProc::Init(Handle target) NODE_SET_METHOD(obj, "undistort", Undistort); NODE_SET_METHOD(obj, "initUndistortRectifyMap", InitUndistortRectifyMap); + NODE_SET_METHOD(obj, "remap", Remap); target->Set(NanNew("imgproc"), obj); } @@ -82,9 +83,9 @@ NAN_METHOD(ImgProc::InitUndistortRectifyMap) if (args[4]->IsArray()) { Local v8sz = args[4]->ToObject(); - imageSize = cv::Size(v8sz->Get(0)->IntegerValue(), v8sz->Get(1)->IntegerValue()); + imageSize = cv::Size(v8sz->Get(1)->IntegerValue(), v8sz->Get(0)->IntegerValue()); } else { - JSTHROW_TYPE("Must pass pattern size"); + JSTHROW_TYPE("Must pass image size"); } // Arg 5 is the first map type, skip for now @@ -120,3 +121,49 @@ NAN_METHOD(ImgProc::InitUndistortRectifyMap) NanReturnUndefined(); } } + +// cv::remap +NAN_METHOD(ImgProc::Remap) +{ + NanEscapableScope(); + + try { + // Get the arguments + + // Arg 0 is the image + Matrix* m0 = ObjectWrap::Unwrap(args[0]->ToObject()); + cv::Mat inputImage = m0->mat; + + // Arg 1 is the first map + Matrix* m1 = ObjectWrap::Unwrap(args[1]->ToObject()); + cv::Mat map1 = m1->mat; + + // Arg 2 is the second map + Matrix* m2 = ObjectWrap::Unwrap(args[2]->ToObject()); + cv::Mat map2 = m2->mat; + + // Arg 3 is the interpolation mode + int interpolation = args[3]->IntegerValue(); + + // Args 4, 5 border settings, skipping for now + + // Output image + cv::Mat outputImage; + + // Remap + cv::remap(inputImage, outputImage, map1, map2, interpolation); + + // Wrap the output image + Local outMatrixWrap = NanNew(Matrix::constructor)->GetFunction()->NewInstance(); + Matrix *outMatrix = ObjectWrap::Unwrap(outMatrixWrap); + outMatrix->mat = outputImage; + + // Return the image + NanReturnValue(outMatrixWrap); + + } catch (cv::Exception &e) { + const char *err_msg = e.what(); + NanThrowError(err_msg); + NanReturnUndefined(); + } +} diff --git a/src/ImgProc.h b/src/ImgProc.h index 96894039..6d264584 100644 --- a/src/ImgProc.h +++ b/src/ImgProc.h @@ -12,6 +12,8 @@ class ImgProc: public node::ObjectWrap { static NAN_METHOD(Undistort); static NAN_METHOD(InitUndistortRectifyMap); + + static NAN_METHOD(Remap); }; #endif From d9aaf529f85e913de51c7ae26ae2d032acb54149 Mon Sep 17 00:00:00 2001 From: Max Ehrlich Date: Tue, 27 Jan 2015 12:55:42 -0500 Subject: [PATCH 35/83] Fixed bug causing image sizes to be transposed --- src/Calib3D.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Calib3D.cc b/src/Calib3D.cc index 274844ed..f223fefd 100644 --- a/src/Calib3D.cc +++ b/src/Calib3D.cc @@ -184,7 +184,7 @@ NAN_METHOD(Calib3D::CalibrateCamera) if (args[2]->IsArray()) { Local v8sz = args[2]->ToObject(); - imageSize = cv::Size(v8sz->Get(0)->IntegerValue(), v8sz->Get(1)->IntegerValue()); + imageSize = cv::Size(v8sz->Get(1)->IntegerValue(), v8sz->Get(0)->IntegerValue()); } else { JSTHROW_TYPE("Must pass pattern size"); } @@ -335,9 +335,9 @@ NAN_METHOD(Calib3D::GetOptimalNewCameraMatrix) if (args[2]->IsArray()) { Local v8sz = args[2]->ToObject(); - imageSize = cv::Size(v8sz->Get(0)->IntegerValue(), v8sz->Get(1)->IntegerValue()); + imageSize = cv::Size(v8sz->Get(1)->IntegerValue(), v8sz->Get(0)->IntegerValue()); } else { - JSTHROW_TYPE("Must pass pattern size"); + JSTHROW_TYPE("Must pass original image size"); } // Arg 3 is the alpha free scaling parameter @@ -348,9 +348,9 @@ NAN_METHOD(Calib3D::GetOptimalNewCameraMatrix) if (args[4]->IsArray()) { Local v8sz = args[4]->ToObject(); - newImageSize = cv::Size(v8sz->Get(0)->IntegerValue(), v8sz->Get(1)->IntegerValue()); + newImageSize = cv::Size(v8sz->Get(1)->IntegerValue(), v8sz->Get(0)->IntegerValue()); } else { - JSTHROW_TYPE("Must pass pattern size"); + JSTHROW_TYPE("Must pass new image size"); } // Arg 5, valid ROI, skip for now From 8ed5177c34f5942352e2e43be65ebd34909f31c1 Mon Sep 17 00:00:00 2001 From: Max Ehrlich Date: Tue, 27 Jan 2015 12:59:51 -0500 Subject: [PATCH 36/83] Added map1 type paramter to initUndistortRectifyMap --- src/ImgProc.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ImgProc.cc b/src/ImgProc.cc index 4c090a6d..d3210fd0 100644 --- a/src/ImgProc.cc +++ b/src/ImgProc.cc @@ -89,7 +89,7 @@ NAN_METHOD(ImgProc::InitUndistortRectifyMap) } // Arg 5 is the first map type, skip for now - int m1type = CV_16SC2; + int m1type = args[5]->IntegerValue(); // Make matrices to hold the output maps cv::Mat map1, map2; From 4bc20cda6f12b799b3660c3722eefd0ad1c7b8fb Mon Sep 17 00:00:00 2001 From: edgarsilva Date: Wed, 4 Feb 2015 11:22:09 -0600 Subject: [PATCH 37/83] Fix issue with different versions of opencv installed in different OSs, updated cflags opencv version in bindings.gyp --- binding.gyp | 118 +++++++++++++++++++++++++++------------------------- 1 file changed, 62 insertions(+), 56 deletions(-) diff --git a/binding.gyp b/binding.gyp index 3d16eedf..e13a62b0 100755 --- a/binding.gyp +++ b/binding.gyp @@ -1,72 +1,78 @@ { "targets": [{ - "target_name": "opencv" - , "sources": [ - "src/init.cc" - , "src/Matrix.cc" - , "src/OpenCV.cc" - , "src/CascadeClassifierWrap.cc" - , "src/Contours.cc" - , "src/Point.cc" - , "src/VideoCaptureWrap.cc" - , "src/CamShift.cc" - , "src/HighGUI.cc" - , "src/FaceRecognizer.cc" - , "src/BackgroundSubtractor.cc" - , "src/Constants.cc" - ] - , 'libraries': [ - '= 2.4.9" )' - , '-Wall' - ] - , 'cflags!' : [ '-fno-exceptions'] - , 'cflags_cc!': [ '-fno-rtti', '-fno-exceptions'] - , "conditions": [ - ['OS=="win"', - { - 'msvs_settings': { - 'VCCLCompilerTool': { - 'ExceptionHandling': '2', - 'DisableSpecificWarnings': [ '4530', '4506', '4244' ], + "include_dirs": [ + "= 2.3.1\" )", + "-Wall" + ] + }], + [ "OS==\"win\"", { + "cflags": [ + "= 2.4.9\" )", + "-Wall" + ], + "msvs_settings": { + "VCCLCompilerTool": { + "ExceptionHandling": "2", + "DisableSpecificWarnings": [ "4530", "4506", "4244" ], }, - }, - }, - ], - ['OS=="mac"', { - # cflags on OS X are stupid and have to be defined like this - 'xcode_settings': { - 'OTHER_CFLAGS': [ + } + }], + [ # 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++", - ' Date: Wed, 4 Feb 2015 11:51:29 -0600 Subject: [PATCH 38/83] Update travis opencv version. --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index d9cfb7ce..64555919 100755 --- a/.travis.yml +++ b/.travis.yml @@ -13,6 +13,7 @@ env: before_install: # Fix a problem with apt-get failing later, see http://docs.travis-ci.com/user/installing-dependencies/#Installing-Ubuntu-packages + - sudo add-apt-repository -y ppa:kubuntu-ppa/backports - sudo apt-get update -qq - sudo apt-get install libcv-dev - sudo apt-get install libopencv-dev From 37bda024c28b95eff31668728577215be2c5569a Mon Sep 17 00:00:00 2001 From: edgarsilva Date: Wed, 4 Feb 2015 11:56:12 -0600 Subject: [PATCH 39/83] Force ppa update to get newer version of opencv. --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 64555919..ff7cf32a 100755 --- a/.travis.yml +++ b/.travis.yml @@ -13,8 +13,9 @@ env: before_install: # Fix a problem with apt-get failing later, see http://docs.travis-ci.com/user/installing-dependencies/#Installing-Ubuntu-packages - - sudo add-apt-repository -y ppa:kubuntu-ppa/backports - sudo apt-get update -qq + - sudo add-apt-repository -y ppa:kubuntu-ppa/backports + - sudo apt-get update - sudo apt-get install libcv-dev - sudo apt-get install libopencv-dev - sudo apt-get install libhighgui-dev From 037fa6a7a595828ff9494771658d4baa96d475d6 Mon Sep 17 00:00:00 2001 From: Max Ehrlich Date: Wed, 4 Feb 2015 13:27:11 -0500 Subject: [PATCH 40/83] Removed unused code to avoid compile warning --- src/BackgroundSubtractor.cc | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/BackgroundSubtractor.cc b/src/BackgroundSubtractor.cc index e9de2646..18a581c9 100644 --- a/src/BackgroundSubtractor.cc +++ b/src/BackgroundSubtractor.cc @@ -21,7 +21,7 @@ BackgroundSubtractorWrap::Init(Handle target) { NODE_SET_PROTOTYPE_METHOD(ctor, "applyMOG", ApplyMOG); target->Set(NanNew("BackgroundSubtractor"), ctor->GetFunction()); - + }; NAN_METHOD(BackgroundSubtractorWrap::New) { @@ -42,17 +42,17 @@ NAN_METHOD(BackgroundSubtractorWrap::New) { NAN_METHOD(BackgroundSubtractorWrap::CreateMOG) { NanScope(); - int history = 200; - int nmixtures = 5; - double backgroundRatio = 0.7; - double noiseSigma = 0; - - if(args.Length() > 1){ - INT_FROM_ARGS(history, 0) - INT_FROM_ARGS(nmixtures, 1) - DOUBLE_FROM_ARGS(backgroundRatio, 2) - DOUBLE_FROM_ARGS(noiseSigma, 3) - } + // int history = 200; + // int nmixtures = 5; + // double backgroundRatio = 0.7; + // double noiseSigma = 0; + // + // if(args.Length() > 1){ + // INT_FROM_ARGS(history, 0) + // INT_FROM_ARGS(nmixtures, 1) + // DOUBLE_FROM_ARGS(backgroundRatio, 2) + // DOUBLE_FROM_ARGS(noiseSigma, 3) + // } Local n = NanNew(BackgroundSubtractorWrap::constructor)->GetFunction()->NewInstance(); @@ -83,13 +83,13 @@ NAN_METHOD(BackgroundSubtractorWrap::ApplyMOG) { Local fgMask = NanNew(Matrix::constructor)->GetFunction()->NewInstance(); Matrix *img = ObjectWrap::Unwrap(fgMask); - + cv::Mat mat; - + if(Buffer::HasInstance(args[0])){ uint8_t *buf = (uint8_t *) Buffer::Data(args[0]->ToObject()); - unsigned len = Buffer::Length(args[0]->ToObject()); + unsigned len = Buffer::Length(args[0]->ToObject()); cv::Mat *mbuf = new cv::Mat(len, 1, CV_64FC1, buf); mat = cv::imdecode(*mbuf, -1); //mbuf->release(); @@ -116,13 +116,13 @@ NAN_METHOD(BackgroundSubtractorWrap::ApplyMOG) { TryCatch try_catch; cb->Call(NanGetCurrentContext()->Global(), 2, argv); - + if (try_catch.HasCaught()) { FatalException(try_catch); } NanReturnUndefined(); - } + } catch( cv::Exception& e ){ const char* err_msg = e.what(); NanThrowError(err_msg); From 7d16f2e0469be04982b0ef8106f41b6576c4afff Mon Sep 17 00:00:00 2001 From: edgarsilva Date: Wed, 4 Feb 2015 12:51:35 -0600 Subject: [PATCH 41/83] Return to old version of opencv to try compilation. --- .travis.yml | 4 ++-- smoke/smoketest.js | 8 ++++---- src/BackgroundSubtractor.cc | 35 ++++++++++++++++++----------------- 3 files changed, 24 insertions(+), 23 deletions(-) diff --git a/.travis.yml b/.travis.yml index ff7cf32a..1508190d 100755 --- a/.travis.yml +++ b/.travis.yml @@ -14,8 +14,8 @@ env: before_install: # Fix a problem with apt-get failing later, see http://docs.travis-ci.com/user/installing-dependencies/#Installing-Ubuntu-packages - sudo apt-get update -qq - - sudo add-apt-repository -y ppa:kubuntu-ppa/backports - - sudo apt-get update + # - sudo add-apt-repository -y ppa:kubuntu-ppa/backports + # - sudo apt-get update - sudo apt-get install libcv-dev - sudo apt-get install libopencv-dev - sudo apt-get install libhighgui-dev diff --git a/smoke/smoketest.js b/smoke/smoketest.js index d26d4745..a34295e2 100755 --- a/smoke/smoketest.js +++ b/smoke/smoketest.js @@ -1,6 +1,6 @@ -var cv = require('../lib/opencv') +var cv = require('../lib/opencv'); -var trainingData = [] +var trainingData = []; /* for (var i = 1; i< 41; i++){ for (var j = 1; j<10; j++){ @@ -22,5 +22,5 @@ cv.readImage("/Users/peterbraden/Downloads/orl_faces/s6/10.pgm", function(e, im) */ cv.readImage("./examples/files/mona.png", function(e, mat){ var th = mat.threshold(200, 200, "Threshold to Zero Inverted"); - th.save('./examples/tmp/out.png') -}) + th.save('./examples/tmp/out.png'); +}); diff --git a/src/BackgroundSubtractor.cc b/src/BackgroundSubtractor.cc index e9de2646..b066529a 100644 --- a/src/BackgroundSubtractor.cc +++ b/src/BackgroundSubtractor.cc @@ -21,7 +21,7 @@ BackgroundSubtractorWrap::Init(Handle target) { NODE_SET_PROTOTYPE_METHOD(ctor, "applyMOG", ApplyMOG); target->Set(NanNew("BackgroundSubtractor"), ctor->GetFunction()); - + }; NAN_METHOD(BackgroundSubtractorWrap::New) { @@ -42,17 +42,17 @@ NAN_METHOD(BackgroundSubtractorWrap::New) { NAN_METHOD(BackgroundSubtractorWrap::CreateMOG) { NanScope(); - int history = 200; - int nmixtures = 5; - double backgroundRatio = 0.7; - double noiseSigma = 0; - - if(args.Length() > 1){ - INT_FROM_ARGS(history, 0) - INT_FROM_ARGS(nmixtures, 1) - DOUBLE_FROM_ARGS(backgroundRatio, 2) - DOUBLE_FROM_ARGS(noiseSigma, 3) - } + // int history = 200; + // int nmixtures = 5; + // double backgroundRatio = 0.7; + // double noiseSigma = 0; + // + // if(args.Length() > 1){ + // INT_FROM_ARGS(history, 0) + // INT_FROM_ARGS(nmixtures, 1) + // DOUBLE_FROM_ARGS(backgroundRatio, 2) + // DOUBLE_FROM_ARGS(noiseSigma, 3) + // } Local n = NanNew(BackgroundSubtractorWrap::constructor)->GetFunction()->NewInstance(); @@ -83,13 +83,13 @@ NAN_METHOD(BackgroundSubtractorWrap::ApplyMOG) { Local fgMask = NanNew(Matrix::constructor)->GetFunction()->NewInstance(); Matrix *img = ObjectWrap::Unwrap(fgMask); - + cv::Mat mat; - + if(Buffer::HasInstance(args[0])){ uint8_t *buf = (uint8_t *) Buffer::Data(args[0]->ToObject()); - unsigned len = Buffer::Length(args[0]->ToObject()); + unsigned len = Buffer::Length(args[0]->ToObject()); cv::Mat *mbuf = new cv::Mat(len, 1, CV_64FC1, buf); mat = cv::imdecode(*mbuf, -1); //mbuf->release(); @@ -116,13 +116,13 @@ NAN_METHOD(BackgroundSubtractorWrap::ApplyMOG) { TryCatch try_catch; cb->Call(NanGetCurrentContext()->Global(), 2, argv); - + if (try_catch.HasCaught()) { FatalException(try_catch); } NanReturnUndefined(); - } + } catch( cv::Exception& e ){ const char* err_msg = e.what(); NanThrowError(err_msg); @@ -136,3 +136,4 @@ BackgroundSubtractorWrap::BackgroundSubtractorWrap(cv::Ptr Date: Wed, 4 Feb 2015 13:02:09 -0600 Subject: [PATCH 42/83] Fix missing targets from bindings to make tests pass. --- binding.gyp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/binding.gyp b/binding.gyp index e13a62b0..ef75193b 100755 --- a/binding.gyp +++ b/binding.gyp @@ -13,7 +13,9 @@ "src/HighGUI.cc", "src/FaceRecognizer.cc", "src/BackgroundSubtractor.cc", - "src/Constants.cc" + "src/Constants.cc", + "src/Calib3D.cc", + "src/ImgProc.cc" ], "libraries": [ From b4a04b112a4c3c128d592a42b98e3a84e2a00885 Mon Sep 17 00:00:00 2001 From: Max Ehrlich Date: Thu, 5 Feb 2015 12:19:44 -0500 Subject: [PATCH 43/83] Added stereo calibrate --- src/Calib3D.cc | 180 ++++++++++++++++++++++++++++++++++++++++++++++++- src/Calib3D.h | 2 + 2 files changed, 181 insertions(+), 1 deletion(-) diff --git a/src/Calib3D.cc b/src/Calib3D.cc index f223fefd..62b56ca3 100644 --- a/src/Calib3D.cc +++ b/src/Calib3D.cc @@ -12,6 +12,7 @@ void Calib3D::Init(Handle target) NODE_SET_METHOD(obj, "calibrateCamera", CalibrateCamera); NODE_SET_METHOD(obj, "solvePnP", SolvePnP); NODE_SET_METHOD(obj, "getOptimalNewCameraMatrix", GetOptimalNewCameraMatrix); + NODE_SET_METHOD(obj, "stereoCalibrate", StereoCalibrate); target->Set(NanNew("calib3d"), obj); } @@ -314,7 +315,7 @@ NAN_METHOD(Calib3D::SolvePnP) } } -// cv::solvePnP +// cv::getOptimalNewCameraMAtrix NAN_METHOD(Calib3D::GetOptimalNewCameraMatrix) { NanEscapableScope(); @@ -373,3 +374,180 @@ NAN_METHOD(Calib3D::GetOptimalNewCameraMatrix) NanReturnUndefined(); } } + +// cv::stereoCalibrate +NAN_METHOD(Calib3D::StereoCalibrate) +{ + NanEscapableScope(); + + try { + // Get the arguments + + // Arg 0, the array of object points, an array of arrays + std::vector > objectPoints; + if(args[0]->IsArray()) { + Local objectPointsArray = Local::Cast(args[0]); + + for(unsigned int i = 0; i < objectPointsArray->Length(); i++) + { + std::vector points; + + Local pointsArray = Local::Cast(objectPointsArray->Get(i)); + for(unsigned int j = 0; j < pointsArray->Length(); j++) + { + Local pt = pointsArray->Get(j)->ToObject(); + points.push_back(cv::Point3f(pt->Get(NanNew("x"))->ToNumber()->Value(), + pt->Get(NanNew("y"))->ToNumber()->Value(), + pt->Get(NanNew("z"))->ToNumber()->Value())); + } + + objectPoints.push_back(points); + } + } else { + JSTHROW_TYPE("Must pass array of object points for each frame") + } + + // Arg 1, the image points1, another array of arrays =( + std::vector > imagePoints1; + if(args[1]->IsArray()) { + Local imagePointsArray = Local::Cast(args[1]); + + for(unsigned int i = 0; i < imagePointsArray->Length(); i++) + { + std::vector points; + + Local pointsArray = Local::Cast(imagePointsArray->Get(i)); + for(unsigned int j = 0; j < pointsArray->Length(); j++) + { + Local pt = pointsArray->Get(j)->ToObject(); + points.push_back(cv::Point2f(pt->Get(NanNew("x"))->ToNumber()->Value(), + pt->Get(NanNew("y"))->ToNumber()->Value())); + } + + imagePoints1.push_back(points); + } + } else { + JSTHROW_TYPE("Must pass array of object points for each frame") + } + + // Arg 2, the image points2, another array of arrays =( + std::vector > imagePoints2; + if(args[2]->IsArray()) { + Local imagePointsArray = Local::Cast(args[2]); + + for(unsigned int i = 0; i < imagePointsArray->Length(); i++) + { + std::vector points; + + Local pointsArray = Local::Cast(imagePointsArray->Get(i)); + for(unsigned int j = 0; j < pointsArray->Length(); j++) + { + Local pt = pointsArray->Get(j)->ToObject(); + points.push_back(cv::Point2f(pt->Get(NanNew("x"))->ToNumber()->Value(), + pt->Get(NanNew("y"))->ToNumber()->Value())); + } + + imagePoints2.push_back(points); + } + } else { + JSTHROW_TYPE("Must pass array of object points for each frame") + } + + // Arg 3 is the image size (follows the PYTHON api not the C++ api since all following arguments are optional or outputs) + cv::Size imageSize; + if (args[3]->IsArray()) { + Local v8sz = args[3]->ToObject(); + + imageSize = cv::Size(v8sz->Get(1)->IntegerValue(), v8sz->Get(0)->IntegerValue()); + } else { + JSTHROW_TYPE("Must pass original image size"); + } + + // Arg 4,5,6,7 is the camera matrix and distortion coefficients (optional but must pass all 4 or none) + cv::Mat k1, d1, k2, d2; + if(args.Length() >= 8) + { + Matrix* mk1 = ObjectWrap::Unwrap(args[4]->ToObject()); + Matrix* md1 = ObjectWrap::Unwrap(args[5]->ToObject()); + Matrix* mk2 = ObjectWrap::Unwrap(args[6]->ToObject()); + Matrix* md2 = ObjectWrap::Unwrap(args[7]->ToObject()); + + k1 = mk1->mat; + d1 = md1->mat; + + k2 = mk2->mat; + d2 = md2->mat; + } + + // Last argument is flags, skipping for now + + // Output mats + cv::Mat R, t, E, F; + + // Do the stereo calibration + cv::stereoCalibrate(objectPoints, imagePoints1, imagePoints2, k1, d1, k2, d2, imageSize, R, t, E, F); + + // make the return value + Local ret = NanNew(); + + // Make the output arguments + + // k1 + Local K1MatrixWrap = NanNew(Matrix::constructor)->GetFunction()->NewInstance(); + Matrix *K1Matrix = ObjectWrap::Unwrap(K1MatrixWrap); + K1Matrix->mat = k1; + + // d1 + Local d1MatrixWrap = NanNew(Matrix::constructor)->GetFunction()->NewInstance(); + Matrix *d1Matrix = ObjectWrap::Unwrap(d1MatrixWrap); + d1Matrix->mat = d1; + + // k2 + Local K2MatrixWrap = NanNew(Matrix::constructor)->GetFunction()->NewInstance(); + Matrix *K2Matrix = ObjectWrap::Unwrap(K2MatrixWrap); + K2Matrix->mat = k2; + + // d2 + Local d2MatrixWrap = NanNew(Matrix::constructor)->GetFunction()->NewInstance(); + Matrix *d2Matrix = ObjectWrap::Unwrap(d2MatrixWrap); + d2Matrix->mat = d2; + + // R + Local RMatrixWrap = NanNew(Matrix::constructor)->GetFunction()->NewInstance(); + Matrix *RMatrix = ObjectWrap::Unwrap(RMatrixWrap); + RMatrix->mat = R; + + // t + Local tMatrixWrap = NanNew(Matrix::constructor)->GetFunction()->NewInstance(); + Matrix *tMatrix = ObjectWrap::Unwrap(tMatrixWrap); + tMatrix->mat = t; + + // E + Local EMatrixWrap = NanNew(Matrix::constructor)->GetFunction()->NewInstance(); + Matrix *EMatrix = ObjectWrap::Unwrap(EMatrixWrap); + EMatrix->mat = E; + + // F + Local FMatrixWrap = NanNew(Matrix::constructor)->GetFunction()->NewInstance(); + Matrix *FMatrix = ObjectWrap::Unwrap(FMatrixWrap); + FMatrix->mat = F; + + // Add to return object + ret->Set(NanNew("K1"), K1MatrixWrap); + ret->Set(NanNew("distortion1"), d1MatrixWrap); + ret->Set(NanNew("K2"), K2MatrixWrap); + ret->Set(NanNew("distortion2"), d2MatrixWrap); + ret->Set(NanNew("R"), RMatrixWrap); + ret->Set(NanNew("t"), tMatrixWrap); + ret->Set(NanNew("E"), EMatrixWrap); + ret->Set(NanNew("F"), FMatrixWrap); + + // Return + NanReturnValue(ret); + + } catch (cv::Exception &e) { + const char *err_msg = e.what(); + NanThrowError(err_msg); + NanReturnUndefined(); + } +} diff --git a/src/Calib3D.h b/src/Calib3D.h index ab5669e6..1f18894c 100644 --- a/src/Calib3D.h +++ b/src/Calib3D.h @@ -18,6 +18,8 @@ class Calib3D: public node::ObjectWrap { static NAN_METHOD(SolvePnP); static NAN_METHOD(GetOptimalNewCameraMatrix); + + static NAN_METHOD(StereoCalibrate); }; #endif From eb4808cebda660394ab0b2eb2bb4ccb663b2e1e6 Mon Sep 17 00:00:00 2001 From: Max Ehrlich Date: Thu, 5 Feb 2015 14:09:52 -0500 Subject: [PATCH 44/83] Factored out commonly repeated code into functions --- src/Calib3D.cc | 417 ++++++++++++++++++------------------------------- 1 file changed, 156 insertions(+), 261 deletions(-) diff --git a/src/Calib3D.cc b/src/Calib3D.cc index 62b56ca3..127cc675 100644 --- a/src/Calib3D.cc +++ b/src/Calib3D.cc @@ -1,6 +1,123 @@ #include "Calib3D.h" #include "Matrix.h" +inline Local matrixFromMat(cv::Mat &input) +{ + Local matrixWrap = NanNew(Matrix::constructor)->GetFunction()->NewInstance(); + Matrix *matrix = ObjectWrap::Unwrap(matrixWrap); + matrix->mat = input; + + return matrixWrap; +} + +inline cv::Mat matFromMatrix(Handle matrix) +{ + Matrix* m = ObjectWrap::Unwrap(matrix->ToObject()); + return m->mat; +} + +inline cv::Size sizeFromArray(Handle jsArray) +{ + cv::Size patternSize; + + if (jsArray->IsArray()) + { + Local v8sz = jsArray->ToObject(); + + patternSize = cv::Size(v8sz->Get(0)->IntegerValue(), v8sz->Get(1)->IntegerValue()); + } + else + { + JSTHROW_TYPE("Size is not a valid array"); + } + + return patternSize; +} + +inline std::vector points2fFromArray(Handle array) +{ + std::vector points; + if(array->IsArray()) + { + Local pointsArray = Local::Cast(array->ToObject()); + + for(unsigned int i = 0; i < pointsArray->Length(); i++) + { + Local pt = pointsArray->Get(i)->ToObject(); + points.push_back(cv::Point2f(pt->Get(NanNew("x"))->ToNumber()->Value(), + pt->Get(NanNew("y"))->ToNumber()->Value())); + } + } + else + { + JSTHROW_TYPE("Points not a valid array"); + } + + return points; +} + +inline std::vector points3fFromArray(Handle array) +{ + std::vector points; + if(array->IsArray()) { + Local pointsArray = Local::Cast(array->ToObject()); + + for(unsigned int i = 0; i < pointsArray->Length(); i++) + { + Local pt = pointsArray->Get(i)->ToObject(); + points.push_back(cv::Point3f(pt->Get(NanNew("x"))->ToNumber()->Value(), + pt->Get(NanNew("y"))->ToNumber()->Value(), + pt->Get(NanNew("z"))->ToNumber()->Value())); + } + } + else + { + JSTHROW_TYPE("Must pass array of object points for each frame") + } + + return points; +} + +inline std::vector > points2fFromArrayOfArrays(Handle array) +{ + std::vector > points; + if(array->IsArray()) + { + Local pointsArray = Local::Cast(array->ToObject()); + + for(unsigned int i = 0; i < pointsArray->Length(); i++) + { + points.push_back(points2fFromArray(pointsArray->Get(i))); + } + } + else + { + JSTHROW_TYPE("Must pass array of object points for each frame") + } + + return points; +} + +inline std::vector > points3fFromArrayOfArrays(Handle array) +{ + std::vector > points; + if(array->IsArray()) + { + Local pointsArray = Local::Cast(array->ToObject()); + + for(unsigned int i = 0; i < pointsArray->Length(); i++) + { + points.push_back(points3fFromArray(pointsArray->Get(i))); + } + } + else + { + JSTHROW_TYPE("Must pass array of object points for each frame") + } + + return points; +} + void Calib3D::Init(Handle target) { Persistent inner; @@ -26,18 +143,10 @@ NAN_METHOD(Calib3D::FindChessboardCorners) // Get the arguments from javascript // Arg 0 is the image - Matrix* m = ObjectWrap::Unwrap(args[0]->ToObject()); - cv::Mat mat = m->mat; + cv::Mat mat = matFromMatrix(args[0]); // Arg 1 is the pattern size - cv::Size patternSize; - if (args[1]->IsArray()) { - Local v8sz = args[1]->ToObject(); - - patternSize = cv::Size(v8sz->Get(0)->IntegerValue(), v8sz->Get(1)->IntegerValue()); - } else { - JSTHROW_TYPE("Must pass pattern size"); - } + cv::Size patternSize = sizeFromArray(args[1]); // Arg 2 would normally be the flags, ignoring this for now and using the default flags @@ -81,33 +190,13 @@ NAN_METHOD(Calib3D::DrawChessboardCorners) // Get the arguments // Arg 0 is the image - Matrix* m = ObjectWrap::Unwrap(args[0]->ToObject()); - cv::Mat mat = m->mat; + cv::Mat mat = matFromMatrix(args[0]); // Arg 1 is the pattern size - cv::Size patternSize; - if (args[1]->IsArray()) { - Local v8sz = args[1]->ToObject(); - - patternSize = cv::Size(v8sz->Get(0)->IntegerValue(), v8sz->Get(1)->IntegerValue()); - } else { - JSTHROW_TYPE("Must pass pattern size"); - } + cv::Size patternSize = sizeFromArray(args[1]); // Arg 2 is the corners array - std::vector corners; - if(args[2]->IsArray()) { - Local cornersArray = Local::Cast(args[2]); - - for(unsigned int i = 0; i < cornersArray->Length(); i++) - { - Local pt = cornersArray->Get(i)->ToObject(); - corners.push_back(cv::Point2f(pt->Get(NanNew("x"))->ToNumber()->Value(), - pt->Get(NanNew("y"))->ToNumber()->Value())); - } - } else { - JSTHROW_TYPE("Must pass corners array"); - } + std::vector corners = points2fFromArray(args[2]); // Arg 3, pattern found boolean bool patternWasFound = args[3]->ToBoolean()->Value(); @@ -134,61 +223,13 @@ NAN_METHOD(Calib3D::CalibrateCamera) // Get the arguments // Arg 0, the array of object points, an array of arrays - std::vector > objectPoints; - if(args[0]->IsArray()) { - Local objectPointsArray = Local::Cast(args[0]); - - for(unsigned int i = 0; i < objectPointsArray->Length(); i++) - { - std::vector points; - - Local pointsArray = Local::Cast(objectPointsArray->Get(i)); - for(unsigned int j = 0; j < pointsArray->Length(); j++) - { - Local pt = pointsArray->Get(j)->ToObject(); - points.push_back(cv::Point3f(pt->Get(NanNew("x"))->ToNumber()->Value(), - pt->Get(NanNew("y"))->ToNumber()->Value(), - pt->Get(NanNew("z"))->ToNumber()->Value())); - } - - objectPoints.push_back(points); - } - } else { - JSTHROW_TYPE("Must pass array of object points for each frame") - } + std::vector > objectPoints = points3fFromArrayOfArrays(args[0]); - // Arg 1, the image points, another array of arrays =( - std::vector > imagePoints; - if(args[1]->IsArray()) { - Local imagePointsArray = Local::Cast(args[1]); - - for(unsigned int i = 0; i < imagePointsArray->Length(); i++) - { - std::vector points; - - Local pointsArray = Local::Cast(imagePointsArray->Get(i)); - for(unsigned int j = 0; j < pointsArray->Length(); j++) - { - Local pt = pointsArray->Get(j)->ToObject(); - points.push_back(cv::Point2f(pt->Get(NanNew("x"))->ToNumber()->Value(), - pt->Get(NanNew("y"))->ToNumber()->Value())); - } - - imagePoints.push_back(points); - } - } else { - JSTHROW_TYPE("Must pass array of object points for each frame") - } + // Arg 1, the image points, another array of arrays + std::vector > imagePoints = points2fFromArrayOfArrays(args[1]); // Arg 2, the image size - cv::Size imageSize; - if (args[2]->IsArray()) { - Local v8sz = args[2]->ToObject(); - - imageSize = cv::Size(v8sz->Get(1)->IntegerValue(), v8sz->Get(0)->IntegerValue()); - } else { - JSTHROW_TYPE("Must pass pattern size"); - } + cv::Size imageSize = sizeFromArray(args[2]); // Arg 3, 4, input guesses for the camrea matrix and distortion coefficients, skipping for now cv::Mat K, dist; @@ -207,17 +248,11 @@ NAN_METHOD(Calib3D::CalibrateCamera) ret->Set(NanNew("reprojectionError"), NanNew(error)); // K - Local KMatrixWrap = NanNew(Matrix::constructor)->GetFunction()->NewInstance(); - Matrix *KMatrix = ObjectWrap::Unwrap(KMatrixWrap); - KMatrix->mat = K; - + Local KMatrixWrap = matrixFromMat(K); ret->Set(NanNew("K"), KMatrixWrap); // dist - Local distMatrixWrap = NanNew(Matrix::constructor)->GetFunction()->NewInstance(); - Matrix *distMatrix = ObjectWrap::Unwrap(distMatrixWrap); - distMatrix->mat = dist; - + Local distMatrixWrap = matrixFromMat(dist); ret->Set(NanNew("distortion"), distMatrixWrap); // Per frame R and t, skiping for now @@ -241,43 +276,16 @@ NAN_METHOD(Calib3D::SolvePnP) // Get the arguments // Arg 0, the array of object points - std::vector objectPoints; - if(args[0]->IsArray()) { - Local objectPointsArray = Local::Cast(args[0]); - - for(unsigned int i = 0; i < objectPointsArray->Length(); i++) - { - Local pt = objectPointsArray->Get(i)->ToObject(); - objectPoints.push_back(cv::Point3f(pt->Get(NanNew("x"))->ToNumber()->Value(), - pt->Get(NanNew("y"))->ToNumber()->Value(), - pt->Get(NanNew("z"))->ToNumber()->Value())); - } - } else { - JSTHROW_TYPE("Must pass array of object points for each frame") - } + std::vector objectPoints = points3fFromArray(args[0]); // Arg 1, the image points - std::vector imagePoints; - if(args[1]->IsArray()) { - Local imagePointsArray = Local::Cast(args[1]); - - for(unsigned int i = 0; i < imagePointsArray->Length(); i++) - { - Local pt = imagePointsArray->Get(i)->ToObject(); - imagePoints.push_back(cv::Point2f(pt->Get(NanNew("x"))->ToNumber()->Value(), - pt->Get(NanNew("y"))->ToNumber()->Value())); - } - } else { - JSTHROW_TYPE("Must pass array of object points for each frame") - } + std::vector imagePoints = points2fFromArray(args[1]); // Arg 2, the camera matrix - Matrix* kWrap = ObjectWrap::Unwrap(args[2]->ToObject()); - cv::Mat K = kWrap->mat; + cv::Mat K = matFromMatrix(args[2]); // Arg 3, the distortion coefficients - Matrix* distWrap = ObjectWrap::Unwrap(args[3]->ToObject()); - cv::Mat dist = distWrap->mat; + cv::Mat dist = matFromMatrix(args[3]); // Arg 4, use extrinsic guess, skipped for now @@ -292,17 +300,11 @@ NAN_METHOD(Calib3D::SolvePnP) Local ret = NanNew(); // rvec - Local rMatrixWrap = NanNew(Matrix::constructor)->GetFunction()->NewInstance(); - Matrix *rMatrix = ObjectWrap::Unwrap(rMatrixWrap); - rMatrix->mat = rvec; - + Local rMatrixWrap = matrixFromMat(rvec); ret->Set(NanNew("rvec"), rMatrixWrap); // tvec - Local tMatrixWrap = NanNew(Matrix::constructor)->GetFunction()->NewInstance(); - Matrix *tMatrix = ObjectWrap::Unwrap(tMatrixWrap); - tMatrix->mat = tvec; - + Local tMatrixWrap = matrixFromMat(tvec); ret->Set(NanNew("tvec"), tMatrixWrap); // Return @@ -324,35 +326,19 @@ NAN_METHOD(Calib3D::GetOptimalNewCameraMatrix) // Get the arguments // Arg 0 is the original camera matrix - Matrix* m0 = ObjectWrap::Unwrap(args[0]->ToObject()); - cv::Mat Kin = m0->mat; + cv::Mat Kin = matFromMatrix(args[0]); // Arg 1 is the distortion coefficients - Matrix* m1 = ObjectWrap::Unwrap(args[1]->ToObject()); - cv::Mat dist = m1->mat; + cv::Mat dist = matFromMatrix(args[1]); // Arg 2, the image size - cv::Size imageSize; - if (args[2]->IsArray()) { - Local v8sz = args[2]->ToObject(); - - imageSize = cv::Size(v8sz->Get(1)->IntegerValue(), v8sz->Get(0)->IntegerValue()); - } else { - JSTHROW_TYPE("Must pass original image size"); - } + cv::Size imageSize = sizeFromArray(args[2]); // Arg 3 is the alpha free scaling parameter double alpha = args[3]->ToNumber()->Value(); // Arg 4, the new image size - cv::Size newImageSize; - if (args[4]->IsArray()) { - Local v8sz = args[4]->ToObject(); - - newImageSize = cv::Size(v8sz->Get(1)->IntegerValue(), v8sz->Get(0)->IntegerValue()); - } else { - JSTHROW_TYPE("Must pass new image size"); - } + cv::Size newImageSize = sizeFromArray(args[4]); // Arg 5, valid ROI, skip for now // Arg 6, center principal point, skip for now @@ -361,9 +347,7 @@ NAN_METHOD(Calib3D::GetOptimalNewCameraMatrix) cv::Mat Kout = cv::getOptimalNewCameraMatrix(Kin, dist, imageSize, alpha, newImageSize); // Wrap the output K - Local KMatrixWrap = NanNew(Matrix::constructor)->GetFunction()->NewInstance(); - Matrix *KMatrix = ObjectWrap::Unwrap(KMatrixWrap); - KMatrix->mat = Kout; + Local KMatrixWrap = matrixFromMat(Kout); // Return the new K matrix NanReturnValue(KMatrixWrap); @@ -384,99 +368,26 @@ NAN_METHOD(Calib3D::StereoCalibrate) // Get the arguments // Arg 0, the array of object points, an array of arrays - std::vector > objectPoints; - if(args[0]->IsArray()) { - Local objectPointsArray = Local::Cast(args[0]); - - for(unsigned int i = 0; i < objectPointsArray->Length(); i++) - { - std::vector points; - - Local pointsArray = Local::Cast(objectPointsArray->Get(i)); - for(unsigned int j = 0; j < pointsArray->Length(); j++) - { - Local pt = pointsArray->Get(j)->ToObject(); - points.push_back(cv::Point3f(pt->Get(NanNew("x"))->ToNumber()->Value(), - pt->Get(NanNew("y"))->ToNumber()->Value(), - pt->Get(NanNew("z"))->ToNumber()->Value())); - } - - objectPoints.push_back(points); - } - } else { - JSTHROW_TYPE("Must pass array of object points for each frame") - } + std::vector > objectPoints = points3fFromArrayOfArrays(args[0]); - // Arg 1, the image points1, another array of arrays =( - std::vector > imagePoints1; - if(args[1]->IsArray()) { - Local imagePointsArray = Local::Cast(args[1]); - - for(unsigned int i = 0; i < imagePointsArray->Length(); i++) - { - std::vector points; - - Local pointsArray = Local::Cast(imagePointsArray->Get(i)); - for(unsigned int j = 0; j < pointsArray->Length(); j++) - { - Local pt = pointsArray->Get(j)->ToObject(); - points.push_back(cv::Point2f(pt->Get(NanNew("x"))->ToNumber()->Value(), - pt->Get(NanNew("y"))->ToNumber()->Value())); - } - - imagePoints1.push_back(points); - } - } else { - JSTHROW_TYPE("Must pass array of object points for each frame") - } + // Arg 1, the image points1, another array of arrays + std::vector > imagePoints1 = points2fFromArrayOfArrays(args[1]); // Arg 2, the image points2, another array of arrays =( - std::vector > imagePoints2; - if(args[2]->IsArray()) { - Local imagePointsArray = Local::Cast(args[2]); - - for(unsigned int i = 0; i < imagePointsArray->Length(); i++) - { - std::vector points; - - Local pointsArray = Local::Cast(imagePointsArray->Get(i)); - for(unsigned int j = 0; j < pointsArray->Length(); j++) - { - Local pt = pointsArray->Get(j)->ToObject(); - points.push_back(cv::Point2f(pt->Get(NanNew("x"))->ToNumber()->Value(), - pt->Get(NanNew("y"))->ToNumber()->Value())); - } - - imagePoints2.push_back(points); - } - } else { - JSTHROW_TYPE("Must pass array of object points for each frame") - } + std::vector > imagePoints2 = points2fFromArrayOfArrays(args[2]); // Arg 3 is the image size (follows the PYTHON api not the C++ api since all following arguments are optional or outputs) - cv::Size imageSize; - if (args[3]->IsArray()) { - Local v8sz = args[3]->ToObject(); - - imageSize = cv::Size(v8sz->Get(1)->IntegerValue(), v8sz->Get(0)->IntegerValue()); - } else { - JSTHROW_TYPE("Must pass original image size"); - } + cv::Size imageSize = sizeFromArray(args[3]); // Arg 4,5,6,7 is the camera matrix and distortion coefficients (optional but must pass all 4 or none) cv::Mat k1, d1, k2, d2; if(args.Length() >= 8) { - Matrix* mk1 = ObjectWrap::Unwrap(args[4]->ToObject()); - Matrix* md1 = ObjectWrap::Unwrap(args[5]->ToObject()); - Matrix* mk2 = ObjectWrap::Unwrap(args[6]->ToObject()); - Matrix* md2 = ObjectWrap::Unwrap(args[7]->ToObject()); - - k1 = mk1->mat; - d1 = md1->mat; + k1 = matFromMatrix(args[4]); + d1 = matFromMatrix(args[5]); - k2 = mk2->mat; - d2 = md2->mat; + k2 = matFromMatrix(args[6]); + d2 = matFromMatrix(args[7]); } // Last argument is flags, skipping for now @@ -493,44 +404,28 @@ NAN_METHOD(Calib3D::StereoCalibrate) // Make the output arguments // k1 - Local K1MatrixWrap = NanNew(Matrix::constructor)->GetFunction()->NewInstance(); - Matrix *K1Matrix = ObjectWrap::Unwrap(K1MatrixWrap); - K1Matrix->mat = k1; + Local K1MatrixWrap = matrixFromMat(k1); // d1 - Local d1MatrixWrap = NanNew(Matrix::constructor)->GetFunction()->NewInstance(); - Matrix *d1Matrix = ObjectWrap::Unwrap(d1MatrixWrap); - d1Matrix->mat = d1; + Local d1MatrixWrap = matrixFromMat(d1); // k2 - Local K2MatrixWrap = NanNew(Matrix::constructor)->GetFunction()->NewInstance(); - Matrix *K2Matrix = ObjectWrap::Unwrap(K2MatrixWrap); - K2Matrix->mat = k2; + Local K2MatrixWrap = matrixFromMat(k2); // d2 - Local d2MatrixWrap = NanNew(Matrix::constructor)->GetFunction()->NewInstance(); - Matrix *d2Matrix = ObjectWrap::Unwrap(d2MatrixWrap); - d2Matrix->mat = d2; + Local d2MatrixWrap = matrixFromMat(d2); // R - Local RMatrixWrap = NanNew(Matrix::constructor)->GetFunction()->NewInstance(); - Matrix *RMatrix = ObjectWrap::Unwrap(RMatrixWrap); - RMatrix->mat = R; + Local RMatrixWrap = matrixFromMat(R); // t - Local tMatrixWrap = NanNew(Matrix::constructor)->GetFunction()->NewInstance(); - Matrix *tMatrix = ObjectWrap::Unwrap(tMatrixWrap); - tMatrix->mat = t; + Local tMatrixWrap = matrixFromMat(t); // E - Local EMatrixWrap = NanNew(Matrix::constructor)->GetFunction()->NewInstance(); - Matrix *EMatrix = ObjectWrap::Unwrap(EMatrixWrap); - EMatrix->mat = E; + Local EMatrixWrap = matrixFromMat(E); // F - Local FMatrixWrap = NanNew(Matrix::constructor)->GetFunction()->NewInstance(); - Matrix *FMatrix = ObjectWrap::Unwrap(FMatrixWrap); - FMatrix->mat = F; + Local FMatrixWrap = matrixFromMat(F); // Add to return object ret->Set(NanNew("K1"), K1MatrixWrap); From 31eab0e8c6733056a04f6b36f15f61b930bcbae1 Mon Sep 17 00:00:00 2001 From: Max Ehrlich Date: Thu, 5 Feb 2015 14:19:46 -0500 Subject: [PATCH 45/83] Added stereoRectify --- src/Calib3D.cc | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/Calib3D.h | 2 ++ 2 files changed, 63 insertions(+) diff --git a/src/Calib3D.cc b/src/Calib3D.cc index 127cc675..67d99277 100644 --- a/src/Calib3D.cc +++ b/src/Calib3D.cc @@ -130,6 +130,7 @@ void Calib3D::Init(Handle target) NODE_SET_METHOD(obj, "solvePnP", SolvePnP); NODE_SET_METHOD(obj, "getOptimalNewCameraMatrix", GetOptimalNewCameraMatrix); NODE_SET_METHOD(obj, "stereoCalibrate", StereoCalibrate); + NODE_SET_METHOD(obj, "stereoRectify", StereoRectify); target->Set(NanNew("calib3d"), obj); } @@ -446,3 +447,63 @@ NAN_METHOD(Calib3D::StereoCalibrate) NanReturnUndefined(); } } + +// cv::stereoCalibrate +NAN_METHOD(Calib3D::StereoRectify) +{ + NanEscapableScope(); + + try { + // Get the arguments + + // Arg0, the first camera matrix + cv::Mat K1 = matFromMatrix(args[0]); + + // Arg1, the first distortion coefficients + cv::Mat d1 = matFromMatrix(args[1]); + + // Arg3, the second camera matrix + cv::Mat K2 = matFromMatrix(args[3]); + + // Arg4, the second distortion coefficients + cv::Mat d2 = matFromMatrix(args[4]); + + // Arg5, the image size + cv::Size imageSize = sizeFromArray(args[5]); + + // arg6, the intercamera rotation matrix + cv::Mat R = matFromMatrix(args[6]); + + // Arg7, the intercamera translation vector + cv::Mat t = matFromMatrix(args[7]); + + // Arg8, flags, skipping for now + + // Arg9, freescaling paremeter, skipping for now + + // Arg10, new image size, skipping for now to fix at original image size + + // Make output matrics + cv::Mat R1, R2, P1, P2, Q; + + // Do the stereo rectification + cv::stereoRectify(K1, d1, K2, d2, imageSize, R, t, R1, R2, P1, P2, Q); + + // Make the return object + Local ret = NanNew(); + + ret->Set(NanNew("R1"), matrixFromMat(R1)); + ret->Set(NanNew("R2"), matrixFromMat(R2)); + ret->Set(NanNew("P1"), matrixFromMat(P1)); + ret->Set(NanNew("P2"), matrixFromMat(P2)); + ret->Set(NanNew("Q"), matrixFromMat(Q)); + + // Return the recification parameters + NanReturnValue(ret); + + } catch (cv::Exception &e) { + const char *err_msg = e.what(); + NanThrowError(err_msg); + NanReturnUndefined(); + } +} diff --git a/src/Calib3D.h b/src/Calib3D.h index 1f18894c..cf1d190c 100644 --- a/src/Calib3D.h +++ b/src/Calib3D.h @@ -20,6 +20,8 @@ class Calib3D: public node::ObjectWrap { static NAN_METHOD(GetOptimalNewCameraMatrix); static NAN_METHOD(StereoCalibrate); + + static NAN_METHOD(StereoRectify); }; #endif From 51631b307ea0ce997909853f0c98abb630a991b1 Mon Sep 17 00:00:00 2001 From: Max Ehrlich Date: Thu, 5 Feb 2015 14:31:37 -0500 Subject: [PATCH 46/83] Added computeCorrespondEpilines --- src/Calib3D.cc | 48 ++++++++++++++++++++++++++++++++++++++++++++++-- src/Calib3D.h | 2 ++ 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/src/Calib3D.cc b/src/Calib3D.cc index 67d99277..8d6a43fa 100644 --- a/src/Calib3D.cc +++ b/src/Calib3D.cc @@ -131,6 +131,7 @@ void Calib3D::Init(Handle target) NODE_SET_METHOD(obj, "getOptimalNewCameraMatrix", GetOptimalNewCameraMatrix); NODE_SET_METHOD(obj, "stereoCalibrate", StereoCalibrate); NODE_SET_METHOD(obj, "stereoRectify", StereoRectify); + NODE_SET_METHOD(obj, "computeCorrespondEpilines", ComputeCorrespondEpilines); target->Set(NanNew("calib3d"), obj); } @@ -448,7 +449,7 @@ NAN_METHOD(Calib3D::StereoCalibrate) } } -// cv::stereoCalibrate +// cv::stereoRectify NAN_METHOD(Calib3D::StereoRectify) { NanEscapableScope(); @@ -500,7 +501,50 @@ NAN_METHOD(Calib3D::StereoRectify) // Return the recification parameters NanReturnValue(ret); - + + } catch (cv::Exception &e) { + const char *err_msg = e.what(); + NanThrowError(err_msg); + NanReturnUndefined(); + } +} + +// cv::stereoRectify +NAN_METHOD(Calib3D::StereoRectify) +{ + NanEscapableScope(); + + try { + // Get the arguments + + // Arg0, the image points + std::vector points = points2fFromArray(args[0]); + + // Arg1, the image index (1 or 2) + int whichImage = int(args[1]->ToNumber()->Value()); + + // Arg2, the fundamental matrix + cv::Mat F = matFromMatrix(args[2]); + + // compute the lines + std::vector lines; + cv::computeCorrespondEpilines(points, whichImage, F, lines); + + // Convert the lines to an array of objects (ax + by + c = 0) + Local linesArray = NanNew(lines.size()); + for(unsigned int i = 0; i < lines.size(); i++) + { + Local line_data = NanNew(); + line_data->Set(NanNew("a"), NanNew(corners[i][0])); + line_data->Set(NanNew("b"), NanNew(corners[i][1])); + line_data->Set(NanNew("c"), NanNew(corners[i][2])); + + linesArray->Set(NanNew(i), line_data); + } + + // Return the lines + NanReturnValue(linesArray); + } catch (cv::Exception &e) { const char *err_msg = e.what(); NanThrowError(err_msg); diff --git a/src/Calib3D.h b/src/Calib3D.h index cf1d190c..9d5afbd8 100644 --- a/src/Calib3D.h +++ b/src/Calib3D.h @@ -22,6 +22,8 @@ class Calib3D: public node::ObjectWrap { static NAN_METHOD(StereoCalibrate); static NAN_METHOD(StereoRectify); + + static NAN_METHOD(ComputeCorrespondEpilines); }; #endif From 17afbceabdda3d09f799907003d856b74fb21cba Mon Sep 17 00:00:00 2001 From: Max Ehrlich Date: Thu, 5 Feb 2015 14:32:51 -0500 Subject: [PATCH 47/83] Fixed bug in function name --- src/Calib3D.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Calib3D.cc b/src/Calib3D.cc index 8d6a43fa..e73a62a7 100644 --- a/src/Calib3D.cc +++ b/src/Calib3D.cc @@ -509,8 +509,8 @@ NAN_METHOD(Calib3D::StereoRectify) } } -// cv::stereoRectify -NAN_METHOD(Calib3D::StereoRectify) +// cv::computeCorrespondEpilines +NAN_METHOD(Calib3D::ComputeCorrespondEpilines) { NanEscapableScope(); From 92a9369d69c6ad8262357cb1f5e451f1f0254f11 Mon Sep 17 00:00:00 2001 From: Max Ehrlich Date: Thu, 5 Feb 2015 14:37:36 -0500 Subject: [PATCH 48/83] Added reprojectImageTo3D --- src/Calib3D.cc | 36 ++++++++++++++++++++++++++++++++++++ src/Calib3D.h | 2 ++ 2 files changed, 38 insertions(+) diff --git a/src/Calib3D.cc b/src/Calib3D.cc index e73a62a7..ebc4f806 100644 --- a/src/Calib3D.cc +++ b/src/Calib3D.cc @@ -132,6 +132,7 @@ void Calib3D::Init(Handle target) NODE_SET_METHOD(obj, "stereoCalibrate", StereoCalibrate); NODE_SET_METHOD(obj, "stereoRectify", StereoRectify); NODE_SET_METHOD(obj, "computeCorrespondEpilines", ComputeCorrespondEpilines); + NODE_SET_METHOD(obj, "reprojectImageTo3D", ReprojectImageTo3D); target->Set(NanNew("calib3d"), obj); } @@ -551,3 +552,38 @@ NAN_METHOD(Calib3D::ComputeCorrespondEpilines) NanReturnUndefined(); } } + +// cv::reprojectImageTo3D +NAN_METHOD(Calib3D::ReprojectImageTo3D) +{ + NanEscapableScope(); + + try { + // Get the arguments + + // Arg0, the disparity image + cv::Mat disparity = matFromMatrix(args[0]); + + // Arg1, the depth-to-disparity transformation Q + cv::Mat Q = matFromMatrix(args[1]); + + // Arg 2, handle missing values, skipped for now + + // Arg3, output bit depth, skipped for now + + // Compute the depth image + cv::Mat depthImage; + cv::reprojectImageTo3D(disparity, depthImage, Q); + + // Wrap the depth image + Local depthImageMatrix = matrixFromMat(depthImage); + + NanReturnValue(depthImageMatrix); + + + } catch (cv::Exception &e) { + const char *err_msg = e.what(); + NanThrowError(err_msg); + NanReturnUndefined(); + } +} diff --git a/src/Calib3D.h b/src/Calib3D.h index 9d5afbd8..4f06505f 100644 --- a/src/Calib3D.h +++ b/src/Calib3D.h @@ -24,6 +24,8 @@ class Calib3D: public node::ObjectWrap { static NAN_METHOD(StereoRectify); static NAN_METHOD(ComputeCorrespondEpilines); + + static NAN_METHOD(ReprojectImageTo3D); }; #endif From b1d77ab64ce80774570509dbedf58445bd334237 Mon Sep 17 00:00:00 2001 From: Max Ehrlich Date: Thu, 5 Feb 2015 14:39:22 -0500 Subject: [PATCH 49/83] Fixed naming error in computeCorrespondEpilines --- src/Calib3D.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Calib3D.cc b/src/Calib3D.cc index ebc4f806..4d1b12cf 100644 --- a/src/Calib3D.cc +++ b/src/Calib3D.cc @@ -536,9 +536,9 @@ NAN_METHOD(Calib3D::ComputeCorrespondEpilines) for(unsigned int i = 0; i < lines.size(); i++) { Local line_data = NanNew(); - line_data->Set(NanNew("a"), NanNew(corners[i][0])); - line_data->Set(NanNew("b"), NanNew(corners[i][1])); - line_data->Set(NanNew("c"), NanNew(corners[i][2])); + line_data->Set(NanNew("a"), NanNew(lines[i][0])); + line_data->Set(NanNew("b"), NanNew(lines[i][1])); + line_data->Set(NanNew("c"), NanNew(lines[i][2])); linesArray->Set(NanNew(i), line_data); } From 90244f1db2cd2b22482d1c6fbdd2ee723738f9b8 Mon Sep 17 00:00:00 2001 From: edgarsilva Date: Thu, 5 Feb 2015 16:24:18 -0600 Subject: [PATCH 50/83] Print available libraries for opencv. --- appveyor.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index 256371e4..6559ec1f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -50,6 +50,8 @@ before_build: - cmd: SET OPENCV_DIR=%OPENCV_ROOT_PATH%\build\%ARCH%\vc12\bin - cmd: SET PATH=%cd%\node_modules\.bin\;C:\MinGW\bin;C:\GTK\bin;C:\msys\1.0\bin;%OPENCV_DIR%;%PATH% - cmd: SET PKG_CONFIG_PATH=C:\GTK\lib\pkgconfig + - cmd: DIR %OPENCV_ROOT_PATH%\build\%ARCH%\vc12\bin + - cmd: DIR %OPENCV_ROOT_PATH%\build\%ARCH%\vc12\lib # Here we need to copy the opencv.pc file from the repo into PKG_CONFIG_PATH # trick part is to check for the vc12 folder and use that one - cmd: copy .\utils\opencv_x64.pc C:\GTK\lib\pkgconfig\opencv.pc From 081ac43f1ba3cf610554aa5931c3674f5778787e Mon Sep 17 00:00:00 2001 From: edgarsilva Date: Thu, 5 Feb 2015 16:53:02 -0600 Subject: [PATCH 51/83] Added all opencv libraries to opencv.pc file. --- utils/opencv_x64.pc | 3 ++- utils/opencv_x86.pc | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/utils/opencv_x64.pc b/utils/opencv_x64.pc index cf1fa63a..98b80c04 100644 --- a/utils/opencv_x64.pc +++ b/utils/opencv_x64.pc @@ -9,4 +9,5 @@ Description: Open Source Computer Vision Library Version: 2.4.9 Cflags: ${includedir} ${includedir}/opencv -Libs: ${libdir}/opencv_core249 ${libdir}/opencv_imgproc249 ${libdir}/opencv_highgui249 ${libdir}/opencv_ml249 ${libdir}/opencv_video249 ${libdir}/opencv_features2d249 ${libdir}/opencv_calib3d249 ${libdir}/opencv_objdetect249 ${libdir}/opencv_contrib249 ${libdir}/opencv_legacy249 ${libdir}/opencv_flann249 ${libdir}/opencv_core249 + +Libs: ${libdir}/opencv_calib3d249 ${libdir}/opencv_contrib249 ${libdir}/opencv_core249 ${libdir}/opencv_features2d249 ${libdir}/opencv_flann249 ${libdir}/opencv_gpu249 ${libdir}/opencv_highgui249 ${libdir}/opencv_imgproc249 ${libdir}/opencv_legacy249 ${libdir}/opencv_ml249 ${libdir}/opencv_nonfree249 ${libdir}/opencv_objdetect249 ${libdir}/opencv_ocl249 ${libdir}/opencv_photo249 ${libdir}/opencv_stitching249 ${libdir}/opencv_superres249 ${libdir}/opencv_ts249 ${libdir}/opencv_video249 ${libdir}/opencv_videostab249 diff --git a/utils/opencv_x86.pc b/utils/opencv_x86.pc index 7b993fc2..14026a12 100644 --- a/utils/opencv_x86.pc +++ b/utils/opencv_x86.pc @@ -9,4 +9,4 @@ Description: Open Source Computer Vision Library Version: 2.4.9 Cflags: ${includedir} ${includedir}/opencv -Libs: ${libdir}/opencv_core249 ${libdir}/opencv_imgproc249 ${libdir}/opencv_highgui249 ${libdir}/opencv_ml249 ${libdir}/opencv_video249 ${libdir}/opencv_features2d249 ${libdir}/opencv_calib3d249 ${libdir}/opencv_objdetect249 ${libdir}/opencv_contrib249 ${libdir}/opencv_legacy249 ${libdir}/opencv_flann249 ${libdir}/opencv_core249 +Libs: ${libdir}/opencv_calib3d249 ${libdir}/opencv_contrib249 ${libdir}/opencv_core249 ${libdir}/opencv_features2d249 ${libdir}/opencv_flann249 ${libdir}/opencv_gpu249 ${libdir}/opencv_highgui249 ${libdir}/opencv_imgproc249 ${libdir}/opencv_legacy249 ${libdir}/opencv_ml249 ${libdir}/opencv_nonfree249 ${libdir}/opencv_objdetect249 ${libdir}/opencv_ocl249 ${libdir}/opencv_photo249 ${libdir}/opencv_stitching249 ${libdir}/opencv_superres249 ${libdir}/opencv_ts249 ${libdir}/opencv_video249 ${libdir}/opencv_videostab249 From a405869720f1575747773f189c12a20128bb8ac5 Mon Sep 17 00:00:00 2001 From: edgarsilva Date: Thu, 5 Feb 2015 17:31:04 -0600 Subject: [PATCH 52/83] Test node-pre-gyp info for 64 bit. --- appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/appveyor.yml b/appveyor.yml index 6559ec1f..2f463a00 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -65,6 +65,7 @@ build_script: - cmd: ECHO "PUBLISH x64 binary package:" - cmd: npm install aws-sdk - cmd: IF %PUBLISH_BINARY%==true (node-pre-gyp package publish 2>&1) + - cmd: node-pre-gyp info - cmd: node-pre-gyp clean - cmd: node-gyp clean - cmd: npm uninstall -g node-gyp From a04ba455dd00158bcd46427ac2a473bb9c03d0d9 Mon Sep 17 00:00:00 2001 From: edgarsilva Date: Thu, 5 Feb 2015 17:48:44 -0600 Subject: [PATCH 53/83] Remove node-pre-gyp info call, since it is failing on windows. --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 2f463a00..0fdf15f3 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -65,7 +65,7 @@ build_script: - cmd: ECHO "PUBLISH x64 binary package:" - cmd: npm install aws-sdk - cmd: IF %PUBLISH_BINARY%==true (node-pre-gyp package publish 2>&1) - - cmd: node-pre-gyp info + #- cmd: node-pre-gyp info - cmd: node-pre-gyp clean - cmd: node-gyp clean - cmd: npm uninstall -g node-gyp @@ -99,7 +99,7 @@ on_success: #- cmd: IF %PUBLISH_BINARY%==true npm install --fallback-to-build=false - cmd: npm install --fallback-to-build=false # Print Available Binaries - - cmd: node-pre-gyp info + #- cmd: node-pre-gyp info test: OFF From 055c7a24052633b259d77bdfefda61911fc0b526 Mon Sep 17 00:00:00 2001 From: edgarsilva Date: Thu, 5 Feb 2015 18:31:13 -0600 Subject: [PATCH 54/83] Bring back node-pre-gyp info to investigate why branch passes but not master. --- appveyor.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 0fdf15f3..6559ec1f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -65,7 +65,6 @@ build_script: - cmd: ECHO "PUBLISH x64 binary package:" - cmd: npm install aws-sdk - cmd: IF %PUBLISH_BINARY%==true (node-pre-gyp package publish 2>&1) - #- cmd: node-pre-gyp info - cmd: node-pre-gyp clean - cmd: node-gyp clean - cmd: npm uninstall -g node-gyp @@ -99,7 +98,7 @@ on_success: #- cmd: IF %PUBLISH_BINARY%==true npm install --fallback-to-build=false - cmd: npm install --fallback-to-build=false # Print Available Binaries - #- cmd: node-pre-gyp info + - cmd: node-pre-gyp info test: OFF From e7b3cab803e9f3a12057999e9af45b8a7dc78727 Mon Sep 17 00:00:00 2001 From: Max Ehrlich Date: Fri, 6 Feb 2015 10:27:20 -0500 Subject: [PATCH 55/83] Added Stereo block matching algorithm --- binding.gyp | 1 + src/Stereo.cc | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/Stereo.h | 19 ++++++++++ src/init.cc | 2 ++ 4 files changed, 121 insertions(+) create mode 100644 src/Stereo.cc create mode 100644 src/Stereo.h diff --git a/binding.gyp b/binding.gyp index 449c0880..846b6b06 100755 --- a/binding.gyp +++ b/binding.gyp @@ -16,6 +16,7 @@ , "src/Constants.cc" , "src/Calib3D.cc" , "src/ImgProc.cc" + , "src/Stereo.cc" ] , 'libraries': [ ' StereoBM::constructor; + +void +StereoBM::Init(Handle target) { + NanScope(); + + Local ctor = NanNew(StereoBM::New); + NanAssignPersistent(constructor, ctor); + ctor->InstanceTemplate()->SetInternalFieldCount(1); + ctor->SetClassName(NanNew("StereoBM")); + + NODE_SET_PROTOTYPE_METHOD(ctor, "compute", Compute); + + ctor->Set(NanNew("BASIC_PRESET"), NanNew((int)cv::StereoBM::BASIC_PRESET)); + ctor->Set(NanNew("FISH_EYE_PRESET"), NanNew((int)cv::StereoBM::FISH_EYE_PRESET)); + ctor->Set(NanNew("NARROW_PRESET"), NanNew((int)cv::StereoBM::NARROW_PRESET)); + + target->Set(NanNew("StereoBM"), ctor->GetFunction()); +} + +NAN_METHOD(StereoBM::New) { + NanScope(); + + if (args.This()->InternalFieldCount() == 0) + NanThrowTypeError("Cannot instantiate without new"); + + StereoBM *stereo; + + if (args.Length() == 0) + { + stereo = new StereoBM(); + } + else if (args.Length() == 1) + { + stereo = new StereoBM(args[0]->IntegerValue()); // preset + } + else if (args.Length() == 2) + { + stereo = new StereoBM(args[0]->IntegerValue(), args[1]->IntegerValue()); // preset, disparity search range + } + else + { + stereo = new StereoBM(args[0]->IntegerValue(), args[1]->IntegerValue(), args[2]->IntegerValue()); // preset, disparity search range, sum of absolute differences window size + } + + stereo->Wrap(args.Holder()); + NanReturnValue(args.Holder()); +} + +StereoBM::StereoBM(int preset, int ndisparities, int SADWindowSize) + : ObjectWrap(), stereo(preset, ndisparities, SADWindowSize) +{ + +} + +// TODO make this async +NAN_METHOD(StereoBM::Compute) +{ + SETUP_FUNCTION(StereoBM) + + try { + // Get the arguments + + // Arg 0, the 'left' image + Matrix* m0 = ObjectWrap::Unwrap(args[0]->ToObject()); + cv::Mat left = m0->mat; + + // Arg 1, the 'right' image + Matrix* m1 = ObjectWrap::Unwrap(args[1]->ToObject()); + cv::Mat right = m1->mat; + + // Optional 3rd arg, the disparty depth + int type = CV_16S; + if(args.Length() > 2) + { + type = args[2]->IntegerValue(); + } + + // Compute stereo using the block matching algorithm + cv::Mat disparity; + self->stereo(left, right, disparity, type); + + // Wrap the returned disparity map + Local disparityWrap = NanNew(Matrix::constructor)->GetFunction()->NewInstance(); + Matrix *disp = ObjectWrap::Unwrap(disparityWrap); + disp->mat = disparity; + + NanReturnValue(disparityWrap); + + } catch (cv::Exception &e) { + const char *err_msg = e.what(); + NanThrowError(err_msg); + NanReturnUndefined(); + } + +}; diff --git a/src/Stereo.h b/src/Stereo.h new file mode 100644 index 00000000..71490669 --- /dev/null +++ b/src/Stereo.h @@ -0,0 +1,19 @@ +#ifndef __NODE_STEREO_H +#define __NODE_STEREO_H + +#include "OpenCV.h" + +class StereoBM: public node::ObjectWrap { +public: + cv::StereoBM stereo; + + static Persistent constructor; + static void Init(Handle target); + static NAN_METHOD(New); + + StereoBM(int preset = cv::StereoBM::BASIC_PRESET, int ndisparities = 0, int SADWindowSize=21); + + JSFUNC(Compute); +}; + +#endif diff --git a/src/init.cc b/src/init.cc index 95eef1af..8cf0cec0 100755 --- a/src/init.cc +++ b/src/init.cc @@ -11,6 +11,7 @@ #include "Constants.h" #include "Calib3D.h" #include "ImgProc.h" +#include "Stereo.h" extern "C" void init(Handle target) { @@ -27,6 +28,7 @@ init(Handle target) { Constants::Init(target); Calib3D::Init(target); ImgProc::Init(target); + StereoBM::Init(target); #if CV_MAJOR_VERSION >= 2 && CV_MINOR_VERSION >=4 From 487ac8a13705d2877cbe1c2659d8399621d39eec Mon Sep 17 00:00:00 2001 From: Max Ehrlich Date: Fri, 6 Feb 2015 11:06:58 -0500 Subject: [PATCH 56/83] Added semi-global block matching stereo --- src/Stereo.cc | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/Stereo.h | 24 +++++++++ src/init.cc | 1 + 3 files changed, 159 insertions(+) diff --git a/src/Stereo.cc b/src/Stereo.cc index 4cab060f..454fb6a8 100644 --- a/src/Stereo.cc +++ b/src/Stereo.cc @@ -1,6 +1,8 @@ #include "Stereo.h" #include "Matrix.h" +// Block matching + v8::Persistent StereoBM::constructor; void @@ -97,3 +99,135 @@ NAN_METHOD(StereoBM::Compute) } }; + +// Semi-Global Block matching + +v8::Persistent StereoSGBM::constructor; + +void +StereoSGBM::Init(Handle target) { + NanScope(); + + Local ctor = NanNew(StereoSGBM::New); + NanAssignPersistent(constructor, ctor); + ctor->InstanceTemplate()->SetInternalFieldCount(1); + ctor->SetClassName(NanNew("StereoSGBM")); + + NODE_SET_PROTOTYPE_METHOD(ctor, "compute", Compute); + + target->Set(NanNew("StereoSGBM"), ctor->GetFunction()); +} + +NAN_METHOD(StereoSGBM::New) { + NanScope(); + + if (args.This()->InternalFieldCount() == 0) + NanThrowTypeError("Cannot instantiate without new"); + + StereoSGBM *stereo; + + if (args.Length() == 0) + { + stereo = new StereoSGBM(); + } + else + { + // If passing arguments, must pass the first 3 at least + if (args.Length() >= 3) + { + switch (args.Length()) + { + case 3: + stereo = new StereoSGBM(args[0]->IntegerValue(), args[1]->IntegerValue(), args[2]->IntegerValue()); + break; + + case 4: + stereo = new StereoSGBM(args[0]->IntegerValue(), args[1]->IntegerValue(), args[2]->IntegerValue(), args[3]->IntegerValue()); + break; + + case 5: + stereo = new StereoSGBM(args[0]->IntegerValue(), args[1]->IntegerValue(), args[2]->IntegerValue(), args[3]->IntegerValue(), args[4]->IntegerValue()); + break; + + case 6: + stereo = new StereoSGBM(args[0]->IntegerValue(), args[1]->IntegerValue(), args[2]->IntegerValue(), args[3]->IntegerValue(), args[4]->IntegerValue(), args[5]->IntegerValue()); + break; + + case 7: + stereo = new StereoSGBM(args[0]->IntegerValue(), args[1]->IntegerValue(), args[2]->IntegerValue(), args[3]->IntegerValue(), args[4]->IntegerValue(), args[5]->IntegerValue(), args[6]->IntegerValue()); + break; + + case 8: + stereo = new StereoSGBM(args[0]->IntegerValue(), args[1]->IntegerValue(), args[2]->IntegerValue(), args[3]->IntegerValue(), args[4]->IntegerValue(), args[5]->IntegerValue(), args[6]->IntegerValue(), args[7]->IntegerValue()); + break; + + case 9: + stereo = new StereoSGBM(args[0]->IntegerValue(), args[1]->IntegerValue(), args[2]->IntegerValue(), args[3]->IntegerValue(), args[4]->IntegerValue(), args[5]->IntegerValue(), args[6]->IntegerValue(), args[7]->IntegerValue(), args[8]->IntegerValue()); + break; + + case 10: + stereo = new StereoSGBM(args[0]->IntegerValue(), args[1]->IntegerValue(), args[2]->IntegerValue(), args[3]->IntegerValue(), args[4]->IntegerValue(), args[5]->IntegerValue(), args[6]->IntegerValue(), args[7]->IntegerValue(), args[8]->IntegerValue(), args[9]->IntegerValue()); + break; + + default: + stereo = new StereoSGBM(args[0]->IntegerValue(), args[1]->IntegerValue(), args[2]->IntegerValue(), args[3]->IntegerValue(), args[4]->IntegerValue(), args[5]->IntegerValue(), args[6]->IntegerValue(), args[7]->IntegerValue(), args[8]->IntegerValue(), args[9]->IntegerValue(), args[10]->ToBoolean()->Value()); + break; + } + } + else + { + NanThrowError("If overriding default settings, must pass minDisparity, numDisparities, and SADWindowSize"); + NanReturnUndefined(); + } + } + + stereo->Wrap(args.Holder()); + NanReturnValue(args.Holder()); +} + +StereoSGBM::StereoSGBM() + : ObjectWrap(), stereo() +{ + +} + +StereoSGBM::StereoSGBM(int minDisparity, int ndisparities, int SADWindowSize, int p1, int p2, int disp12MaxDiff, int preFilterCap, int uniquenessRatio, int speckleWindowSize, int speckleRange, bool fullDP) + : ObjectWrap(), stereo(minDisparity, ndisparities, SADWindowSize, p1, p2, disp12MaxDiff, preFilterCap, uniquenessRatio, speckleWindowSize, speckleRange, fullDP) +{ + +} + +// TODO make this async +NAN_METHOD(StereoSGBM::Compute) +{ + SETUP_FUNCTION(StereoSGBM) + + try { + // Get the arguments + + // Arg 0, the 'left' image + Matrix* m0 = ObjectWrap::Unwrap(args[0]->ToObject()); + cv::Mat left = m0->mat; + + // Arg 1, the 'right' image + Matrix* m1 = ObjectWrap::Unwrap(args[1]->ToObject()); + cv::Mat right = m1->mat; + + // Compute stereo using the block matching algorithm + cv::Mat disparity; + self->stereo(left, right, disparity); + + // Wrap the returned disparity map + Local disparityWrap = NanNew(Matrix::constructor)->GetFunction()->NewInstance(); + Matrix *disp = ObjectWrap::Unwrap(disparityWrap); + disp->mat = disparity; + + NanReturnValue(disparityWrap); + + } catch (cv::Exception &e) { + const char *err_msg = e.what(); + NanThrowError(err_msg); + NanReturnUndefined(); + } + +}; diff --git a/src/Stereo.h b/src/Stereo.h index 71490669..c1449899 100644 --- a/src/Stereo.h +++ b/src/Stereo.h @@ -16,4 +16,28 @@ class StereoBM: public node::ObjectWrap { JSFUNC(Compute); }; +class StereoSGBM: public node::ObjectWrap { +public: + cv::StereoSGBM stereo; + + static Persistent constructor; + static void Init(Handle target); + static NAN_METHOD(New); + + StereoSGBM(); + StereoSGBM(int minDisparity, + int ndisparities, + int SADWindowSize, + int p1 = 0, + int p2 = 0, + int disp12MaxDiff = 0, + int preFilterCap = 0, + int uniquenessRatio = 0, + int speckleWindowSize = 0, + int speckleRange = 0, + bool fullDP = false); + + JSFUNC(Compute); +}; + #endif diff --git a/src/init.cc b/src/init.cc index 8cf0cec0..af7c474c 100755 --- a/src/init.cc +++ b/src/init.cc @@ -29,6 +29,7 @@ init(Handle target) { Calib3D::Init(target); ImgProc::Init(target); StereoBM::Init(target); + StereoSGBM::Init(target); #if CV_MAJOR_VERSION >= 2 && CV_MINOR_VERSION >=4 From 44695e0c61cb70af9fe10e3aadfec62f96871211 Mon Sep 17 00:00:00 2001 From: edgarsilva Date: Fri, 6 Feb 2015 11:26:46 -0600 Subject: [PATCH 57/83] Test install from pre compiled binaries --- appveyor.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 6559ec1f..257ed74d 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -59,7 +59,8 @@ before_build: # to run your custom scripts instead of automatic MSBuild build_script: - cmd: ECHO "BUILDING x64 binary package:" - - cmd: npm install --build-from-source --msvs_version=2013 + #- cmd: npm install --build-from-source --msvs_version=2013 + - cmd: npm install --msvs_version=2013 - cmd: npm test - cmd: node lib/opencv.js - cmd: ECHO "PUBLISH x64 binary package:" @@ -81,7 +82,8 @@ after_build: - cmd: npm install -g node-gyp - cmd: copy .\utils\opencv_x86.pc C:\GTK\lib\pkgconfig\opencv.pc - cmd: ECHO "BUILDING x86 binary package:" - - cmd: npm install --build-from-source --msvs_version=2013 + #- cmd: npm install --build-from-source --msvs_version=2013 + - cmd: npm install --msvs_version=2013 - cmd: npm test - cmd: node lib/opencv.js - cmd: ECHO "PUBLISH x86 binary package:" From 3558be3d50f03e80b002b519762f09b18ea790a3 Mon Sep 17 00:00:00 2001 From: edgarsilva Date: Fri, 6 Feb 2015 15:40:25 -0600 Subject: [PATCH 58/83] Always build from source in appveyor. --- appveyor.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 257ed74d..6559ec1f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -59,8 +59,7 @@ before_build: # to run your custom scripts instead of automatic MSBuild build_script: - cmd: ECHO "BUILDING x64 binary package:" - #- cmd: npm install --build-from-source --msvs_version=2013 - - cmd: npm install --msvs_version=2013 + - cmd: npm install --build-from-source --msvs_version=2013 - cmd: npm test - cmd: node lib/opencv.js - cmd: ECHO "PUBLISH x64 binary package:" @@ -82,8 +81,7 @@ after_build: - cmd: npm install -g node-gyp - cmd: copy .\utils\opencv_x86.pc C:\GTK\lib\pkgconfig\opencv.pc - cmd: ECHO "BUILDING x86 binary package:" - #- cmd: npm install --build-from-source --msvs_version=2013 - - cmd: npm install --msvs_version=2013 + - cmd: npm install --build-from-source --msvs_version=2013 - cmd: npm test - cmd: node lib/opencv.js - cmd: ECHO "PUBLISH x86 binary package:" From d0400ec5aed2f29398551da797737727ac3ddda4 Mon Sep 17 00:00:00 2001 From: Max Ehrlich Date: Mon, 9 Feb 2015 18:19:00 -0500 Subject: [PATCH 59/83] Added graph-cut stereo algorithm --- src/Stereo.cc | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/Stereo.h | 15 +++++++++ 2 files changed, 105 insertions(+) diff --git a/src/Stereo.cc b/src/Stereo.cc index 454fb6a8..54da7af6 100644 --- a/src/Stereo.cc +++ b/src/Stereo.cc @@ -1,5 +1,6 @@ #include "Stereo.h" #include "Matrix.h" +#include // Block matching @@ -231,3 +232,92 @@ NAN_METHOD(StereoSGBM::Compute) } }; + +// Graph cut + +v8::Persistent StereoGC::constructor; + +void +StereoGC::Init(Handle target) { + NanScope(); + + Local ctor = NanNew(StereoGC::New); + NanAssignPersistent(constructor, ctor); + ctor->InstanceTemplate()->SetInternalFieldCount(1); + ctor->SetClassName(NanNew("StereoGC")); + + NODE_SET_PROTOTYPE_METHOD(ctor, "compute", Compute); + + target->Set(NanNew("StereoGC"), ctor->GetFunction()); +} + +NAN_METHOD(StereoGC::New) { + NanScope(); + + if (args.This()->InternalFieldCount() == 0) + NanThrowTypeError("Cannot instantiate without new"); + + StereoGC *stereo; + + if (args.Length() == 0) + { + stereo = new StereoGC(); + } + else if (args.Length() == 1) + { + stereo = new StereoGC(args[0]->IntegerValue()); // numberOfDisparities + } + else + { + stereo = new StereoGC(args[0]->IntegerValue(), args[1]->IntegerValue()); // max iterations + } + + stereo->Wrap(args.Holder()); + NanReturnValue(args.Holder()); +} + +StereoGC::StereoGC(int numberOfDisparities, int maxIters) +: ObjectWrap() +{ + stereo = cvCreateStereoGCState(numberOfDisparities, maxIters); +} + +// TODO make this async +NAN_METHOD(StereoGC::Compute) +{ + SETUP_FUNCTION(StereoGC) + + try { + // Get the arguments + + // Arg 0, the 'left' image + Matrix* m0 = ObjectWrap::Unwrap(args[0]->ToObject()); + cv::Mat left = m0->mat; + + // Arg 1, the 'right' image + Matrix* m1 = ObjectWrap::Unwrap(args[1]->ToObject()); + cv::Mat right = m1->mat; + + // Compute stereo using the block matching algorithm + CvMat left_leg = left, right_leg = right; + CvMat *disp_left = cvCreateMat(left.rows, left.cols, CV_16S), *disp_right = cvCreateMat(right.rows, right.cols, CV_16S); + cvFindStereoCorrespondenceGC(&left_leg, &right_leg, disp_left, disp_right, self->stereo, 0); + + cv::Mat disp16 = disp_left; + cv::Mat disparity(disp16.rows, disp16.cols, CV_8U); + disp16.convertTo(disparity, CV_8U, -16); + + // Wrap the returned disparity map + Local disparityWrap = NanNew(Matrix::constructor)->GetFunction()->NewInstance(); + Matrix *disp = ObjectWrap::Unwrap(disparityWrap); + disp->mat = disparity; + + NanReturnValue(disparityWrap); + + } catch (cv::Exception &e) { + const char *err_msg = e.what(); + NanThrowError(err_msg); + NanReturnUndefined(); + } + +}; diff --git a/src/Stereo.h b/src/Stereo.h index c1449899..569a6d65 100644 --- a/src/Stereo.h +++ b/src/Stereo.h @@ -40,4 +40,19 @@ class StereoSGBM: public node::ObjectWrap { JSFUNC(Compute); }; +struct CvStereoGCState; + +class StereoGC: public node::ObjectWrap { +public: + CvStereoGCState *stereo; + + static Persistent constructor; + static void Init(Handle target); + static NAN_METHOD(New); + + StereoGC(int numberOfDisparities = 16, int maxIterations = 2); + + JSFUNC(Compute); +}; + #endif From c36350ade89844cd05ece165f06f60ec40bcfcc4 Mon Sep 17 00:00:00 2001 From: Peter Braden Date: Wed, 11 Feb 2015 18:32:25 +0100 Subject: [PATCH 60/83] Move smoke test into makefile --- Makefile | 14 +++++++++----- smoke/smoke.sh | 14 -------------- 2 files changed, 9 insertions(+), 19 deletions(-) delete mode 100755 smoke/smoke.sh diff --git a/Makefile b/Makefile index 129b06f6..bcacd408 100644 --- a/Makefile +++ b/Makefile @@ -1,11 +1,15 @@ VERSION := $(shell node -e "console.log(require('./package.json').version)") -.PHONY: default release +.PHONY: default release smoke + +test: + npm test + +smoke: + npm install --build-from-source + node smoke/smoketest.js + npm test -# Add a default task so we don't release just because someone ran 'make' -default: - @echo "Did you mean to release a new version?" - @echo "If so, run 'make release'." release: @echo "Tagging release $(VERSION)" diff --git a/smoke/smoke.sh b/smoke/smoke.sh deleted file mode 100755 index 84fab840..00000000 --- a/smoke/smoke.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash - -if [ ! -f smoke/smoketest.js ]; then - echo "Please run smoke test from the top-level folder of the repository." >&2 - exit 1 -fi - -node-gyp build && echo '-- Compiled OK -- - -' && node smoke/smoketest.js && echo '-- Smoke Done, running tests -- - -' && npm test # && echo '-- Tests Run, runnning examples -- -#(building example data) -#' && ./examples/make-example-files.sh && node examples/motion-track.js From cfc6c16721fa79b6a45e9b1e9a0e37a536c1a08a Mon Sep 17 00:00:00 2001 From: Peter Braden Date: Wed, 11 Feb 2015 18:35:00 +0100 Subject: [PATCH 61/83] Remove unused 'sleep_for' variable to suppress compile warning --- src/CascadeClassifierWrap.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/CascadeClassifierWrap.cc b/src/CascadeClassifierWrap.cc index d2f8871b..ac8a35fc 100755 --- a/src/CascadeClassifierWrap.cc +++ b/src/CascadeClassifierWrap.cc @@ -50,7 +50,7 @@ CascadeClassifierWrap::CascadeClassifierWrap(v8::Value* fileName){ class AsyncDetectMultiScale : public NanAsyncWorker { public: - AsyncDetectMultiScale(NanCallback *callback, CascadeClassifierWrap *cc, Matrix* im, double scale, int neighbors, int minw, int minh, int sleep_for) : NanAsyncWorker(callback), cc(cc), im(im), scale(scale), neighbors(neighbors), minw(minw), minh(minh), sleep_for(sleep_for) {} + AsyncDetectMultiScale(NanCallback *callback, CascadeClassifierWrap *cc, Matrix* im, double scale, int neighbors, int minw, int minh) : NanAsyncWorker(callback), cc(cc), im(im), scale(scale), neighbors(neighbors), minw(minw), minh(minh) {} ~AsyncDetectMultiScale() {} void Execute () { @@ -103,7 +103,6 @@ class AsyncDetectMultiScale : public NanAsyncWorker { int neighbors; int minw; int minh; - int sleep_for; std::vector res; }; @@ -141,7 +140,7 @@ NAN_METHOD(CascadeClassifierWrap::DetectMultiScale){ NanCallback *callback = new NanCallback(cb.As()); - NanAsyncQueueWorker( new AsyncDetectMultiScale(callback, self, im, scale, neighbors, minw, minh, 1) ); + NanAsyncQueueWorker( new AsyncDetectMultiScale(callback, self, im, scale, neighbors, minw, minh) ); NanReturnUndefined(); } From 373fa339f71a19046f0b363aaa25ca6642dee153 Mon Sep 17 00:00:00 2001 From: Peter Braden Date: Wed, 11 Feb 2015 18:35:00 +0100 Subject: [PATCH 62/83] Remove unused 'sleep_for' variable to suppress compile warning --- src/CascadeClassifierWrap.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/CascadeClassifierWrap.cc b/src/CascadeClassifierWrap.cc index d2f8871b..ac8a35fc 100755 --- a/src/CascadeClassifierWrap.cc +++ b/src/CascadeClassifierWrap.cc @@ -50,7 +50,7 @@ CascadeClassifierWrap::CascadeClassifierWrap(v8::Value* fileName){ class AsyncDetectMultiScale : public NanAsyncWorker { public: - AsyncDetectMultiScale(NanCallback *callback, CascadeClassifierWrap *cc, Matrix* im, double scale, int neighbors, int minw, int minh, int sleep_for) : NanAsyncWorker(callback), cc(cc), im(im), scale(scale), neighbors(neighbors), minw(minw), minh(minh), sleep_for(sleep_for) {} + AsyncDetectMultiScale(NanCallback *callback, CascadeClassifierWrap *cc, Matrix* im, double scale, int neighbors, int minw, int minh) : NanAsyncWorker(callback), cc(cc), im(im), scale(scale), neighbors(neighbors), minw(minw), minh(minh) {} ~AsyncDetectMultiScale() {} void Execute () { @@ -103,7 +103,6 @@ class AsyncDetectMultiScale : public NanAsyncWorker { int neighbors; int minw; int minh; - int sleep_for; std::vector res; }; @@ -141,7 +140,7 @@ NAN_METHOD(CascadeClassifierWrap::DetectMultiScale){ NanCallback *callback = new NanCallback(cb.As()); - NanAsyncQueueWorker( new AsyncDetectMultiScale(callback, self, im, scale, neighbors, minw, minh, 1) ); + NanAsyncQueueWorker( new AsyncDetectMultiScale(callback, self, im, scale, neighbors, minw, minh) ); NanReturnUndefined(); } From 03ce7973bf39988cc428bdf14f4b62c7538d3fc6 Mon Sep 17 00:00:00 2001 From: Peter Braden Date: Wed, 11 Feb 2015 19:20:19 +0100 Subject: [PATCH 63/83] Use Nan for template matches --- src/Matrix.cc | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/Matrix.cc b/src/Matrix.cc index 40b9dc8b..d1f53823 100755 --- a/src/Matrix.cc +++ b/src/Matrix.cc @@ -1730,11 +1730,8 @@ NAN_METHOD(Matrix::FloodFill){ // @author olfox // Returns an array of the most probable positions // Usage: output = input.templateMatches(min_probability, max_probability, limit, ascending, min_x_distance, min_y_distance); -Handle -Matrix::TemplateMatches(const v8::Arguments& args) { - HandleScope scope; - - Matrix *self = ObjectWrap::Unwrap(args.This()); +NAN_METHOD(Matrix::TemplateMatches){ + SETUP_FUNCTION(Matrix) bool filter_min_probability = (args.Length() >= 1) ? args[0]->IsNumber() : false; bool filter_max_probability = (args.Length() >= 2) ? args[1]->IsNumber() : false; From ae5887c4cd21a145124074bd45164657fc325053 Mon Sep 17 00:00:00 2001 From: Peter Braden Date: Wed, 11 Feb 2015 19:44:38 +0100 Subject: [PATCH 64/83] Use Nan for rest of the method --- src/Matrix.cc | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Matrix.cc b/src/Matrix.cc index d1f53823..1f0b9d95 100755 --- a/src/Matrix.cc +++ b/src/Matrix.cc @@ -1750,7 +1750,7 @@ NAN_METHOD(Matrix::TemplateMatches){ cv::sortIdx(self->mat.reshape(0,1), indices, CV_SORT_DESCENDING + CV_SORT_EVERY_ROW); cv::Mat hit_mask = cv::Mat::zeros(self->mat.size(), CV_64F); - v8::Local probabilites_array = v8::Array::New(); + v8::Local probabilites_array = NanNew(limit); cv::Mat_::const_iterator begin = self->mat.begin(); cv::Mat_::const_iterator it = indices.begin(); @@ -1789,20 +1789,20 @@ NAN_METHOD(Matrix::TemplateMatches){ cv::rectangle(hit_mask, top_left, bottom_right, color, CV_FILLED); } - Local x_value = v8::Number::New(pt.x); - Local y_value = v8::Number::New(pt.y); - Local probability_value = v8::Number::New(probability); + Local x_value = NanNew(pt.x); + Local y_value = NanNew(pt.y); + Local probability_value = NanNew(probability); - Local probability_object = Object::New(); - probability_object->Set(String::NewSymbol("x"), x_value); - probability_object->Set(String::NewSymbol("y"), y_value); - probability_object->Set(String::NewSymbol("probability"), probability_value); + Local probability_object = NanNew(); + probability_object->Set(NanNew("x"), x_value); + probability_object->Set(NanNew("y"), y_value); + probability_object->Set(NanNew("probability"), probability_value); probabilites_array->Set(index, probability_object); index++; } - return scope.Close(probabilites_array); + NanReturnValue(probabilites_array); } // @author ytham From 4618b158804b1301444498e0339ad2d334b64c3d Mon Sep 17 00:00:00 2001 From: Peter Braden Date: Wed, 11 Feb 2015 19:45:13 +0100 Subject: [PATCH 65/83] Travis test 0.12 --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index eae5110b..52ec0ef3 100755 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,7 @@ language: node_js node_js: - "0.10" - "0.11" + - "0.12" before_install: - sudo apt-get update From 9e4f904da76433164ff768fd1e2c6aadd409d052 Mon Sep 17 00:00:00 2001 From: Peter Braden Date: Wed, 11 Feb 2015 19:52:11 +0100 Subject: [PATCH 66/83] Keep changelog up to date --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 86c9edbb..6247af4d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,18 @@ # Changelog +### Next + +- Support for node 0.12 +- Camera Calibration Functions from @queuecumber +- Fix for Nan 1.5.1 from @IMGNRY +- More build fixes from @scanlime +- Matrix crop prototype from @dbpieter +- Many fixes from @madshall + +Thanks to everyone that contributed! + + ### 1.0.0 Ok, let's do a proper semver release :) From 081ca6056fac34716b212d62f1224c9f662ac99e Mon Sep 17 00:00:00 2001 From: Peter Braden Date: Wed, 11 Feb 2015 19:52:50 +0100 Subject: [PATCH 67/83] Much overdue release. 2.0.0 --- CHANGELOG.md | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6247af4d..d5a7a625 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog -### Next +### 2.0.0 - Support for node 0.12 - Camera Calibration Functions from @queuecumber diff --git a/package.json b/package.json index 7ce4b0a6..04018262 100755 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "buffers": "0.1.1", "nan": "1.4.3" }, - "version": "1.0.0", + "version": "2.0.0", "devDependencies": { "tape": "^3.0.0" }, From 0c72d55ec447b55ef6fa625240046147dfdbba5e Mon Sep 17 00:00:00 2001 From: Peter Braden Date: Wed, 11 Feb 2015 20:15:01 +0100 Subject: [PATCH 68/83] Fix example paths --- examples/car-detection.js | 8 ++++---- examples/color-filter.js | 4 ++-- examples/contours.js | 8 ++++---- examples/convert-image.js | 12 ++++++------ examples/detect-shapes.js | 6 +++--- examples/face-detection-rectangle.js | 8 ++++---- examples/face-detection.js | 8 ++++---- examples/quad-crosses.js | 6 +++--- examples/salt.js | 2 +- examples/warp-image.js | 4 ++-- test/examples.js | 7 ++++++- 11 files changed, 39 insertions(+), 34 deletions(-) diff --git a/examples/car-detection.js b/examples/car-detection.js index 95a5afa8..58c2d61f 100644 --- a/examples/car-detection.js +++ b/examples/car-detection.js @@ -1,10 +1,10 @@ var cv = require('../lib/opencv'); -cv.readImage("./examples/files/car1.jpg", function(err, im){ +cv.readImage("./files/car1.jpg", function(err, im){ if (err) throw err; if (im.width() < 1 || im.height() < 1) throw new Error('Image has no size'); - im.detectObject("./data/hogcascade_cars_sideview.xml", {}, function(err, cars){ + im.detectObject("../data/hogcascade_cars_sideview.xml", {}, function(err, cars){ if (err) throw err; for (var i=0; i < cars.length; i++){ @@ -12,7 +12,7 @@ cv.readImage("./examples/files/car1.jpg", function(err, im){ im.rectangle([x.x, x.y], [x.width, x.height]); } - im.save('./examples/tmp/car-detection.jpg'); - console.log('Image saved to ./examples/tmp/car-detection.jpg'); + im.save('./tmp/car-detection.jpg'); + console.log('Image saved to ./tmp/car-detection.jpg'); }); }); diff --git a/examples/color-filter.js b/examples/color-filter.js index 031b65d2..b7c5d6a9 100644 --- a/examples/color-filter.js +++ b/examples/color-filter.js @@ -4,11 +4,11 @@ var cv = require('../lib/opencv'); var lower_threshold = [46, 57, 83]; var upper_threshold = [80, 96, 115]; -cv.readImage('./examples/files/coin1.jpg', function(err, im) { +cv.readImage('./files/coin1.jpg', function(err, im) { if (err) throw err; if (im.width() < 1 || im.height() < 1) throw new Error('Image has no size'); im.inRange(lower_threshold, upper_threshold); - im.save('./examples/tmp/coin_detected.jpg'); + im.save('./tmp/coin_detected.jpg'); console.log('Image saved to ./tmp/coin_detected.jpg'); }); diff --git a/examples/contours.js b/examples/contours.js index 842011e3..43bb0ac4 100755 --- a/examples/contours.js +++ b/examples/contours.js @@ -9,7 +9,7 @@ var GREEN = [0, 255, 0]; // B, G, R var WHITE = [255, 255, 255]; // B, G, R var RED = [0, 0, 255]; // B, G, R -cv.readImage('./examples/files/stuff.png', function(err, im) { +cv.readImage('./files/stuff.png', function(err, im) { if (err) throw err; var width = im.width(); var height = im.height(); @@ -39,7 +39,7 @@ cv.readImage('./examples/files/stuff.png', function(err, im) { all.drawAllContours(contours, WHITE); - big.save('./examples/tmp/big.png'); - all.save('./examples/tmp/all.png'); - console.log('Image saved to ./examples/tmp/big.png && ./tmp/all.png'); + big.save('./tmp/big.png'); + all.save('./tmp/all.png'); + console.log('Image saved to ./tmp/big.png && ./tmp/all.png'); }); diff --git a/examples/convert-image.js b/examples/convert-image.js index dbc9f0c2..7f62ff3d 100755 --- a/examples/convert-image.js +++ b/examples/convert-image.js @@ -1,6 +1,6 @@ var cv = require('../lib/opencv'); -cv.readImage('./examples/files/mona.png', function(err, im) { +cv.readImage('./files/mona.png', function(err, im) { if (err) throw err; if (im.width() < 1 || im.height() < 1) throw new Error('Image has no size'); @@ -10,12 +10,12 @@ cv.readImage('./examples/files/mona.png', function(err, im) { img_hsv.convertHSVscale(); img_gray.convertGrayscale(); - im.save('./examples/tmp/nor.png'); - img_hsv.save('./examples/tmp/hsv.png'); - img_gray.save('./examples/tmp/gray.png'); + im.save('./tmp/nor.png'); + img_hsv.save('./tmp/hsv.png'); + img_gray.save('./tmp/gray.png'); img_crop = im.crop(50,50,250,250); - img_crop.save('./examples/tmp/crop.png'); + img_crop.save('./tmp/crop.png'); - console.log('Image saved to ./examples/tmp/{crop|nor|hsv|gray}.png'); + console.log('Image saved to ./tmp/{crop|nor|hsv|gray}.png'); }); diff --git a/examples/detect-shapes.js b/examples/detect-shapes.js index 63269959..f465d235 100755 --- a/examples/detect-shapes.js +++ b/examples/detect-shapes.js @@ -12,7 +12,7 @@ var GREEN = [0, 255, 0]; // B, G, R var WHITE = [255, 255, 255]; // B, G, R -cv.readImage('./examples/files/shapes.jpg', function(err, im) { +cv.readImage('./files/shapes.jpg', function(err, im) { if (err) throw err; width = im.width() @@ -46,6 +46,6 @@ cv.readImage('./examples/files/shapes.jpg', function(err, im) { } } - out.save('./examples/tmp/detect-shapes.png'); - console.log('Image saved to ./examples/tmp/detect-shapes.png'); + out.save('./tmp/detect-shapes.png'); + console.log('Image saved to ./tmp/detect-shapes.png'); }); diff --git a/examples/face-detection-rectangle.js b/examples/face-detection-rectangle.js index e2d4f873..f108eee9 100755 --- a/examples/face-detection-rectangle.js +++ b/examples/face-detection-rectangle.js @@ -3,11 +3,11 @@ var cv = require('../lib/opencv'); var COLOR = [0, 255, 0]; // default red var thickness = 2; // default 1 -cv.readImage('./examples/files/mona.png', function(err, im) { +cv.readImage('./files/mona.png', function(err, im) { if (err) throw err; if (im.width() < 1 || im.height() < 1) throw new Error('Image has no size'); - im.detectObject('./data/haarcascade_frontalface_alt2.xml', {}, function(err, faces) { + im.detectObject('../data/haarcascade_frontalface_alt2.xml', {}, function(err, faces) { if (err) throw err; for (var i = 0; i < faces.length; i++) { @@ -15,8 +15,8 @@ cv.readImage('./examples/files/mona.png', function(err, im) { im.rectangle([face.x, face.y], [face.x + face.width, face.y + face.height], COLOR, 2); } - im.save('./examples/tmp/face-detection-rectangle.png'); - console.log('Image saved to ./examples/tmp/face-detection-rectangle.png'); + im.save('./tmp/face-detection-rectangle.png'); + console.log('Image saved to ./tmp/face-detection-rectangle.png'); }); }); diff --git a/examples/face-detection.js b/examples/face-detection.js index 185a78b5..0cc5fee1 100755 --- a/examples/face-detection.js +++ b/examples/face-detection.js @@ -1,10 +1,10 @@ var cv = require('../lib/opencv'); -cv.readImage("./examples/files/mona.png", function(err, im){ +cv.readImage("./files/mona.png", function(err, im){ if (err) throw err; if (im.width() < 1 || im.height() < 1) throw new Error('Image has no size'); - im.detectObject("./data/haarcascade_frontalface_alt.xml", {}, function(err, faces){ + im.detectObject("../data/haarcascade_frontalface_alt.xml", {}, function(err, faces){ if (err) throw err; for (var i = 0; i < faces.length; i++){ @@ -12,7 +12,7 @@ cv.readImage("./examples/files/mona.png", function(err, im){ im.ellipse(face.x + face.width / 2, face.y + face.height / 2, face.width / 2, face.height / 2); } - im.save('./examples/tmp/face-detection.png'); - console.log('Image saved to ./examples/tmp/face-detection.png'); + im.save('./tmp/face-detection.png'); + console.log('Image saved to ./tmp/face-detection.png'); }); }); diff --git a/examples/quad-crosses.js b/examples/quad-crosses.js index 1a3a558c..341631f2 100755 --- a/examples/quad-crosses.js +++ b/examples/quad-crosses.js @@ -12,7 +12,7 @@ var RED = [0, 0, 255]; //B, G, R var GREEN = [0, 255, 0]; //B, G, R var WHITE = [255, 255, 255]; //B, G, R -cv.readImage('./examples/files/quads.jpg', function(err, im) { +cv.readImage('./files/quads.jpg', function(err, im) { if (err) throw err; if (im.width() < 1 || im.height() < 1) throw new Error('Image has no size'); @@ -47,6 +47,6 @@ cv.readImage('./examples/files/quads.jpg', function(err, im) { out.line([points[1].x,points[1].y], [points[3].x, points[3].y], RED); } - out.save('./examples/tmp/quad-crosses.png'); - console.log('Image saved to ./examples/tmp/quad-crosses.png'); + out.save('./tmp/quad-crosses.png'); + console.log('Image saved to ./tmp/quad-crosses.png'); }); diff --git a/examples/salt.js b/examples/salt.js index d3212b25..737e834e 100755 --- a/examples/salt.js +++ b/examples/salt.js @@ -1,7 +1,7 @@ var cv = require('../lib/opencv'); cv.readImage("./files/mona.png", function(err, im) { - salt(im, 1000); + salt(im, 100); im.save("./tmp/salt.png"); console.log('Image saved to ./tmp/salt.png'); }); diff --git a/examples/warp-image.js b/examples/warp-image.js index bcf13b86..8549bf9c 100644 --- a/examples/warp-image.js +++ b/examples/warp-image.js @@ -1,6 +1,6 @@ var cv = require('../lib/opencv'); -cv.readImage("./examples/files/mona.png", function(err, im) { +cv.readImage("./files/mona.png", function(err, im) { if (err) throw err; var width = im.width(); @@ -11,6 +11,6 @@ cv.readImage("./examples/files/mona.png", function(err, im) { var dstArray = [0, 0, width * 0.9, height * 0.1, width, height, width * 0.2, height * 0.8]; var xfrmMat = im.getPerspectiveTransform(srcArray, dstArray); im.warpPerspective(xfrmMat, width, height, [255, 255, 255]); - im.save("./examples/tmp/warp-image.png"); + im.save("./tmp/warp-image.png"); console.log('Image saved to ./tmp/warp-image.png'); }); diff --git a/test/examples.js b/test/examples.js index b48a743c..23f0f141 100644 --- a/test/examples.js +++ b/test/examples.js @@ -1,12 +1,17 @@ var test = require('tape') , glob = require('glob') , exec = require('child_process').exec + , path = require('path') module.exports = function(){ glob.sync('./examples/*.js').forEach(function(example){ test("Example: " + example, function(assert){ - exec('node ' + example, function(error, stdout, stderr){ + + var fullName = path.resolve(example) + , examples = path.resolve('./examples') + + exec('node ' + fullName, {cwd: examples}, function(error, stdout, stderr){ assert.error(error) assert.end() }) From 7af5707be13798e12e7768556a1bebb074820a9b Mon Sep 17 00:00:00 2001 From: Peter Braden Date: Wed, 11 Feb 2015 20:24:17 +0100 Subject: [PATCH 69/83] Update Car Detection cascade for example re http://code.opencv.org/issues/2387 --- data/hogcascade_cars_sideview.xml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/data/hogcascade_cars_sideview.xml b/data/hogcascade_cars_sideview.xml index 167705bd..8860c161 100644 --- a/data/hogcascade_cars_sideview.xml +++ b/data/hogcascade_cars_sideview.xml @@ -1,6 +1,6 @@ - + BOOST HOG 24 @@ -835,5 +835,7 @@ 16 8 16 8 24 <_> - 16 8 16 8 28 + 16 8 16 8 28 + + From 2eaf099b35ad8f2cac68ef6e5274d52b89e1eb15 Mon Sep 17 00:00:00 2001 From: Peter Braden Date: Wed, 11 Feb 2015 20:38:39 +0100 Subject: [PATCH 70/83] New Travis keys --- .travis.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index e516cf69..5c752dd0 100755 --- a/.travis.yml +++ b/.travis.yml @@ -9,8 +9,10 @@ compiler: clang env: global: - - secure: v7yz4KwR5+Iv7+oPs54wAK6/fYp7xnEDmbbr2z5F2i8NaG5Qvi4AGwfRuPTLNAeFhpapzL8wk8LI4NfxChUe2S1Rj9ytpW350wtHNcIEBiJXsbfKBeHCZQcZnlx+KofmuP//BRjO3kiVgilOxuLvVbdA9Ob/6ixAdKTHl0yk+NA= - - secure: ehjkxVYyBwL9dZAD1w/D3oEN2lWQebN44CnrftTYw0xVPiYsNeCKV0SpTs/RIlhhiVlQjZRmZbt+My213q32vYdKGEv4TGyyiSfy3BQz+hkXb5vCtxS0WZjfQpxcApYlh9bLh4LzvCcEXe6RrdLSApTXVh9PPiKVGBPtZjLXfZU= + - secure: "kCAwXdfcMv4l4ok5lO89ANbKXXwWQpn5/3qupSbhmX2NDIGUxyXze/cs90u9gF5hcT7ebq27ZJPEtu7pRov8MadfQM9BAd4ZZrHcMHWSkA0Iz+nM+m0Urwach6jkp2Iuwx15L2NHSis7f5PUKJcEv4Gnqs8jrCJzHHS7m7dO0Xo=" + - secure: "lBIk4BhdIkSmJtFUNp93UjDm445i9eF7nKA+oSiLRu+b9i/WeRLiKFI89tehexWeXBlyNhziBN16LrHmx3I86yZfEok9dBMA1JuzYBjrvpjRAflGcqaCFLV3axyyyNQRIh7Q+ziAlg0xg8HL752BpnfXO91g3jfDPjGxcvBb5xQ=" + + before_install: # Fix a problem with apt-get failing later, see http://docs.travis-ci.com/user/installing-dependencies/#Installing-Ubuntu-packages From bd6629de47cf4ca4f4e661f60379dbd8e9ace166 Mon Sep 17 00:00:00 2001 From: Peter Braden Date: Wed, 11 Feb 2015 20:46:15 +0100 Subject: [PATCH 71/83] Appveyor keys --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 6559ec1f..aacd7c5b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,9 +1,9 @@ # environment variables environment: node_pre_gyp_accessKeyId: - secure: hTQMi31kndQOPU0AZVkVXgH7Vc3EjJmvThFwMYhkno4= + secure: 3GHZvq0y83PQ8Qi7FOc5rKoULRQvd2OohhtGqRQLZB4 node_pre_gyp_secretAccessKey: - secure: ZOsWmB5rxfiPgPW5bCuvkK1UUEupssSoHfK5jWcJBJsPuPWQHEWOr1lUteVbx2NV + secure: AiX8Bx+U8LKu5JZHb5CMth5xOHuWawkQW3il0OFWfV4kodPZnC8dLYIqb4XZeF7f # try on unstable version of the server to build node-opencv os: unstable From f485906bc08d966d99bd530460b5aa6ed4e79318 Mon Sep 17 00:00:00 2001 From: Peter Braden Date: Wed, 11 Feb 2015 20:52:56 +0100 Subject: [PATCH 72/83] [publish binary] Lets test this From efc2f6a8818b8ccb05a58e5c7f4edeafa81a2ad0 Mon Sep 17 00:00:00 2001 From: Peter Braden Date: Wed, 11 Feb 2015 21:17:30 +0100 Subject: [PATCH 73/83] Missed a character... [publish binary] --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index aacd7c5b..d508c3d1 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,7 +1,7 @@ # environment variables environment: node_pre_gyp_accessKeyId: - secure: 3GHZvq0y83PQ8Qi7FOc5rKoULRQvd2OohhtGqRQLZB4 + secure: 3GHZvq0y83PQ8Qi7FOc5rKoULRQvd2OohhtGqRQLZB4= node_pre_gyp_secretAccessKey: secure: AiX8Bx+U8LKu5JZHb5CMth5xOHuWawkQW3il0OFWfV4kodPZnC8dLYIqb4XZeF7f From 2c6ec42ffd19b3bda9dab2b9a7ca7470185d3249 Mon Sep 17 00:00:00 2001 From: Peter Braden Date: Wed, 11 Feb 2015 21:24:59 +0100 Subject: [PATCH 74/83] Don't fail the build if package upload fails --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 5c752dd0..51017892 100755 --- a/.travis.yml +++ b/.travis.yml @@ -50,7 +50,7 @@ install: before_script: - echo "Publishing native platform Binary Package? ->" $PUBLISH_BINARY # if publishing, do it - - if [[ $PUBLISH_BINARY == true ]]; then node-pre-gyp package publish; fi; + - if [[ $PUBLISH_BINARY == true ]]; then node-pre-gyp package publish || true ; fi; # cleanup - node-pre-gyp clean - node-gyp clean From efb9bf5356a39d76df556da1fb7d7e613e5371e6 Mon Sep 17 00:00:00 2001 From: Peter Braden Date: Wed, 11 Feb 2015 21:38:49 +0100 Subject: [PATCH 75/83] disable broken example --- examples/car-detection.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/examples/car-detection.js b/examples/car-detection.js index 58c2d61f..df296d62 100644 --- a/examples/car-detection.js +++ b/examples/car-detection.js @@ -1,3 +1,6 @@ +/* For some reason the cascade file is broken on linux :( + + var cv = require('../lib/opencv'); cv.readImage("./files/car1.jpg", function(err, im){ @@ -16,3 +19,4 @@ cv.readImage("./files/car1.jpg", function(err, im){ console.log('Image saved to ./tmp/car-detection.jpg'); }); }); +*/ From 94dcfda3c254747fd6b45ad82eacb9517d690f85 Mon Sep 17 00:00:00 2001 From: Peter Braden Date: Wed, 11 Feb 2015 21:47:31 +0100 Subject: [PATCH 76/83] Bump the version. 3.0.0 --- CHANGELOG.md | 11 +++++++++++ package.json | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d5a7a625..3b6dc892 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,17 @@ # Changelog +### 3.0.0 + +You wait ages for a release, and 2 come along at once... + +This one is awesome. It adds prebuilt binaries, so you don't need +to build opencv for the common platforms. + +Many many thanks to @edgarsilva for awesome work here, and +http://hybridgroup.com/ for hosting the binaries + + ### 2.0.0 - Support for node 0.12 diff --git a/package.json b/package.json index 5f835b84..27ea0338 100755 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "buffers": "0.1.1", "nan": "1.4.3" }, - "version": "2.0.0", + "version": "3.0.0", "devDependencies": { "tape": "^3.0.0", "aws-sdk": "~2.0.21" From e7604cda59328f67b6b4eb5f5966c080680ad190 Mon Sep 17 00:00:00 2001 From: Peter Braden Date: Wed, 11 Feb 2015 21:49:05 +0100 Subject: [PATCH 77/83] missing comma --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 27ea0338..f136a9f8 100755 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "version": "3.0.0", "devDependencies": { "tape": "^3.0.0", - "aws-sdk": "~2.0.21" + "aws-sdk": "~2.0.21", "glob": "^4.0.6", "request": "^2.45.0" }, From bce394f7751b37987173c8772ef2b8c5d4a80d28 Mon Sep 17 00:00:00 2001 From: Max Ehrlich Date: Thu, 12 Feb 2015 14:17:58 -0500 Subject: [PATCH 78/83] Init StereoGC class --- src/init.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/init.cc b/src/init.cc index af7c474c..a107061e 100755 --- a/src/init.cc +++ b/src/init.cc @@ -30,6 +30,7 @@ init(Handle target) { ImgProc::Init(target); StereoBM::Init(target); StereoSGBM::Init(target); + StereoGC::Init(target); #if CV_MAJOR_VERSION >= 2 && CV_MINOR_VERSION >=4 From f60b41ec32e3fb7e140d16ecd37ade8916b817b2 Mon Sep 17 00:00:00 2001 From: Max Ehrlich Date: Fri, 13 Feb 2015 12:05:58 -0500 Subject: [PATCH 79/83] Fixed naming error in reprojectImageTo3d --- src/Calib3D.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Calib3D.cc b/src/Calib3D.cc index 4d1b12cf..8595e7b4 100644 --- a/src/Calib3D.cc +++ b/src/Calib3D.cc @@ -132,7 +132,7 @@ void Calib3D::Init(Handle target) NODE_SET_METHOD(obj, "stereoCalibrate", StereoCalibrate); NODE_SET_METHOD(obj, "stereoRectify", StereoRectify); NODE_SET_METHOD(obj, "computeCorrespondEpilines", ComputeCorrespondEpilines); - NODE_SET_METHOD(obj, "reprojectImageTo3D", ReprojectImageTo3D); + NODE_SET_METHOD(obj, "reprojectImageTo3d", ReprojectImageTo3D); target->Set(NanNew("calib3d"), obj); } From 14fed8c12b833d34b7094d8e54b660f2022ff750 Mon Sep 17 00:00:00 2001 From: Max Ehrlich Date: Fri, 13 Feb 2015 12:11:18 -0500 Subject: [PATCH 80/83] Fixed a bug causing argments to be read incorrectly in stereoRectify --- src/Calib3D.cc | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Calib3D.cc b/src/Calib3D.cc index 8595e7b4..600a788e 100644 --- a/src/Calib3D.cc +++ b/src/Calib3D.cc @@ -464,20 +464,20 @@ NAN_METHOD(Calib3D::StereoRectify) // Arg1, the first distortion coefficients cv::Mat d1 = matFromMatrix(args[1]); - // Arg3, the second camera matrix - cv::Mat K2 = matFromMatrix(args[3]); + // Arg2, the second camera matrix + cv::Mat K2 = matFromMatrix(args[2]); - // Arg4, the second distortion coefficients - cv::Mat d2 = matFromMatrix(args[4]); + // Arg3, the second distortion coefficients + cv::Mat d2 = matFromMatrix(args[3]); - // Arg5, the image size - cv::Size imageSize = sizeFromArray(args[5]); + // Arg4, the image size + cv::Size imageSize = sizeFromArray(args[4]); - // arg6, the intercamera rotation matrix - cv::Mat R = matFromMatrix(args[6]); + // arg5, the intercamera rotation matrix + cv::Mat R = matFromMatrix(args[5]); - // Arg7, the intercamera translation vector - cv::Mat t = matFromMatrix(args[7]); + // Arg6, the intercamera translation vector + cv::Mat t = matFromMatrix(args[6]); // Arg8, flags, skipping for now From 131554274ac8c8f8af816212876f8bd18b811489 Mon Sep 17 00:00:00 2001 From: edgarsilva Date: Tue, 24 Feb 2015 17:51:12 -0600 Subject: [PATCH 81/83] Fix issue with travis-ci pre-compiled binaries using a really old opencv version. --- .travis.yml | 16 ++++++---------- package.json | 2 +- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/.travis.yml b/.travis.yml index 51017892..8cd4a3dd 100755 --- a/.travis.yml +++ b/.travis.yml @@ -9,19 +9,15 @@ compiler: clang env: global: - - secure: "kCAwXdfcMv4l4ok5lO89ANbKXXwWQpn5/3qupSbhmX2NDIGUxyXze/cs90u9gF5hcT7ebq27ZJPEtu7pRov8MadfQM9BAd4ZZrHcMHWSkA0Iz+nM+m0Urwach6jkp2Iuwx15L2NHSis7f5PUKJcEv4Gnqs8jrCJzHHS7m7dO0Xo=" - - secure: "lBIk4BhdIkSmJtFUNp93UjDm445i9eF7nKA+oSiLRu+b9i/WeRLiKFI89tehexWeXBlyNhziBN16LrHmx3I86yZfEok9dBMA1JuzYBjrvpjRAflGcqaCFLV3axyyyNQRIh7Q+ziAlg0xg8HL752BpnfXO91g3jfDPjGxcvBb5xQ=" - - + - secure: "kCAwXdfcMv4l4ok5lO89ANbKXXwWQpn5/3qupSbhmX2NDIGUxyXze/cs90u9gF5hcT7ebq27ZJPEtu7pRov8MadfQM9BAd4ZZrHcMHWSkA0Iz+nM+ + - secure: "lBIk4BhdIkSmJtFUNp93UjDm445i9eF7nKA+oSiLRu+b9i/WeRLiKFI89tehexWeXBlyNhziBN16LrHmx3I86yZfEok9dBMA1JuzYBjrvpjRAflGc before_install: # Fix a problem with apt-get failing later, see http://docs.travis-ci.com/user/installing-dependencies/#Installing-Ubuntu-packages - sudo apt-get update -qq - # - sudo add-apt-repository -y ppa:kubuntu-ppa/backports - # - sudo apt-get update - - sudo apt-get install libcv-dev - - sudo apt-get install libopencv-dev - - sudo apt-get install libhighgui-dev + - sudo add-apt-repository -y ppa:kubuntu-ppa/backports + - sudo apt-get update + - sudo apt-get install --force-yes libcv-dev libcvaux-dev libhighgui-dev libopencv-dev # get commit message - COMMIT_MESSAGE=$(git show -s --format=%B $TRAVIS_COMMIT | tr -d '\n') # put local node-pre-gyp on PATH @@ -50,7 +46,7 @@ install: before_script: - echo "Publishing native platform Binary Package? ->" $PUBLISH_BINARY # if publishing, do it - - if [[ $PUBLISH_BINARY == true ]]; then node-pre-gyp package publish || true ; fi; + - if [[ $PUBLISH_BINARY == true ]]; then node-pre-gyp package publish || true; fi; # cleanup - node-pre-gyp clean - node-gyp clean diff --git a/package.json b/package.json index f136a9f8..00d13d66 100755 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "buffers": "0.1.1", "nan": "1.4.3" }, - "version": "3.0.0", + "version": "3.0.1", "devDependencies": { "tape": "^3.0.0", "aws-sdk": "~2.0.21", From a872bcf9c4d35f245188c8444ddfae10ea2d36ed Mon Sep 17 00:00:00 2001 From: edgarsilva Date: Tue, 24 Feb 2015 18:00:27 -0600 Subject: [PATCH 82/83] Fix incorrect secure keys. --- .travis.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8cd4a3dd..f846ea2e 100755 --- a/.travis.yml +++ b/.travis.yml @@ -9,8 +9,9 @@ compiler: clang env: global: - - secure: "kCAwXdfcMv4l4ok5lO89ANbKXXwWQpn5/3qupSbhmX2NDIGUxyXze/cs90u9gF5hcT7ebq27ZJPEtu7pRov8MadfQM9BAd4ZZrHcMHWSkA0Iz+nM+ - - secure: "lBIk4BhdIkSmJtFUNp93UjDm445i9eF7nKA+oSiLRu+b9i/WeRLiKFI89tehexWeXBlyNhziBN16LrHmx3I86yZfEok9dBMA1JuzYBjrvpjRAflGc + - secure: "kCAwXdfcMv4l4ok5lO89ANbKXXwWQpn5/3qupSbhmX2NDIGUxyXze/cs90u9gF5hcT7ebq27ZJPEtu7pRov8MadfQM9BAd4ZZrHcMHWSkA0Iz+nM+m0Urwach6jkp2Iuwx15L2NHSis7f5PUKJcEv4Gnqs8jrCJzHHS7m7dO0Xo=" + - secure: "lBIk4BhdIkSmJtFUNp93UjDm445i9eF7nKA+oSiLRu+b9i/WeRLiKFI89tehexWeXBlyNhziBN16LrHmx3I86yZfEok9dBMA1JuzYBjrvpjRAflGcqaCFLV3axyyyNQRIh7Q+ziAlg0xg8HL752BpnfXO91g3jfDPjGxcvBb5xQ=" + before_install: # Fix a problem with apt-get failing later, see http://docs.travis-ci.com/user/installing-dependencies/#Installing-Ubuntu-packages From 7acb6ea5cdd445fa0290bf646097117c023cf3b5 Mon Sep 17 00:00:00 2001 From: Max Ehrlich Date: Tue, 17 Mar 2015 10:09:39 -0400 Subject: [PATCH 83/83] Added fillPoly function for drawing polygons --- src/Matrix.cc | 77 ++++++++++++++++++++++++++++++++++++++------------- src/Matrix.h | 1 + 2 files changed, 58 insertions(+), 20 deletions(-) diff --git a/src/Matrix.cc b/src/Matrix.cc index d378a630..149778b9 100755 --- a/src/Matrix.cc +++ b/src/Matrix.cc @@ -38,6 +38,7 @@ Matrix::Init(Handle target) { NODE_SET_PROTOTYPE_METHOD(ctor, "ellipse", Ellipse); NODE_SET_PROTOTYPE_METHOD(ctor, "rectangle", Rectangle); NODE_SET_PROTOTYPE_METHOD(ctor, "line", Line); + NODE_SET_PROTOTYPE_METHOD(ctor, "fillPoly", FillPoly); NODE_SET_PROTOTYPE_METHOD(ctor, "save", Save); NODE_SET_PROTOTYPE_METHOD(ctor, "saveAsync", SaveAsync); NODE_SET_PROTOTYPE_METHOD(ctor, "resize", Resize); @@ -266,7 +267,7 @@ NAN_METHOD(Matrix::Set){ } else { NanThrowTypeError( "Invalid number of arguments" ); } - + NanReturnUndefined(); } @@ -283,9 +284,9 @@ NAN_METHOD(Matrix::Size){ NAN_METHOD(Matrix::Clone){ SETUP_FUNCTION(Matrix) - + Local im_h = NanNew(Matrix::constructor)->GetFunction()->NewInstance(); - + Matrix *m = ObjectWrap::Unwrap(im_h); m->mat = self->mat.clone(); @@ -451,7 +452,7 @@ NAN_METHOD(Matrix::ToBuffer){ Local buf = NanNewBufferHandle(vec.size()); uchar* data = (uchar*) Buffer::Data(buf); memcpy(data, &vec[0], vec.size()); - + v8::Local globalObj = NanGetCurrentContext()->Global(); v8::Local bufferConstructor = v8::Local::Cast(globalObj->Get(NanNew("Buffer"))); v8::Handle constructorArgs[3] = {buf, NanNew((unsigned)vec.size()), NanNew(0)}; @@ -470,21 +471,21 @@ class AsyncToBufferWorker : public NanAsyncWorker { void Execute () { std::vector vec(0); - + //std::vector params(0);//CV_IMWRITE_JPEG_QUALITY 90 cv::imencode(ext, this->matrix->mat, vec, this->params); - + res = vec; } void HandleOKCallback () { NanScope(); - + Local buf = NanNewBufferHandle(res.size()); uchar* data = (uchar*) Buffer::Data(buf); memcpy(data, &res[0], res.size()); - + v8::Local globalObj = NanGetCurrentContext()->Global(); v8::Local bufferConstructor = v8::Local::Cast(globalObj->Get(NanNew("Buffer"))); v8::Handle constructorArgs[3] = {buf, NanNew((unsigned)res.size()), NanNew(0)}; @@ -495,13 +496,13 @@ class AsyncToBufferWorker : public NanAsyncWorker { NanNull() , actualBuffer }; - + TryCatch try_catch; callback->Call(2, argv); if (try_catch.HasCaught()) { FatalException(try_catch); } - + } private: @@ -519,7 +520,7 @@ NAN_METHOD(Matrix::ToBufferAsync){ std::string ext = std::string(".jpg"); std::vector params; - + // See if the options argument is passed if ((args.Length() > 1) && (args[1]->IsObject())) { // Get this options argument @@ -539,14 +540,14 @@ NAN_METHOD(Matrix::ToBufferAsync){ int compression = options->Get(NanNew("pngCompression"))->IntegerValue(); params.push_back(CV_IMWRITE_PNG_COMPRESSION); params.push_back(compression); - } + } } - + NanCallback *callback = new NanCallback(cb.As()); NanAsyncQueueWorker(new AsyncToBufferWorker(callback, self, ext, params)); - + NanReturnUndefined(); } @@ -685,6 +686,42 @@ NAN_METHOD(Matrix::Line) { NanReturnNull(); } +NAN_METHOD(Matrix::FillPoly) { + SETUP_FUNCTION(Matrix) + + if(args[0]->IsArray()) + { + Local polyArray = Local::Cast(args[0]->ToObject()); + + cv::Point **polygons = new cv::Point*[polyArray->Length()]; + int *polySizes = new int[polyArray->Length()]; + for(unsigned int i = 0; i < polyArray->Length(); i++) + { + Local singlePoly = Local::Cast(polyArray->Get(i)->ToObject()); + polygons[i] = new cv::Point[singlePoly->Length()]; + polySizes[i] = singlePoly->Length(); + + for(unsigned int j = 0; j < singlePoly->Length(); j++) + { + Local point = Local::Cast(singlePoly->Get(j)->ToObject()); + polygons[i][j].x = point->Get(0)->IntegerValue(); + polygons[i][j].y = point->Get(1)->IntegerValue(); + } + } + + cv::Scalar color(0, 0, 255); + + if(args[1]->IsArray()) { + Local objColor = args[1]->ToObject(); + color = setColor(objColor); + } + + cv::fillPoly(self->mat, (const cv::Point **)polygons, polySizes, polyArray->Length(), color); + } + + NanReturnNull(); +} + NAN_METHOD(Matrix::Save) { SETUP_FUNCTION(Matrix) @@ -727,7 +764,7 @@ class AsyncSaveWorker : public NanAsyncWorker { NanNull() , NanNew(res) }; - + TryCatch try_catch; callback->Call(2, argv); if (try_catch.HasCaught()) { @@ -752,7 +789,7 @@ NAN_METHOD(Matrix::SaveAsync){ NanAsciiString filename(args[0]); REQ_FUN_ARG(1, cb); - + NanCallback *callback = new NanCallback(cb.As()); NanAsyncQueueWorker(new AsyncSaveWorker(callback, self, *filename)); @@ -1041,7 +1078,7 @@ NAN_METHOD(Matrix::BitwiseXor) { cv::bitwise_xor(src1->mat, src2->mat, self->mat, mask->mat); }else{ cv::bitwise_xor(src1->mat, src2->mat, self->mat); - } + } NanReturnNull(); } @@ -1058,7 +1095,7 @@ NAN_METHOD(Matrix::BitwiseNot) { cv::bitwise_not(self->mat, dst->mat, mask->mat); }else{ cv::bitwise_not(self->mat, dst->mat); - } + } NanReturnNull(); } @@ -1076,7 +1113,7 @@ NAN_METHOD(Matrix::BitwiseAnd) { cv::bitwise_and(src1->mat, src2->mat, self->mat, mask->mat); }else{ cv::bitwise_and(src1->mat, src2->mat, self->mat); - } + } NanReturnNull(); } @@ -1283,7 +1320,7 @@ NAN_METHOD(Matrix::HoughCircles) { equalizeHist(self->mat, gray); - + cv::HoughCircles(gray, circles, CV_HOUGH_GRADIENT, dp, minDist, higherThreshold, accumulatorThreshold, minRadius, maxRadius); v8::Local arr = NanNew(circles.size()); diff --git a/src/Matrix.h b/src/Matrix.h index 7ea1aa40..54619757 100755 --- a/src/Matrix.h +++ b/src/Matrix.h @@ -35,6 +35,7 @@ class Matrix: public node::ObjectWrap { JSFUNC(Rectangle) JSFUNC(Line) JSFUNC(Empty) + JSFUNC(FillPoly) JSFUNC(Save) JSFUNC(SaveAsync)