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 8dfc669..e338449 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 3331e44..083ac6a 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 dc9379f..a8774dc 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 4405141..551560f 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 0000000..b48a743 --- /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 ac5609d..5bb051f 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 5b6d32d..bcf13b8 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 4978953..05312c9 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 a8774dc..ac6c309 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 541ba7b..307c64f 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 551560f..4438fca 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 abe885b..25b0246 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 f108eee..e2d4f87 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 bb1197b..3b99c9e 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 341631f..e56f4cb 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 418809b..36e8831 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 7f62ff3..dbc9f0c 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 f465d23..6326995 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 0cc5fee..185a78b 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 e56f4cb..1a3a558 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 05312c9..9f57b48 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 8060758..babcb83 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 58c2d61..95a5afa 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 b7c5d6a..031b65d 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 43bb0ac..842011e 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 36e8831..2c61ebe 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 25b0246..96ce808 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 2c61ebe..79167d6 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 eae5110..d9cfb7c 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 0000000..256371e --- /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 aa089a6..f5b4168 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 83e0b2e..4acd6c2 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 4405141..b699864 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 0000000..cf1fa63 --- /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 0000000..7b993fc --- /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 0000000..129b06f --- /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 0000000..0a441a8 --- /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 0a441a8..d2ea375 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 4e97c64..4cad417 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 f5b4168..3d16eed 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 4cad417..fbee02c 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 fbee02c..91faa07 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 4405141..7ce4b0a 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 4ed6c43..24f594b 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 ea1ca83..b8a53ab 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 aa089a6..6e56fc9 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 0000000..e8bba46 --- /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 24f594b..6ebdf01 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 b8a53ab..2dc32e5 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 eb8b79a..2486e07 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 240c431..512b524 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 e8bba46..14ecc99 100644 --- a/src/Calib3D.h +++ b/src/Calib3D.h @@ -10,6 +10,8 @@ public: 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 512b524..f8a1fcc 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 14ecc99..e42df5c 100644 --- a/src/Calib3D.h +++ b/src/Calib3D.h @@ -12,6 +12,8 @@ public: 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 f8a1fcc..3519470 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]; + // Make the return value + Local ret = NanNew(); + ret->Set(NanNew("found"), NanNew(found)); - 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) + 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; + ret->Set(NanNew("corners"), cornersArray); - cb->Call(NanGetCurrentContext()->Global(), 2, argv); - - if(try_catch.HasCaught()) { - FatalException(try_catch); - } - - 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 3519470..b031965 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 e42df5c..67bf2c7 100644 --- a/src/Calib3D.h +++ b/src/Calib3D.h @@ -14,6 +14,8 @@ public: 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 b031965..6f078a8 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 8060758..a698e34 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 a698e34..37d61ef 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 6e56fc9..449c088 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 0000000..140b056 --- /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 2486e07..95eef1a 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 7945d93..d0b1ea6 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 140b056..c00393f 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 6f078a8..274844e 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 67bf2c7..ab5669e 100644 --- a/src/Calib3D.h +++ b/src/Calib3D.h @@ -16,6 +16,8 @@ public: 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 d0b1ea6..4291e17 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 c00393f..9689403 100644 --- a/src/ImgProc.h +++ b/src/ImgProc.h @@ -10,6 +10,8 @@ public: 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 e5b3b68..1d9696b 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 4291e17..4c090a6 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 9689403..6d26458 100644 --- a/src/ImgProc.h +++ b/src/ImgProc.h @@ -12,6 +12,8 @@ public: 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 274844e..f223fef 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 4c090a6..d3210fd 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 | 120 +++++++++++++++++++++++++++------------------------- 1 file changed, 63 insertions(+), 57 deletions(-) diff --git a/binding.gyp b/binding.gyp index 3d16eed..e13a62b 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' ], - }, - }, - }, - ], - ['OS=="mac"', { - # cflags on OS X are stupid and have to be defined like this - 'xcode_settings': { - 'OTHER_CFLAGS': [ - "-mmacosx-version-min=10.7", - "-std=c++11", - "-stdlib=libc++", - '= 2.3.1\" )", + "-Wall" ] - , "GCC_ENABLE_CPP_RTTI": "YES" - , "GCC_ENABLE_CPP_EXCEPTIONS": "YES" + }], + [ "OS==\"win\"", { + "cflags": [ + "= 2.4.9\" )", + "-Wall" + ], + "msvs_settings": { + "VCCLCompilerTool": { + "ExceptionHandling": "2", + "DisableSpecificWarnings": [ "4530", "4506", "4244" ], + }, + } + }], + [ # cflags on OS X are stupid and have to be defined like this + "OS==\"mac\"", { + "xcode_settings": { + "OTHER_CFLAGS": [ + "-mmacosx-version-min=10.7", + "-std=c++11", + "-stdlib=libc++", + " 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 d9cfb7c..6455591 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 6455591..ff7cf32 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 e9de264..18a581c 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 ff7cf32..1508190 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 d26d474..a34295e 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 e9de264..b066529 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 e13a62b..ef75193 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 f223fef..62b56ca 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 ab5669e..1f18894 100644 --- a/src/Calib3D.h +++ b/src/Calib3D.h @@ -18,6 +18,8 @@ public: 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 62b56ca..127cc67 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]); + std::vector > objectPoints = points3fFromArrayOfArrays(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 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]); + std::vector > objectPoints = points3fFromArrayOfArrays(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 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 = matFromMatrix(args[4]); + d1 = matFromMatrix(args[5]); - k1 = mk1->mat; - d1 = md1->mat; - - 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 127cc67..67d9927 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 1f18894..cf1d190 100644 --- a/src/Calib3D.h +++ b/src/Calib3D.h @@ -20,6 +20,8 @@ public: 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 67d9927..8d6a43f 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 cf1d190..9d5afbd 100644 --- a/src/Calib3D.h +++ b/src/Calib3D.h @@ -22,6 +22,8 @@ public: 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 8d6a43f..e73a62a 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 e73a62a..ebc4f80 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 9d5afbd..4f06505 100644 --- a/src/Calib3D.h +++ b/src/Calib3D.h @@ -24,6 +24,8 @@ public: 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 ebc4f80..4d1b12c 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 256371e..6559ec1 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 cf1fa63..98b80c0 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 7b993fc..14026a1 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 6559ec1..2f463a0 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 2f463a0..0fdf15f 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 0fdf15f..6559ec1 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 449c088..846b6b0 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 0000000..7149066 --- /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 95eef1a..8cf0cec 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 4cab060..454fb6a 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 7149066..c144989 100644 --- a/src/Stereo.h +++ b/src/Stereo.h @@ -16,4 +16,28 @@ public: 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 8cf0cec..af7c474 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 6559ec1..257ed74 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 257ed74..6559ec1 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 454fb6a..54da7af 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 c144989..569a6d6 100644 --- a/src/Stereo.h +++ b/src/Stereo.h @@ -40,4 +40,19 @@ public: 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 129b06f..bcacd40 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 84fab84..0000000 --- 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 d2f8871..ac8a35f 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 d2f8871..ac8a35f 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 40b9dc8..d1f5382 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 d1f5382..1f0b9d9 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 eae5110..52ec0ef 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 86c9edb..6247af4 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 6247af4..d5a7a62 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 7ce4b0a..0401826 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 95a5afa..58c2d61 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 031b65d..b7c5d6a 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 842011e..43bb0ac 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 dbc9f0c..7f62ff3 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 6326995..f465d23 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 e2d4f87..f108eee 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 185a78b..0cc5fee 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 1a3a558..341631f 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 d3212b2..737e834 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 bcf13b8..8549bf9 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 b48a743..23f0f14 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 167705b..8860c16 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 e516cf6..5c752dd 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 6559ec1..aacd7c5 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 aacd7c5..d508c3d 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 5c752dd..5101789 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 58c2d61..df296d6 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 d5a7a62..3b6dc89 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 5f835b8..27ea033 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 27ea033..f136a9f 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 af7c474..a107061 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 4d1b12c..8595e7b 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 8595e7b..600a788 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 5101789..8cd4a3d 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 f136a9f..00d13d6 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 8cd4a3d..f846ea2 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 d378a63..149778b 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 7ea1aa4..5461975 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)