Merge pull request #587 from btsimonh/asyncprotection

Asyncprotection
This commit is contained in:
btsimonh 2017-11-12 16:57:15 +00:00 committed by GitHub
commit 649df8f8de
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 80 additions and 32 deletions

View File

@ -16,6 +16,8 @@ cv.readImage("./files/mona.png", function(err, im) {
}
img.save("./tmp/resize-async-image.png");
console.log('Image saved to ./tmp/resize-async-image.png at '+img.width()+'x'+img.height());
img.release();
delete img;
};
var newwidth = width*0.95;
@ -25,6 +27,8 @@ cv.readImage("./files/mona.png", function(err, im) {
if (Async){
// note - generates a new image
im.resize(newwidth, newheight, AfterResize);
im.release(); // test release image before resize if done
delete im;
} else {
// sync - note - modifies the input image
im.resize(newwidth, newheight);

View File

@ -3,9 +3,10 @@ var path = require('path'),
var bg = null;
require("v8").setFlagsFromString('--expose_gc');
var gc = require("vm").runInNewContext('gc');
// gc stuff which we shojld not need with release() begin used
//require("v8").setFlagsFromString('--expose_gc');
//var gc = require("vm").runInNewContext('gc');
var do_sync = function(done){
// When opening a file, the full path must be passed to opencv
@ -17,15 +18,20 @@ var do_sync = function(done){
vid.read(function(err, m2){
if (err) throw err;
var mat = bg.apply(m2);
m2.release();
delete m2;
// mat is a monochrome img where moving objects are white
// do something with the return data
// we are done with the return data
mat.release();
delete mat;
if (x++<100){
//console.log("iter "+x);
setTimeout(iter, 1);
} else {
delete vid;
console.log("bg sync done");
gc();
// gc(); - no need to gc if we release both m2 and mat
if (undefined !== done)
done();
}
@ -45,7 +51,10 @@ var do_async = function(done){
vid.read(function(err, m2){
if (err) throw err;
bg.apply(m2, function(err, mat){
delete mat;
// do something with the return data
// we are done with the return data
mat.release();
delete mat;
if (err) throw err;
// mat is a monochrome img where moving objects are white
if (x++<100){
@ -54,11 +63,12 @@ var do_async = function(done){
} else {
console.log("bg async done");
delete vid;
gc();
// gc(); - no need to gc if we release both m2 and mat
if (undefined !== done)
done();
}
});
m2.release();
})
};

View File

@ -27,3 +27,33 @@ vid.read(function(err, mat) {
});
// restart video read
var vid2 = new cv.VideoCapture(path.join(__dirname, 'files', 'motion.mov'));
var filename2 = './tmp/output-async-'+new Date().getTime()+'.avi';
var writer2 = null;
var x = 0;
// do the same write async
var iter = function () {
vid2.read(function (err, m2) {
if (writer2 === null)
writer2 = new cv.VideoWriter(filename2, 'DIVX', vid2.getFPS(), m2.size(), true);
x++;
writer2.write(m2, function(err){
if (x < 100) {
iter();
} else {
vid2.release();
writer2.release();
}
});
m2.release();
delete m2;
});
};
// kick it off
iter();

View File

@ -313,13 +313,15 @@ public:
AsyncBackgroundSubtractorWorker(
Nan::Callback *callback,
BackgroundSubtractorWrap *bg,
Matrix *img) :
cv::Mat &img_mat):
Nan::AsyncWorker(callback),
bg(bg),
img(img) {
img_mat(img_mat) { // note: this makes a new cv::Mat, and so increments the ref count for the data without copying it
}
~AsyncBackgroundSubtractorWorker() {
// upon destroy, img_mat will reduce refcount on data by one
}
// Executed inside the worker-thread.
@ -330,9 +332,9 @@ public:
// wait here if already in apply - auto-release on scope exit
BGAutoMutex(bg->applymutex);
#if CV_MAJOR_VERSION >= 3
bg->subtractor->apply(this->img->mat, _fgMask);
bg->subtractor->apply(this->img_mat, _fgMask);
#else
bg->subtractor->operator()(this->img->mat, _fgMask);
bg->subtractor->operator()(this->img_mat, _fgMask);
#endif
}
@ -360,7 +362,7 @@ public:
private:
BackgroundSubtractorWrap *bg;
Matrix *img;
cv::Mat img_mat;
cv::Mat _fgMask;
};
@ -400,7 +402,7 @@ NAN_METHOD(BackgroundSubtractorWrap::Apply) {
Nan::Callback *callback = new Nan::Callback(cb.As<Function>());
Matrix *_img = Nan::ObjectWrap::Unwrap<Matrix>(info[0]->ToObject());
Nan::AsyncQueueWorker(new AsyncBackgroundSubtractorWorker( callback, self, _img));
Nan::AsyncQueueWorker(new AsyncBackgroundSubtractorWorker( callback, self, _img->mat));
return;
} else { //synchronous - return the image

View File

@ -769,21 +769,22 @@ NAN_METHOD(Matrix::ToBuffer) {
class AsyncToBufferWorker: public Nan::AsyncWorker {
public:
AsyncToBufferWorker(Nan::Callback *callback, Matrix* matrix, std::string ext,
AsyncToBufferWorker(Nan::Callback *callback, cv::Mat mat, std::string ext,
std::vector<int> params) :
Nan::AsyncWorker(callback),
matrix(matrix),
mat(mat), // dulipcate mat, adding ref, but not copying data
ext(ext),
params(params) {
}
~AsyncToBufferWorker() {
// mat is released, decrementing refcount
}
void Execute() {
std::vector<uchar> vec(0);
// std::vector<int> params(0);//CV_IMWRITE_JPEG_QUALITY 90
cv::imencode(ext, this->matrix->mat, vec, this->params);
cv::imencode(ext, this->mat, vec, this->params);
res = vec;
}
@ -813,7 +814,7 @@ public:
}
private:
Matrix* matrix;
cv::Mat mat;
std::string ext;
std::vector<int> params;
std::vector<uchar> res;
@ -853,7 +854,7 @@ NAN_METHOD(Matrix::ToBufferAsync) {
}
Nan::Callback *callback = new Nan::Callback(cb.As<Function>());
Nan::AsyncQueueWorker(new AsyncToBufferWorker(callback, self, ext, params));
Nan::AsyncQueueWorker(new AsyncToBufferWorker(callback, self->mat, ext, params));
return;
}
@ -1046,9 +1047,9 @@ NAN_METHOD(Matrix::Save) {
// https://github.com/rvagg/nan/blob/c579ae858ae3208d7e702e8400042ba9d48fa64b/examples/async_pi_estimate/async.cc
class AsyncSaveWorker: public Nan::AsyncWorker {
public:
AsyncSaveWorker(Nan::Callback *callback, Matrix* matrix, char* filename) :
AsyncSaveWorker(Nan::Callback *callback, cv::Mat mat, char* filename) :
Nan::AsyncWorker(callback),
matrix(matrix),
mat(mat),
filename(filename) {
}
@ -1060,7 +1061,7 @@ public:
// here, so everything we need for input and output
// should go on `this`.
void Execute() {
res = cv::imwrite(this->filename, this->matrix->mat);
res = cv::imwrite(this->filename, this->mat);
}
// Executed when the async work is complete
@ -1082,7 +1083,7 @@ public:
}
private:
Matrix* matrix;
cv::Mat mat;
std::string filename;
int res;
};
@ -1099,7 +1100,7 @@ NAN_METHOD(Matrix::SaveAsync) {
REQ_FUN_ARG(1, cb);
Nan::Callback *callback = new Nan::Callback(cb.As<Function>());
Nan::AsyncQueueWorker(new AsyncSaveWorker(callback, self, *filename));
Nan::AsyncQueueWorker(new AsyncSaveWorker(callback, self->mat, *filename));
return;
}
@ -1892,9 +1893,9 @@ cv::Rect* setRect(Local<Object> objRect, cv::Rect &result) {
class ResizeASyncWorker: public Nan::AsyncWorker {
public:
ResizeASyncWorker(Nan::Callback *callback, Matrix *image, cv::Size size, double fx, double fy, int interpolation) :
ResizeASyncWorker(Nan::Callback *callback, cv::Mat image, cv::Size size, double fx, double fy, int interpolation) :
Nan::AsyncWorker(callback),
image(image),
image(image), // here, the cv::Mat is duplicated, adding to refcount without data copy
dest(NULL),
size(size),
fx(fx),
@ -1908,12 +1909,13 @@ public:
// could happen if NaN does not call HandleSuccess?
delete dest;
dest = NULL;
// cv::Mat image will be deleted, which will reduce refcount
}
void Execute() {
try {
dest = new Matrix();
cv::resize(image->mat, dest->mat, size, fx, fy, interpolation);
cv::resize(image, dest->mat, size, fx, fy, interpolation);
success = 1;
} catch(...){
success = 0;
@ -1973,7 +1975,7 @@ public:
}
private:
Matrix *image;
cv::Mat image;
Matrix *dest;
cv::Size size;
double fx;
@ -2039,7 +2041,7 @@ NAN_METHOD(Matrix::Resize) {
if (isAsync){
REQ_FUN_ARG(numargs-1, cb);
Nan::Callback *callback = new Nan::Callback(cb.As<Function>());
Nan::AsyncQueueWorker(new ResizeASyncWorker(callback, self, size, fx, fy, interpolation));
Nan::AsyncQueueWorker(new ResizeASyncWorker(callback, self->mat, size, fx, fy, interpolation));
info.GetReturnValue().Set(Nan::Null());
} else {
try{

View File

@ -90,10 +90,10 @@ NAN_METHOD(VideoWriterWrap::Release) {
class AsyncVWWorker: public Nan::AsyncWorker {
public:
AsyncVWWorker(Nan::Callback *callback, VideoWriterWrap *vw, Matrix *im) :
AsyncVWWorker(Nan::Callback *callback, VideoWriterWrap *vw, cv::Mat mat) :
Nan::AsyncWorker(callback),
vw(vw),
im(im) {
mat(mat) {
}
~AsyncVWWorker() {
@ -104,7 +104,7 @@ public:
// here, so everything we need for input and output
// should go on `this`.
void Execute() {
this->vw->writer.write(im->mat);
this->vw->writer.write(mat);
}
// Executed when the async work is complete
@ -126,7 +126,7 @@ public:
private:
VideoWriterWrap *vw;
Matrix* im;
cv::Mat mat;
};
NAN_METHOD(VideoWriterWrap::Write) {
@ -137,7 +137,7 @@ NAN_METHOD(VideoWriterWrap::Write) {
REQ_FUN_ARG(1, cb);
Nan::Callback *callback = new Nan::Callback(cb.As<Function>());
Nan::AsyncQueueWorker(new AsyncVWWorker(callback, v, im));
Nan::AsyncQueueWorker(new AsyncVWWorker(callback, v, im->mat));
return;
}