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);