mirror of
https://github.com/peterbraden/node-opencv.git
synced 2025-12-08 19:45:55 +00:00
commit
649df8f8de
@ -16,6 +16,8 @@ cv.readImage("./files/mona.png", function(err, im) {
|
|||||||
}
|
}
|
||||||
img.save("./tmp/resize-async-image.png");
|
img.save("./tmp/resize-async-image.png");
|
||||||
console.log('Image saved to ./tmp/resize-async-image.png at '+img.width()+'x'+img.height());
|
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;
|
var newwidth = width*0.95;
|
||||||
@ -25,6 +27,8 @@ cv.readImage("./files/mona.png", function(err, im) {
|
|||||||
if (Async){
|
if (Async){
|
||||||
// note - generates a new image
|
// note - generates a new image
|
||||||
im.resize(newwidth, newheight, AfterResize);
|
im.resize(newwidth, newheight, AfterResize);
|
||||||
|
im.release(); // test release image before resize if done
|
||||||
|
delete im;
|
||||||
} else {
|
} else {
|
||||||
// sync - note - modifies the input image
|
// sync - note - modifies the input image
|
||||||
im.resize(newwidth, newheight);
|
im.resize(newwidth, newheight);
|
||||||
|
|||||||
@ -3,9 +3,10 @@ var path = require('path'),
|
|||||||
|
|
||||||
var bg = null;
|
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){
|
var do_sync = function(done){
|
||||||
// When opening a file, the full path must be passed to opencv
|
// 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){
|
vid.read(function(err, m2){
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
var mat = bg.apply(m2);
|
var mat = bg.apply(m2);
|
||||||
|
m2.release();
|
||||||
delete m2;
|
delete m2;
|
||||||
// mat is a monochrome img where moving objects are white
|
// 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){
|
if (x++<100){
|
||||||
//console.log("iter "+x);
|
//console.log("iter "+x);
|
||||||
setTimeout(iter, 1);
|
setTimeout(iter, 1);
|
||||||
} else {
|
} else {
|
||||||
delete vid;
|
delete vid;
|
||||||
console.log("bg sync done");
|
console.log("bg sync done");
|
||||||
gc();
|
// gc(); - no need to gc if we release both m2 and mat
|
||||||
if (undefined !== done)
|
if (undefined !== done)
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
@ -45,7 +51,10 @@ var do_async = function(done){
|
|||||||
vid.read(function(err, m2){
|
vid.read(function(err, m2){
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
bg.apply(m2, function(err, mat){
|
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;
|
if (err) throw err;
|
||||||
// mat is a monochrome img where moving objects are white
|
// mat is a monochrome img where moving objects are white
|
||||||
if (x++<100){
|
if (x++<100){
|
||||||
@ -54,11 +63,12 @@ var do_async = function(done){
|
|||||||
} else {
|
} else {
|
||||||
console.log("bg async done");
|
console.log("bg async done");
|
||||||
delete vid;
|
delete vid;
|
||||||
gc();
|
// gc(); - no need to gc if we release both m2 and mat
|
||||||
if (undefined !== done)
|
if (undefined !== done)
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
m2.release();
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -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();
|
||||||
|
|||||||
@ -313,13 +313,15 @@ public:
|
|||||||
AsyncBackgroundSubtractorWorker(
|
AsyncBackgroundSubtractorWorker(
|
||||||
Nan::Callback *callback,
|
Nan::Callback *callback,
|
||||||
BackgroundSubtractorWrap *bg,
|
BackgroundSubtractorWrap *bg,
|
||||||
Matrix *img) :
|
cv::Mat &img_mat):
|
||||||
Nan::AsyncWorker(callback),
|
Nan::AsyncWorker(callback),
|
||||||
bg(bg),
|
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() {
|
~AsyncBackgroundSubtractorWorker() {
|
||||||
|
// upon destroy, img_mat will reduce refcount on data by one
|
||||||
}
|
}
|
||||||
|
|
||||||
// Executed inside the worker-thread.
|
// Executed inside the worker-thread.
|
||||||
@ -330,9 +332,9 @@ public:
|
|||||||
// wait here if already in apply - auto-release on scope exit
|
// wait here if already in apply - auto-release on scope exit
|
||||||
BGAutoMutex(bg->applymutex);
|
BGAutoMutex(bg->applymutex);
|
||||||
#if CV_MAJOR_VERSION >= 3
|
#if CV_MAJOR_VERSION >= 3
|
||||||
bg->subtractor->apply(this->img->mat, _fgMask);
|
bg->subtractor->apply(this->img_mat, _fgMask);
|
||||||
#else
|
#else
|
||||||
bg->subtractor->operator()(this->img->mat, _fgMask);
|
bg->subtractor->operator()(this->img_mat, _fgMask);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -360,7 +362,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
BackgroundSubtractorWrap *bg;
|
BackgroundSubtractorWrap *bg;
|
||||||
Matrix *img;
|
cv::Mat img_mat;
|
||||||
cv::Mat _fgMask;
|
cv::Mat _fgMask;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -399,8 +401,8 @@ NAN_METHOD(BackgroundSubtractorWrap::Apply) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Nan::Callback *callback = new Nan::Callback(cb.As<Function>());
|
Nan::Callback *callback = new Nan::Callback(cb.As<Function>());
|
||||||
Matrix *_img = Nan::ObjectWrap::Unwrap<Matrix>(info[0]->ToObject());
|
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;
|
return;
|
||||||
} else { //synchronous - return the image
|
} else { //synchronous - return the image
|
||||||
|
|
||||||
|
|||||||
@ -769,21 +769,22 @@ NAN_METHOD(Matrix::ToBuffer) {
|
|||||||
|
|
||||||
class AsyncToBufferWorker: public Nan::AsyncWorker {
|
class AsyncToBufferWorker: public Nan::AsyncWorker {
|
||||||
public:
|
public:
|
||||||
AsyncToBufferWorker(Nan::Callback *callback, Matrix* matrix, std::string ext,
|
AsyncToBufferWorker(Nan::Callback *callback, cv::Mat mat, std::string ext,
|
||||||
std::vector<int> params) :
|
std::vector<int> params) :
|
||||||
Nan::AsyncWorker(callback),
|
Nan::AsyncWorker(callback),
|
||||||
matrix(matrix),
|
mat(mat), // dulipcate mat, adding ref, but not copying data
|
||||||
ext(ext),
|
ext(ext),
|
||||||
params(params) {
|
params(params) {
|
||||||
}
|
}
|
||||||
|
|
||||||
~AsyncToBufferWorker() {
|
~AsyncToBufferWorker() {
|
||||||
|
// mat is released, decrementing refcount
|
||||||
}
|
}
|
||||||
|
|
||||||
void Execute() {
|
void Execute() {
|
||||||
std::vector<uchar> vec(0);
|
std::vector<uchar> vec(0);
|
||||||
// std::vector<int> params(0);//CV_IMWRITE_JPEG_QUALITY 90
|
// 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;
|
res = vec;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -813,7 +814,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Matrix* matrix;
|
cv::Mat mat;
|
||||||
std::string ext;
|
std::string ext;
|
||||||
std::vector<int> params;
|
std::vector<int> params;
|
||||||
std::vector<uchar> res;
|
std::vector<uchar> res;
|
||||||
@ -853,7 +854,7 @@ NAN_METHOD(Matrix::ToBufferAsync) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Nan::Callback *callback = new Nan::Callback(cb.As<Function>());
|
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;
|
return;
|
||||||
}
|
}
|
||||||
@ -1046,9 +1047,9 @@ NAN_METHOD(Matrix::Save) {
|
|||||||
// https://github.com/rvagg/nan/blob/c579ae858ae3208d7e702e8400042ba9d48fa64b/examples/async_pi_estimate/async.cc
|
// https://github.com/rvagg/nan/blob/c579ae858ae3208d7e702e8400042ba9d48fa64b/examples/async_pi_estimate/async.cc
|
||||||
class AsyncSaveWorker: public Nan::AsyncWorker {
|
class AsyncSaveWorker: public Nan::AsyncWorker {
|
||||||
public:
|
public:
|
||||||
AsyncSaveWorker(Nan::Callback *callback, Matrix* matrix, char* filename) :
|
AsyncSaveWorker(Nan::Callback *callback, cv::Mat mat, char* filename) :
|
||||||
Nan::AsyncWorker(callback),
|
Nan::AsyncWorker(callback),
|
||||||
matrix(matrix),
|
mat(mat),
|
||||||
filename(filename) {
|
filename(filename) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1060,7 +1061,7 @@ public:
|
|||||||
// here, so everything we need for input and output
|
// here, so everything we need for input and output
|
||||||
// should go on `this`.
|
// should go on `this`.
|
||||||
void Execute() {
|
void Execute() {
|
||||||
res = cv::imwrite(this->filename, this->matrix->mat);
|
res = cv::imwrite(this->filename, this->mat);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Executed when the async work is complete
|
// Executed when the async work is complete
|
||||||
@ -1082,7 +1083,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Matrix* matrix;
|
cv::Mat mat;
|
||||||
std::string filename;
|
std::string filename;
|
||||||
int res;
|
int res;
|
||||||
};
|
};
|
||||||
@ -1099,7 +1100,7 @@ NAN_METHOD(Matrix::SaveAsync) {
|
|||||||
REQ_FUN_ARG(1, cb);
|
REQ_FUN_ARG(1, cb);
|
||||||
|
|
||||||
Nan::Callback *callback = new Nan::Callback(cb.As<Function>());
|
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;
|
return;
|
||||||
}
|
}
|
||||||
@ -1892,9 +1893,9 @@ cv::Rect* setRect(Local<Object> objRect, cv::Rect &result) {
|
|||||||
|
|
||||||
class ResizeASyncWorker: public Nan::AsyncWorker {
|
class ResizeASyncWorker: public Nan::AsyncWorker {
|
||||||
public:
|
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),
|
Nan::AsyncWorker(callback),
|
||||||
image(image),
|
image(image), // here, the cv::Mat is duplicated, adding to refcount without data copy
|
||||||
dest(NULL),
|
dest(NULL),
|
||||||
size(size),
|
size(size),
|
||||||
fx(fx),
|
fx(fx),
|
||||||
@ -1908,12 +1909,13 @@ public:
|
|||||||
// could happen if NaN does not call HandleSuccess?
|
// could happen if NaN does not call HandleSuccess?
|
||||||
delete dest;
|
delete dest;
|
||||||
dest = NULL;
|
dest = NULL;
|
||||||
|
// cv::Mat image will be deleted, which will reduce refcount
|
||||||
}
|
}
|
||||||
|
|
||||||
void Execute() {
|
void Execute() {
|
||||||
try {
|
try {
|
||||||
dest = new Matrix();
|
dest = new Matrix();
|
||||||
cv::resize(image->mat, dest->mat, size, fx, fy, interpolation);
|
cv::resize(image, dest->mat, size, fx, fy, interpolation);
|
||||||
success = 1;
|
success = 1;
|
||||||
} catch(...){
|
} catch(...){
|
||||||
success = 0;
|
success = 0;
|
||||||
@ -1973,7 +1975,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Matrix *image;
|
cv::Mat image;
|
||||||
Matrix *dest;
|
Matrix *dest;
|
||||||
cv::Size size;
|
cv::Size size;
|
||||||
double fx;
|
double fx;
|
||||||
@ -2039,7 +2041,7 @@ NAN_METHOD(Matrix::Resize) {
|
|||||||
if (isAsync){
|
if (isAsync){
|
||||||
REQ_FUN_ARG(numargs-1, cb);
|
REQ_FUN_ARG(numargs-1, cb);
|
||||||
Nan::Callback *callback = new Nan::Callback(cb.As<Function>());
|
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());
|
info.GetReturnValue().Set(Nan::Null());
|
||||||
} else {
|
} else {
|
||||||
try{
|
try{
|
||||||
|
|||||||
@ -90,10 +90,10 @@ NAN_METHOD(VideoWriterWrap::Release) {
|
|||||||
|
|
||||||
class AsyncVWWorker: public Nan::AsyncWorker {
|
class AsyncVWWorker: public Nan::AsyncWorker {
|
||||||
public:
|
public:
|
||||||
AsyncVWWorker(Nan::Callback *callback, VideoWriterWrap *vw, Matrix *im) :
|
AsyncVWWorker(Nan::Callback *callback, VideoWriterWrap *vw, cv::Mat mat) :
|
||||||
Nan::AsyncWorker(callback),
|
Nan::AsyncWorker(callback),
|
||||||
vw(vw),
|
vw(vw),
|
||||||
im(im) {
|
mat(mat) {
|
||||||
}
|
}
|
||||||
|
|
||||||
~AsyncVWWorker() {
|
~AsyncVWWorker() {
|
||||||
@ -104,7 +104,7 @@ public:
|
|||||||
// here, so everything we need for input and output
|
// here, so everything we need for input and output
|
||||||
// should go on `this`.
|
// should go on `this`.
|
||||||
void Execute() {
|
void Execute() {
|
||||||
this->vw->writer.write(im->mat);
|
this->vw->writer.write(mat);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Executed when the async work is complete
|
// Executed when the async work is complete
|
||||||
@ -126,7 +126,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
VideoWriterWrap *vw;
|
VideoWriterWrap *vw;
|
||||||
Matrix* im;
|
cv::Mat mat;
|
||||||
};
|
};
|
||||||
|
|
||||||
NAN_METHOD(VideoWriterWrap::Write) {
|
NAN_METHOD(VideoWriterWrap::Write) {
|
||||||
@ -137,7 +137,7 @@ NAN_METHOD(VideoWriterWrap::Write) {
|
|||||||
REQ_FUN_ARG(1, cb);
|
REQ_FUN_ARG(1, cb);
|
||||||
|
|
||||||
Nan::Callback *callback = new Nan::Callback(cb.As<Function>());
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user