From 487ac8a13705d2877cbe1c2659d8399621d39eec Mon Sep 17 00:00:00 2001 From: Max Ehrlich Date: Fri, 6 Feb 2015 11:06:58 -0500 Subject: [PATCH] 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