node-opencv/src/Stereo.cc
Keegan Brown ec09e0bdde Swapped out all "handle" for "local"
Now building and passing tests locally in node v0.10.40 v0.12.7 and
v4.1.1. Other modules would not build at node lower than v0.10, so I
stopped there.
2015-10-05 14:33:12 -05:00

315 lines
10 KiB
C++

#include "Stereo.h"
#include "Matrix.h"
#include <opencv2/legacy/legacy.hpp>
// Block matching
Nan::Persistent<FunctionTemplate> StereoBM::constructor;
void StereoBM::Init(Local<Object> target) {
Nan::HandleScope scope;
Local<FunctionTemplate> ctor = Nan::New<FunctionTemplate>(StereoBM::New);
constructor.Reset(ctor);
ctor->InstanceTemplate()->SetInternalFieldCount(1);
ctor->SetClassName(Nan::New("StereoBM").ToLocalChecked());
Nan::SetPrototypeMethod(ctor, "compute", Compute);
ctor->Set(Nan::New<String>("BASIC_PRESET").ToLocalChecked(), Nan::New<Integer>((int)cv::StereoBM::BASIC_PRESET));
ctor->Set(Nan::New<String>("FISH_EYE_PRESET").ToLocalChecked(), Nan::New<Integer>((int)cv::StereoBM::FISH_EYE_PRESET));
ctor->Set(Nan::New<String>("NARROW_PRESET").ToLocalChecked(), Nan::New<Integer>((int)cv::StereoBM::NARROW_PRESET));
target->Set(Nan::New("StereoBM").ToLocalChecked(), ctor->GetFunction());
}
NAN_METHOD(StereoBM::New) {
Nan::HandleScope scope;
if (info.This()->InternalFieldCount() == 0) {
Nan::ThrowTypeError("Cannot instantiate without new");
}
StereoBM *stereo;
if (info.Length() == 0) {
stereo = new StereoBM();
} else if (info.Length() == 1) {
// preset
stereo = new StereoBM(info[0]->IntegerValue());
} else if (info.Length() == 2) {
// preset, disparity search range
stereo = new StereoBM(info[0]->IntegerValue(), info[1]->IntegerValue());
} else {
stereo = new StereoBM(info[0]->IntegerValue(), info[1]->IntegerValue(),
// preset, disparity search range, sum of absolute differences window size
info[2]->IntegerValue());
}
stereo->Wrap(info.Holder());
info.GetReturnValue().Set(info.Holder());
}
StereoBM::StereoBM(int preset, int ndisparities, int SADWindowSize) :
Nan::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 = Nan::ObjectWrap::Unwrap<Matrix>(info[0]->ToObject());
cv::Mat left = m0->mat;
// Arg 1, the 'right' image
Matrix* m1 = Nan::ObjectWrap::Unwrap<Matrix>(info[1]->ToObject());
cv::Mat right = m1->mat;
// Optional 3rd arg, the disparty depth
int type = CV_16S;
if (info.Length() > 2) {
type = info[2]->IntegerValue();
}
// Compute stereo using the block matching algorithm
cv::Mat disparity;
self->stereo(left, right, disparity, type);
// Wrap the returned disparity map
Local < Object > disparityWrap =
Nan::New(Matrix::constructor)->GetFunction()->NewInstance();
Matrix *disp = Nan::ObjectWrap::Unwrap<Matrix>(disparityWrap);
disp->mat = disparity;
info.GetReturnValue().Set(disparityWrap);
} catch (cv::Exception &e) {
const char *err_msg = e.what();
Nan::ThrowError(err_msg);
return;
}
}
// Semi-Global Block matching
Nan::Persistent<FunctionTemplate> StereoSGBM::constructor;
void StereoSGBM::Init(Local<Object> target) {
Nan::HandleScope scope;
Local<FunctionTemplate> ctor = Nan::New<FunctionTemplate>(StereoSGBM::New);
constructor.Reset(ctor);
ctor->InstanceTemplate()->SetInternalFieldCount(1);
ctor->SetClassName(Nan::New("StereoSGBM").ToLocalChecked());
Nan::SetPrototypeMethod(ctor, "compute", Compute);
target->Set(Nan::New("StereoSGBM").ToLocalChecked(), ctor->GetFunction());
}
NAN_METHOD(StereoSGBM::New) {
Nan::HandleScope scope;
if (info.This()->InternalFieldCount() == 0) {
Nan::ThrowTypeError("Cannot instantiate without new");
}
StereoSGBM *stereo;
if (info.Length() == 0) {
stereo = new StereoSGBM();
} else {
// If passing arguments, must pass the first 3 at least
if (info.Length() >= 3) {
switch (info.Length()) {
case 3:
stereo = new StereoSGBM(info[0]->IntegerValue(), info[1]->IntegerValue(),
info[2]->IntegerValue());
break;
case 4:
stereo = new StereoSGBM(info[0]->IntegerValue(), info[1]->IntegerValue(),
info[2]->IntegerValue(), info[3]->IntegerValue());
break;
case 5:
stereo = new StereoSGBM(info[0]->IntegerValue(), info[1]->IntegerValue(),
info[2]->IntegerValue(), info[3]->IntegerValue(), info[4]->IntegerValue());
break;
case 6:
stereo = new StereoSGBM(info[0]->IntegerValue(), info[1]->IntegerValue(),
info[2]->IntegerValue(), info[3]->IntegerValue(), info[4]->IntegerValue(),
info[5]->IntegerValue());
break;
case 7:
stereo = new StereoSGBM(info[0]->IntegerValue(), info[1]->IntegerValue(),
info[2]->IntegerValue(), info[3]->IntegerValue(), info[4]->IntegerValue(),
info[5]->IntegerValue(), info[6]->IntegerValue());
break;
case 8:
stereo = new StereoSGBM(info[0]->IntegerValue(), info[1]->IntegerValue(),
info[2]->IntegerValue(), info[3]->IntegerValue(), info[4]->IntegerValue(),
info[5]->IntegerValue(), info[6]->IntegerValue(), info[7]->IntegerValue());
break;
case 9:
stereo = new StereoSGBM(info[0]->IntegerValue(), info[1]->IntegerValue(),
info[2]->IntegerValue(), info[3]->IntegerValue(), info[4]->IntegerValue(),
info[5]->IntegerValue(), info[6]->IntegerValue(), info[7]->IntegerValue(),
info[8]->IntegerValue());
break;
case 10:
stereo = new StereoSGBM(info[0]->IntegerValue(), info[1]->IntegerValue(),
info[2]->IntegerValue(), info[3]->IntegerValue(), info[4]->IntegerValue(),
info[5]->IntegerValue(), info[6]->IntegerValue(), info[7]->IntegerValue(),
info[8]->IntegerValue(), info[9]->IntegerValue());
break;
default:
stereo = new StereoSGBM(info[0]->IntegerValue(), info[1]->IntegerValue(),
info[2]->IntegerValue(), info[3]->IntegerValue(), info[4]->IntegerValue(),
info[5]->IntegerValue(), info[6]->IntegerValue(), info[7]->IntegerValue(),
info[8]->IntegerValue(), info[9]->IntegerValue(), info[10]->ToBoolean()->Value());
break;
}
} else {
Nan::ThrowError("If overriding default settings, must pass minDisparity, numDisparities, and SADWindowSize");
return;
}
}
stereo->Wrap(info.Holder());
info.GetReturnValue().Set(info.Holder());
}
StereoSGBM::StereoSGBM() :
Nan::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) :
Nan::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 = Nan::ObjectWrap::Unwrap<Matrix>(info[0]->ToObject());
cv::Mat left = m0->mat;
// Arg 1, the 'right' image
Matrix* m1 = Nan::ObjectWrap::Unwrap<Matrix>(info[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 < Object > disparityWrap =
Nan::New(Matrix::constructor)->GetFunction()->NewInstance();
Matrix *disp = Nan::ObjectWrap::Unwrap<Matrix>(disparityWrap);
disp->mat = disparity;
info.GetReturnValue().Set(disparityWrap);
} catch (cv::Exception &e) {
const char *err_msg = e.what();
Nan::ThrowError(err_msg);
return;
}
}
// Graph cut
Nan::Persistent<FunctionTemplate> StereoGC::constructor;
void StereoGC::Init(Local<Object> target) {
Nan::HandleScope scope;
Local<FunctionTemplate> ctor = Nan::New<FunctionTemplate>(StereoGC::New);
constructor.Reset(ctor);
ctor->InstanceTemplate()->SetInternalFieldCount(1);
ctor->SetClassName(Nan::New("StereoGC").ToLocalChecked());
Nan::SetPrototypeMethod(ctor, "compute", Compute);
target->Set(Nan::New("StereoGC").ToLocalChecked(), ctor->GetFunction());
}
NAN_METHOD(StereoGC::New) {
Nan::HandleScope scope;
if (info.This()->InternalFieldCount() == 0)
Nan::ThrowTypeError("Cannot instantiate without new");
StereoGC *stereo;
if (info.Length() == 0) {
stereo = new StereoGC();
} else if (info.Length() == 1) {
// numberOfDisparities
stereo = new StereoGC(info[0]->IntegerValue());
} else {
// max iterations
stereo = new StereoGC(info[0]->IntegerValue(), info[1]->IntegerValue());
}
stereo->Wrap(info.Holder());
info.GetReturnValue().Set(info.Holder());
}
StereoGC::StereoGC(int numberOfDisparities, int maxIters) :
Nan::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 = Nan::ObjectWrap::Unwrap<Matrix>(info[0]->ToObject());
cv::Mat left = m0->mat;
// Arg 1, the 'right' image
Matrix* m1 = Nan::ObjectWrap::Unwrap<Matrix>(info[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 < Object > disparityWrap =
Nan::New(Matrix::constructor)->GetFunction()->NewInstance();
Matrix *disp = Nan::ObjectWrap::Unwrap<Matrix>(disparityWrap);
disp->mat = disparity;
info.GetReturnValue().Set(disparityWrap);
} catch (cv::Exception &e) {
const char *err_msg = e.what();
Nan::ThrowError(err_msg);
return;
}
}