From dbf2df0ef8114f8fce2fb45f1d9e7f74a9c8c35a Mon Sep 17 00:00:00 2001 From: David Starke Date: Fri, 22 Dec 2017 15:29:49 -0800 Subject: [PATCH] Track external memory usage for matrices --- src/BackgroundSubtractor.cc | 18 ++---- src/FaceRecognizer.cc | 4 +- src/ImgProc.cc | 25 ++------- src/LDAWrap.cc | 8 +-- src/Matrix.cc | 106 ++++++++++++++++++++---------------- src/Matrix.h | 2 + src/OpenCV.cc | 29 +++------- src/Stereo.cc | 15 +---- src/VideoCaptureWrap.cc | 5 +- 9 files changed, 85 insertions(+), 127 deletions(-) diff --git a/src/BackgroundSubtractor.cc b/src/BackgroundSubtractor.cc index cf952364..0afa37ae 100644 --- a/src/BackgroundSubtractor.cc +++ b/src/BackgroundSubtractor.cc @@ -255,10 +255,6 @@ NAN_METHOD(BackgroundSubtractorWrap::ApplyMOG) { try { - Local fgMask = - Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked(); - Matrix *img = Nan::ObjectWrap::Unwrap(fgMask); - cv::Mat mat; if (Buffer::HasInstance(info[0])) { uint8_t *buf = (uint8_t *) Buffer::Data(info[0]->ToObject()); @@ -287,7 +283,7 @@ NAN_METHOD(BackgroundSubtractorWrap::ApplyMOG) { #endif } - img->mat = _fgMask; + Local fgMask = Matrix::CreateWrappedFromMat(_fgMask); mat.release(); argv[0] = Nan::Null(); @@ -344,9 +340,7 @@ class AsyncBackgroundSubtractorWorker: public Nan::AsyncWorker { void HandleOKCallback() { Nan::HandleScope scope; - Local im_to_return= Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked(); - Matrix *imgout = Nan::ObjectWrap::Unwrap(im_to_return); - imgout->mat = _fgMask; + Local im_to_return = Matrix::CreateWrappedFromMat(_fgMask); Local argv[] = { Nan::Null() @@ -372,7 +366,6 @@ NAN_METHOD(BackgroundSubtractorWrap::Apply) { SETUP_FUNCTION(BackgroundSubtractorWrap); int callback_arg = -1; int numargs = info.Length(); - int success = 1; Local cb; @@ -407,10 +400,7 @@ NAN_METHOD(BackgroundSubtractorWrap::Apply) { } else { //synchronous - return the image try { - Local fgMask = - Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked(); - Matrix *img = Nan::ObjectWrap::Unwrap(fgMask); - + Local fgMask; cv::Mat mat; if (Buffer::HasInstance(info[0])) { uint8_t *buf = (uint8_t *) Buffer::Data(info[0]->ToObject()); @@ -436,7 +426,7 @@ NAN_METHOD(BackgroundSubtractorWrap::Apply) { #else self->subtractor->operator()(mat, _fgMask); #endif - img->mat = _fgMask; + fgMask = Matrix::CreateWrappedFromMat(_fgMask); } mat.release(); diff --git a/src/FaceRecognizer.cc b/src/FaceRecognizer.cc index 47b55838..e5518df1 100644 --- a/src/FaceRecognizer.cc +++ b/src/FaceRecognizer.cc @@ -448,9 +448,7 @@ NAN_METHOD(FaceRecognizerWrap::GetMat) { m = self->rec->getMat(key); #endif - Local im = Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked(); - Matrix *img = Nan::ObjectWrap::Unwrap(im); - img->mat = m; + Local im = Matrix::CreateWrappedFromMat(m); info.GetReturnValue().Set(im); } diff --git a/src/ImgProc.cc b/src/ImgProc.cc index 4dc4efb3..9e77444f 100644 --- a/src/ImgProc.cc +++ b/src/ImgProc.cc @@ -36,9 +36,7 @@ NAN_METHOD(ImgProc::DistanceTransform) { cv::distanceTransform(inputImage, outputImage, distType, 0); // Wrap the output image - Local outMatrixWrap = Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked(); - Matrix *outMatrix = Nan::ObjectWrap::Unwrap(outMatrixWrap); - outMatrix->mat = outputImage; + Local outMatrixWrap = Matrix::CreateWrappedFromMat(outputImage); // Return the output image info.GetReturnValue().Set(outMatrixWrap); @@ -75,9 +73,7 @@ NAN_METHOD(ImgProc::Undistort) { cv::undistort(inputImage, outputImage, K, dist); // Wrap the output image - Local outMatrixWrap = Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked(); - Matrix *outMatrix = Nan::ObjectWrap::Unwrap(outMatrixWrap); - outMatrix->mat = outputImage; + Local outMatrixWrap = Matrix::CreateWrappedFromMat(outputImage); // Return the output image info.GetReturnValue().Set(outMatrixWrap); @@ -128,13 +124,8 @@ NAN_METHOD(ImgProc::InitUndistortRectifyMap) { cv::initUndistortRectifyMap(K, dist, R, newK, imageSize, m1type, map1, map2); // Wrap the output maps - Local map1Wrap = Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked(); - Matrix *map1Matrix = Nan::ObjectWrap::Unwrap(map1Wrap); - map1Matrix->mat = map1; - - Local map2Wrap = Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked(); - Matrix *map2Matrix = Nan::ObjectWrap::Unwrap(map2Wrap); - map2Matrix->mat = map2; + Local map1Wrap = Matrix::CreateWrappedFromMat(map1); + Local map2Wrap = Matrix::CreateWrappedFromMat(map2); // Make a return object with the two maps Local ret = Nan::New(); @@ -181,9 +172,7 @@ NAN_METHOD(ImgProc::Remap) { cv::remap(inputImage, outputImage, map1, map2, interpolation); // Wrap the output image - Local outMatrixWrap = Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked(); - Matrix *outMatrix = Nan::ObjectWrap::Unwrap(outMatrixWrap); - outMatrix->mat = outputImage; + Local outMatrixWrap = Matrix::CreateWrappedFromMat(outputImage); // Return the image info.GetReturnValue().Set(outMatrixWrap); @@ -223,9 +212,7 @@ NAN_METHOD(ImgProc::GetStructuringElement) { cv::Mat mat = cv::getStructuringElement(shape, ksize); // Wrap the output image - Local outMatrixWrap = Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked(); - Matrix *outMatrix = ObjectWrap::Unwrap(outMatrixWrap); - outMatrix->mat = mat; + Local outMatrixWrap = Matrix::CreateWrappedFromMat(mat); // Return the image info.GetReturnValue().Set(outMatrixWrap); diff --git a/src/LDAWrap.cc b/src/LDAWrap.cc index 30867c8d..0dd2d6c5 100644 --- a/src/LDAWrap.cc +++ b/src/LDAWrap.cc @@ -66,9 +66,7 @@ NAN_METHOD(LDAWrap::SubspaceProject) { cv::Mat m = cv::subspaceProject(w->mat, mean->mat, src->mat); - Local im = Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked(); - Matrix *img = Nan::ObjectWrap::Unwrap(im); - img->mat = m; + Local im = Matrix::CreateWrappedFromMat(m); info.GetReturnValue().Set(im); } @@ -92,9 +90,7 @@ NAN_METHOD(LDAWrap::SubspaceReconstruct) { cv::Mat m = cv::subspaceReconstruct(w->mat, mean->mat, src->mat); - Local im = Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked(); - Matrix *img = Nan::ObjectWrap::Unwrap(im); - img->mat = m; + Local im = Matrix::CreateWrappedFromMat(m); info.GetReturnValue().Set(im); } diff --git a/src/Matrix.cc b/src/Matrix.cc index 01b4443d..d3a24e59 100755 --- a/src/Matrix.cc +++ b/src/Matrix.cc @@ -161,6 +161,16 @@ NAN_METHOD(Matrix::New) { info.GetReturnValue().Set(info.Holder()); } +//convenience factory method for creating a wrapped Matrix from a cv::Mat and tracking external memory correctly +Local Matrix::CreateWrappedFromMat(cv::Mat mat){ + Local < Object > result = + Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked(); + Matrix *m = Nan::ObjectWrap::Unwrap(result); + m->mat = mat; + Nan::AdjustExternalMemory(m->mat.rows * m->mat.cols * m->mat.elemSize()); + return result; +} + Matrix::Matrix() : node_opencv::Matrix() { mat = cv::Mat(); @@ -169,20 +179,24 @@ Matrix::Matrix() : Matrix::Matrix(int rows, int cols) : node_opencv::Matrix() { mat = cv::Mat(rows, cols, CV_32FC3); + Nan::AdjustExternalMemory(mat.rows * mat.cols * mat.elemSize()); } Matrix::Matrix(int rows, int cols, int type) : node_opencv::Matrix() { mat = cv::Mat(rows, cols, type); + Nan::AdjustExternalMemory(mat.rows * mat.cols * mat.elemSize()); } Matrix::Matrix(cv::Mat m, cv::Rect roi) : node_opencv::Matrix() { mat = cv::Mat(m, roi); + Nan::AdjustExternalMemory(mat.rows * mat.cols * mat.elemSize()); } Matrix::Matrix(int rows, int cols, int type, Local scalarObj) { mat = cv::Mat(rows, cols, type); + Nan::AdjustExternalMemory(mat.rows * mat.cols * mat.elemSize()); if (mat.channels() == 3) { mat.setTo(cv::Scalar(scalarObj->Get(0)->IntegerValue(), scalarObj->Get(1)->IntegerValue(), @@ -197,6 +211,11 @@ Matrix::Matrix(int rows, int cols, int type, Local scalarObj) { } } +Matrix::~Matrix(){ + int size = mat.rows * mat.cols * mat.elemSize(); + Nan::AdjustExternalMemory(-1 * size); +} + NAN_METHOD(Matrix::Empty) { SETUP_FUNCTION(Matrix) info.GetReturnValue().Set(Nan::New(self->mat.empty())); @@ -549,11 +568,7 @@ NAN_METHOD(Matrix::Type) { NAN_METHOD(Matrix::Clone) { SETUP_FUNCTION(Matrix) - Local < Object > im_h = - Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked(); - - Matrix *m = Nan::ObjectWrap::Unwrap(im_h); - m->mat = self->mat.clone(); + Local im_h = Matrix::CreateWrappedFromMat(self->mat.clone()); info.GetReturnValue().Set(im_h); } @@ -571,10 +586,7 @@ NAN_METHOD(Matrix::Crop) { cv::Rect roi(x, y, width, height); - Local < Object > im_h = - Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked(); - Matrix *m = Nan::ObjectWrap::Unwrap(im_h); - m->mat = self->mat(roi); + Local < Object > im_h = Matrix::CreateWrappedFromMat(self->mat(roi)); info.GetReturnValue().Set(im_h); } else { @@ -1115,11 +1127,8 @@ NAN_METHOD(Matrix::Zeros) { int h = info[1]->Uint32Value(); int type = (info.Length() > 2) ? info[2]->IntegerValue() : CV_64FC1; - Local im_h = Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked(); - Matrix *img = Nan::ObjectWrap::Unwrap(im_h); cv::Mat mat = cv::Mat::zeros(w, h, type); - - img->mat = mat; + Local im_h = Matrix::CreateWrappedFromMat(mat); info.GetReturnValue().Set(im_h); } @@ -1130,11 +1139,9 @@ NAN_METHOD(Matrix::Ones) { int h = info[1]->Uint32Value(); int type = (info.Length() > 2) ? info[2]->IntegerValue() : CV_64FC1; - Local im_h = Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked(); - Matrix *img = Nan::ObjectWrap::Unwrap(im_h); cv::Mat mat = cv::Mat::ones(w, h, type); + Local im_h = Matrix::CreateWrappedFromMat(mat); - img->mat = mat; info.GetReturnValue().Set(im_h); } @@ -1145,11 +1152,9 @@ NAN_METHOD(Matrix::Eye) { int h = info[1]->Uint32Value(); int type = (info.Length() > 2) ? info[2]->IntegerValue() : CV_64FC1; - Local im_h = Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked(); - Matrix *img = Nan::ObjectWrap::Unwrap(im_h); cv::Mat mat = cv::Mat::eye(w, h, type); + Local im_h = Matrix::CreateWrappedFromMat(mat); - img->mat = mat; info.GetReturnValue().Set(im_h); } @@ -1161,7 +1166,10 @@ NAN_METHOD(Matrix::ConvertGrayscale) { Nan::ThrowError("Image is no 3-channel"); } + int oldSize = self->mat.rows * self->mat.cols * self->mat.elemSize(); cv::cvtColor(self->mat, self->mat, CV_BGR2GRAY); + int newSize = self->mat.rows * self->mat.cols * self->mat.elemSize(); + Nan::AdjustExternalMemory(newSize - oldSize); info.GetReturnValue().Set(Nan::Null()); } @@ -1292,6 +1300,7 @@ NAN_METHOD(Matrix::Sobel) { Matrix *result = Nan::ObjectWrap::Unwrap(result_to_return); cv::Sobel(self->mat, result->mat, ddepth, xorder, yorder, ksize, scale, delta, borderType); + Nan::AdjustExternalMemory(result->mat.rows * result->mat.cols * result->mat.elemSize()); info.GetReturnValue().Set(result_to_return); } @@ -1305,6 +1314,7 @@ NAN_METHOD(Matrix::Copy) { Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked(); Matrix *img = Nan::ObjectWrap::Unwrap(img_to_return); self->mat.copyTo(img->mat); + Nan::AdjustExternalMemory(img->mat.rows * img->mat.cols * img->mat.elemSize()); info.GetReturnValue().Set(img_to_return); } @@ -1324,6 +1334,7 @@ NAN_METHOD(Matrix::Flip) { Local img_to_return = Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked(); Matrix *img = Nan::ObjectWrap::Unwrap(img_to_return); cv::flip(self->mat, img->mat, flipCode); + Nan::AdjustExternalMemory(img->mat.rows * img->mat.cols * img->mat.elemSize()); info.GetReturnValue().Set(img_to_return); } @@ -1338,8 +1349,6 @@ NAN_METHOD(Matrix::ROI) { } // Although it's an image to return, it is in fact a pointer to ROI of parent matrix - Local img_to_return = Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked(); - Matrix *img = Nan::ObjectWrap::Unwrap(img_to_return); int x = info[0]->IntegerValue(); int y = info[1]->IntegerValue(); @@ -1347,7 +1356,8 @@ NAN_METHOD(Matrix::ROI) { int h = info[3]->IntegerValue(); cv::Mat roi(self->mat, cv::Rect(x,y,w,h)); - img->mat = roi; + // Although it's an image to return, it is in fact a pointer to ROI of parent matrix + Local img_to_return = Matrix::CreateWrappedFromMat(roi); info.GetReturnValue().Set(img_to_return); } @@ -1387,6 +1397,7 @@ NAN_METHOD(Matrix::Dct) { Local out = Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked(); Matrix *m_out = Nan::ObjectWrap::Unwrap(out); m_out->mat.create(cols, rows, CV_32F); + Nan::AdjustExternalMemory(m_out->mat.rows * m_out->mat.cols * m_out->mat.elemSize()); cv::dct(self->mat, m_out->mat); @@ -1403,6 +1414,7 @@ NAN_METHOD(Matrix::Idct) { Local out = Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked(); Matrix *m_out = Nan::ObjectWrap::Unwrap(out); m_out->mat.create(cols, rows, CV_32F); + Nan::AdjustExternalMemory(m_out->mat.rows * m_out->mat.cols * m_out->mat.elemSize()); cv::idct(self->mat, m_out->mat); @@ -1442,6 +1454,7 @@ NAN_METHOD(Matrix::Add) { Local out = Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked(); Matrix *m_out = Nan::ObjectWrap::Unwrap(out); m_out->mat.create(cols, rows, self->mat.type()); + Nan::AdjustExternalMemory(m_out->mat.rows * m_out->mat.cols * m_out->mat.elemSize()); try { cv::add(self->mat, src1->mat, m_out->mat); @@ -1937,9 +1950,7 @@ class ResizeASyncWorker: public Nan::AsyncWorker { if (success){ try{ - Local im_to_return= Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked(); - Matrix *img = Nan::ObjectWrap::Unwrap(im_to_return); - img->mat = dest->mat; + Local im_to_return = Matrix::CreateWrappedFromMat(dest->mat); delete dest; dest = NULL; @@ -2128,12 +2139,8 @@ NAN_METHOD(Matrix::GetRotationMatrix2D) { int y = Nan::To(info[2]).FromJust(); double scale = Nan::To(info[3]).FromMaybe(1.0); - Local img_to_return = - Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked(); - Matrix *img = Nan::ObjectWrap::Unwrap(img_to_return); - cv::Point center = cv::Point(x,y); - img->mat = getRotationMatrix2D(center, angle, scale); + Local img_to_return = Matrix::CreateWrappedFromMat(getRotationMatrix2D(center, angle, scale)); info.GetReturnValue().Set(img_to_return); } @@ -2298,6 +2305,7 @@ NAN_METHOD(Matrix::Threshold) { self->mat.copyTo(img->mat); cv::threshold(self->mat, img->mat, threshold, maxVal, typ); + Nan::AdjustExternalMemory(img->mat.rows * img->mat.cols * img->mat.elemSize()); info.GetReturnValue().Set(img_to_return); } @@ -2318,6 +2326,7 @@ NAN_METHOD(Matrix::AdaptiveThreshold) { cv::adaptiveThreshold(self->mat, img->mat, maxVal, adaptiveMethod, thresholdType, blockSize, C); + Nan::AdjustExternalMemory(img->mat.rows * img->mat.cols * img->mat.elemSize()); info.GetReturnValue().Set(img_to_return); } @@ -2333,6 +2342,8 @@ NAN_METHOD(Matrix::MeanStdDev) { Matrix *m_stddev = Nan::ObjectWrap::Unwrap(stddev); cv::meanStdDev(self->mat, m_mean->mat, m_stddev->mat); + Nan::AdjustExternalMemory(m_mean->mat.rows * m_mean->mat.cols * m_mean->mat.elemSize()); + Nan::AdjustExternalMemory(m_stddev->mat.rows * m_stddev->mat.cols * m_stddev->mat.elemSize()); Local data = Nan::New(); data->Set(Nan::New("mean").ToLocalChecked(), mean); @@ -2465,7 +2476,12 @@ NAN_METHOD(Matrix::CvtColor) { Nan::ThrowTypeError("Conversion code is unsupported"); } + int oldSize = self->mat.rows * self->mat.cols * self->mat.elemSize(); cv::cvtColor(self->mat, self->mat, iTransform); + int newSize = self->mat.rows * self->mat.cols * self->mat.elemSize(); + if(oldSize != newSize){ + Nan::AdjustExternalMemory(newSize - oldSize); + } return; } @@ -2489,10 +2505,7 @@ NAN_METHOD(Matrix::Split) { size = channels.size(); v8::Local arrChannels = Nan::New(size); for (unsigned int i = 0; i < size; i++) { - Local matObject = - Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked(); - Matrix * m = Nan::ObjectWrap::Unwrap(matObject); - m->mat = channels[i]; + Local matObject = Matrix::CreateWrappedFromMat(channels[i]); arrChannels->Set(i, matObject); } @@ -2508,6 +2521,7 @@ NAN_METHOD(Matrix::Merge) { if (!info[0]->IsArray()) { Nan::ThrowTypeError("The argument must be an array"); } + int oldSize = self->mat.rows * self->mat.cols * self->mat.elemSize(); v8::Local jsChannels = v8::Local::Cast(info[0]); unsigned int L = jsChannels->Length(); @@ -2517,6 +2531,8 @@ NAN_METHOD(Matrix::Merge) { vChannels[i] = matObject->mat; } cv::merge(vChannels, self->mat); + int newSize = self->mat.rows * self->mat.cols * self->mat.elemSize(); + Nan::AdjustExternalMemory(newSize - oldSize); return; } @@ -2675,6 +2691,7 @@ NAN_METHOD(Matrix::MatchTemplateByMatrix) { int cols = self->mat.cols - templ->mat.cols + 1; int rows = self->mat.rows - templ->mat.rows + 1; m_out->mat.create(cols, rows, CV_32FC1); + Nan::AdjustExternalMemory(m_out->mat.rows * m_out->mat.cols * m_out->mat.elemSize()); /* TM_SQDIFF =0 @@ -2709,6 +2726,7 @@ NAN_METHOD(Matrix::MatchTemplate) { int cols = self->mat.cols - templ.cols + 1; int rows = self->mat.rows - templ.rows + 1; m_out->mat.create(cols, rows, CV_32FC1); + Nan::AdjustExternalMemory(m_out->mat.rows * m_out->mat.cols * m_out->mat.elemSize()); /* TM_SQDIFF =0 @@ -2862,9 +2880,7 @@ NAN_METHOD(Matrix::GetPerspectiveTransform) { tgt_corners[i] = cvPoint(tgtArray->Get(i*2)->IntegerValue(),tgtArray->Get(i*2+1)->IntegerValue()); } - Local xfrm = Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked(); - Matrix *xfrmmat = Nan::ObjectWrap::Unwrap(xfrm); - xfrmmat->mat = cv::getPerspectiveTransform(src_corners, tgt_corners); + Local xfrm = Matrix::CreateWrappedFromMat(cv::getPerspectiveTransform(src_corners, tgt_corners)); info.GetReturnValue().Set(xfrm); } @@ -3019,11 +3035,7 @@ NAN_METHOD(Matrix::Reshape) { JSTHROW("Invalid number of arguments"); } - Local img_to_return = - Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked(); - Matrix *img = Nan::ObjectWrap::Unwrap(img_to_return); - - img->mat = self->mat.reshape(cn, rows); + Local img_to_return = Matrix::CreateWrappedFromMat(self->mat.reshape(cn, rows)); info.GetReturnValue().Set(img_to_return); } @@ -3032,7 +3044,9 @@ NAN_METHOD(Matrix::Release) { Nan::HandleScope scope; Matrix *self = Nan::ObjectWrap::Unwrap(info.This()); + int size = self->mat.rows * self->mat.cols * self->mat.elemSize(); self->mat.release(); + Nan::AdjustExternalMemory(-1 * size); return; } @@ -3103,9 +3117,7 @@ NAN_METHOD(Matrix::Compare) { cv::Mat res = cv::Mat(width, height, CV_8UC1); cv::compare(self->mat, other->mat, res, cmpop); - Local out = Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked(); - Matrix *m_out = Nan::ObjectWrap::Unwrap(out); - m_out->mat = res; + Local out = Matrix::CreateWrappedFromMat(res); info.GetReturnValue().Set(out); return; @@ -3124,9 +3136,7 @@ NAN_METHOD(Matrix::Mul) { cv::Mat res = self->mat.mul(other->mat, scale); - Local out = Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked(); - Matrix *m_out = Nan::ObjectWrap::Unwrap(out); - m_out->mat = res; + Local out = Matrix::CreateWrappedFromMat(res); info.GetReturnValue().Set(out); return; diff --git a/src/Matrix.h b/src/Matrix.h index 81e89b21..9f69de97 100755 --- a/src/Matrix.h +++ b/src/Matrix.h @@ -7,11 +7,13 @@ class Matrix: public node_opencv::Matrix{ static Nan::Persistent constructor; static void Init(Local target); static NAN_METHOD(New); + static Local CreateWrappedFromMat(cv::Mat mat); Matrix(); Matrix(cv::Mat other, cv::Rect roi); Matrix(int rows, int cols); Matrix(int rows, int cols, int type); Matrix(int rows, int cols, int type, Local scalarObj); + ~Matrix(); static double DblGet(cv::Mat mat, int i, int j); diff --git a/src/OpenCV.cc b/src/OpenCV.cc index 6e8447dc..7ce38fe8 100755 --- a/src/OpenCV.cc +++ b/src/OpenCV.cc @@ -48,9 +48,7 @@ class AsyncImDecodeWorker: public Nan::AsyncWorker { Nan::HandleScope scope; try{ - Local im_to_return= Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked(); - Matrix *img = Nan::ObjectWrap::Unwrap(im_to_return); - img->mat = outputmat; + Local im_to_return = Matrix::CreateWrappedFromMat(outputmat); Local argv[] = { Nan::Null(), @@ -111,9 +109,7 @@ class AsyncImReadWorker: public Nan::AsyncWorker { void HandleOKCallback() { Nan::HandleScope scope; - Local im_to_return= Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked(); - Matrix *img = Nan::ObjectWrap::Unwrap(im_to_return); - img->mat = outputmat; + Local im_to_return = Matrix::CreateWrappedFromMat(outputmat); Local argv[] = { Nan::Null(), @@ -169,10 +165,7 @@ NAN_METHOD(OpenCV::ReadImageAsync) { width = info[0]->Uint32Value(); height = info[1]->Uint32Value(); - Local img_to_return = - Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked(); - Matrix *img = Nan::ObjectWrap::Unwrap(img_to_return); - img->mat = *(new cv::Mat(width, height, type)); + Local img_to_return = Matrix::CreateWrappedFromMat(*(new cv::Mat(width, height, type))); if (callback_arg < 0){ info.GetReturnValue().Set(img_to_return); return; @@ -197,10 +190,7 @@ NAN_METHOD(OpenCV::ReadImageAsync) { } } if (callback_arg < 0){ - Local img_to_return = - Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked(); - Matrix *img = Nan::ObjectWrap::Unwrap(img_to_return); - img->mat = cv::imread(filename, flags); + Local img_to_return = Matrix::CreateWrappedFromMat(cv::imread(filename, flags)); info.GetReturnValue().Set(img_to_return); return; } else { @@ -222,13 +212,10 @@ NAN_METHOD(OpenCV::ReadImageAsync) { } } if (callback_arg < 0){ - Local img_to_return = - Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked(); - Matrix *img = Nan::ObjectWrap::Unwrap(img_to_return); uint8_t *buf = (uint8_t *) Buffer::Data(info[0]->ToObject()); unsigned len = Buffer::Length(info[0]->ToObject()); cv::Mat *mbuf = new cv::Mat(len, 1, CV_64FC1, buf); - img->mat = cv::imdecode(*mbuf, flags); + Local img_to_return = Matrix::CreateWrappedFromMat(cv::imdecode(*mbuf, flags)); info.GetReturnValue().Set(img_to_return); return; } else { @@ -331,6 +318,7 @@ NAN_METHOD(OpenCV::ReadImage) { } img->mat = mat; + Nan::AdjustExternalMemory(img->mat.rows * img->mat.cols * img->mat.elemSize()); } catch (cv::Exception& e) { argv[0] = Nan::Error(e.what()); argv[1] = Nan::Null(); @@ -383,10 +371,7 @@ NAN_METHOD(OpenCV::ReadImageMulti) { argv[1] = output; for (std::vector::size_type i = 0; i < mats.size(); i ++) { - Local im_h = Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked(); - Matrix *img = Nan::ObjectWrap::Unwrap(im_h); - img->mat = mats[i]; - + Local im_h = Matrix::CreateWrappedFromMat(mats[i]); output->Set(i, im_h); } diff --git a/src/Stereo.cc b/src/Stereo.cc index c3af10f9..57e227d6 100644 --- a/src/Stereo.cc +++ b/src/Stereo.cc @@ -93,10 +93,7 @@ NAN_METHOD(StereoBM::Compute) { self->stereo(left, right, disparity, type); // Wrap the returned disparity map - Local < Object > disparityWrap = - Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked(); - Matrix *disp = Nan::ObjectWrap::Unwrap(disparityWrap); - disp->mat = disparity; + Local < Object > disparityWrap = Matrix::CreateWrappedFromMat(disparity); info.GetReturnValue().Set(disparityWrap); @@ -228,10 +225,7 @@ NAN_METHOD(StereoSGBM::Compute) { self->stereo(left, right, disparity); // Wrap the returned disparity map - Local < Object > disparityWrap = - Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked(); - Matrix *disp = Nan::ObjectWrap::Unwrap(disparityWrap); - disp->mat = disparity; + Local < Object > disparityWrap = Matrix::CreateWrappedFromMat(disparity); info.GetReturnValue().Set(disparityWrap); } catch (cv::Exception &e) { @@ -312,10 +306,7 @@ NAN_METHOD(StereoGC::Compute) { disp16.convertTo(disparity, CV_8U, -16); // Wrap the returned disparity map - Local < Object > disparityWrap = - Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked(); - Matrix *disp = Nan::ObjectWrap::Unwrap(disparityWrap); - disp->mat = disparity; + Local < Object > disparityWrap = Matrix::CreateWrappedFromMat(disparity); info.GetReturnValue().Set(disparityWrap); } catch (cv::Exception &e) { diff --git a/src/VideoCaptureWrap.cc b/src/VideoCaptureWrap.cc index d3e6c988..34e15d55 100755 --- a/src/VideoCaptureWrap.cc +++ b/src/VideoCaptureWrap.cc @@ -237,9 +237,7 @@ class AsyncVCWorker: public Nan::AsyncWorker { void HandleOKCallback() { Nan::HandleScope scope; - Local im_to_return= Nan::NewInstance(Nan::GetFunction(Nan::New(Matrix::constructor)).ToLocalChecked()).ToLocalChecked(); - Matrix *img = Nan::ObjectWrap::Unwrap(im_to_return); - img->mat = mat; + Local im_to_return = Matrix::CreateWrappedFromMat(mat); Local argv[] = { Nan::Null() @@ -280,6 +278,7 @@ NAN_METHOD(VideoCaptureWrap::ReadSync) { Matrix *img = Nan::ObjectWrap::Unwrap(im_to_return); v->cap.read(img->mat); + Nan::AdjustExternalMemory(img->mat.rows * img->mat.cols * img->mat.elemSize()); info.GetReturnValue().Set(im_to_return); }