From 97715a8048aa8be714451d578cc29cbf0190eff6 Mon Sep 17 00:00:00 2001 From: Max Ehrlich Date: Mon, 19 Jan 2015 15:15:05 -0500 Subject: [PATCH 1/7] 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 2/7] 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 3/7] 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 4/7] 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 5/7] 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 6/7] 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 7/7] 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);