mirror of
https://github.com/peterbraden/node-opencv.git
synced 2025-12-08 19:45:55 +00:00
- first pass migration of all relevant source done
* compiling ok under node 0.11.13 * missing a number of async methods
This commit is contained in:
parent
3bf2ee7fac
commit
a793f21561
@ -1,6 +1,7 @@
|
|||||||
#include "BackgroundSubtractor.h"
|
#include "BackgroundSubtractor.h"
|
||||||
#include "Matrix.h"
|
#include "Matrix.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <nan.h>
|
||||||
|
|
||||||
#if CV_MAJOR_VERSION >= 2 && CV_MINOR_VERSION >=4
|
#if CV_MAJOR_VERSION >= 2 && CV_MINOR_VERSION >=4
|
||||||
|
|
||||||
@ -8,21 +9,23 @@ Persistent<FunctionTemplate> BackgroundSubtractorWrap::constructor;
|
|||||||
|
|
||||||
void
|
void
|
||||||
BackgroundSubtractorWrap::Init(Handle<Object> target) {
|
BackgroundSubtractorWrap::Init(Handle<Object> target) {
|
||||||
HandleScope scope;
|
NanScope();
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
constructor = Persistent<FunctionTemplate>::New(FunctionTemplate::New(BackgroundSubtractorWrap::New));
|
Local<FunctionTemplate> ctor = NanNew<FunctionTemplate>(BackgroundSubtractorWrap::New);
|
||||||
constructor->InstanceTemplate()->SetInternalFieldCount(1);
|
NanAssignPersistent(constructor, ctor);
|
||||||
constructor->SetClassName(String::NewSymbol("BackgroundSubtractor"));
|
ctor->InstanceTemplate()->SetInternalFieldCount(1);
|
||||||
|
ctor->SetClassName(NanNew("BackgroundSubtractor"));
|
||||||
|
|
||||||
NODE_SET_METHOD(constructor, "createMOG", CreateMOG);
|
NODE_SET_METHOD(ctor, "createMOG", CreateMOG);
|
||||||
NODE_SET_PROTOTYPE_METHOD(constructor, "applyMOG", ApplyMOG);
|
NODE_SET_PROTOTYPE_METHOD(ctor, "applyMOG", ApplyMOG);
|
||||||
|
|
||||||
target->Set(String::NewSymbol("BackgroundSubtractor"), constructor->GetFunction());
|
target->Set(NanNew("BackgroundSubtractor"), ctor->GetFunction());
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
NAN_METHOD(BackgroundSubtractorWrap::New() {
|
NAN_METHOD(BackgroundSubtractorWrap::New) {
|
||||||
HandleScope scope;
|
NanScope();
|
||||||
|
|
||||||
if (args.This()->InternalFieldCount() == 0)
|
if (args.This()->InternalFieldCount() == 0)
|
||||||
JSTHROW_TYPE("Cannot Instantiate without new")
|
JSTHROW_TYPE("Cannot Instantiate without new")
|
||||||
@ -33,11 +36,11 @@ NAN_METHOD(BackgroundSubtractorWrap::New() {
|
|||||||
|
|
||||||
pt->Wrap(args.This());
|
pt->Wrap(args.This());
|
||||||
|
|
||||||
return args.This();
|
NanReturnValue(args.This());
|
||||||
}
|
}
|
||||||
|
|
||||||
NAN_METHOD(BackgroundSubtractorWrap::CreateMOG() {
|
NAN_METHOD(BackgroundSubtractorWrap::CreateMOG) {
|
||||||
HandleScope scope;
|
NanScope();
|
||||||
|
|
||||||
int history = 200;
|
int history = 200;
|
||||||
int nmixtures = 5;
|
int nmixtures = 5;
|
||||||
@ -51,17 +54,17 @@ NAN_METHOD(BackgroundSubtractorWrap::CreateMOG() {
|
|||||||
DOUBLE_FROM_ARGS(noiseSigma, 3)
|
DOUBLE_FROM_ARGS(noiseSigma, 3)
|
||||||
}
|
}
|
||||||
|
|
||||||
Local<Object> n = BackgroundSubtractorWrap::constructor->GetFunction()->NewInstance();
|
Local<Object> n = NanNew(BackgroundSubtractorWrap::constructor)->GetFunction()->NewInstance();
|
||||||
|
|
||||||
cv::Ptr<cv::BackgroundSubtractor> bg;
|
cv::Ptr<cv::BackgroundSubtractor> bg;
|
||||||
BackgroundSubtractorWrap *pt = new BackgroundSubtractorWrap(bg);
|
BackgroundSubtractorWrap *pt = new BackgroundSubtractorWrap(bg);
|
||||||
|
|
||||||
pt->Wrap(n);
|
pt->Wrap(n);
|
||||||
return n;
|
NanReturnValue( n );
|
||||||
};
|
};
|
||||||
|
|
||||||
//Fetch foreground mask
|
//Fetch foreground mask
|
||||||
NAN_METHOD(BackgroundSubtractorWrap::ApplyMOG() {
|
NAN_METHOD(BackgroundSubtractorWrap::ApplyMOG) {
|
||||||
|
|
||||||
SETUP_FUNCTION(BackgroundSubtractorWrap)
|
SETUP_FUNCTION(BackgroundSubtractorWrap)
|
||||||
|
|
||||||
@ -70,15 +73,15 @@ NAN_METHOD(BackgroundSubtractorWrap::ApplyMOG() {
|
|||||||
Local<Value> argv[2];
|
Local<Value> argv[2];
|
||||||
|
|
||||||
if(args.Length() == 0){
|
if(args.Length() == 0){
|
||||||
argv[0] = String::New("Input image missing");
|
argv[0] = NanNew("Input image missing");
|
||||||
argv[1] = Local<Value>::New(Null());
|
argv[1] = NanNull();
|
||||||
cb->Call(Context::GetCurrent()->Global(), 2, argv);
|
cb->Call(NanGetCurrentContext()->Global(), 2, argv);
|
||||||
return scope.Close(Undefined());
|
NanReturnUndefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
try{
|
try{
|
||||||
|
|
||||||
Local<Object> fgMask = Matrix::constructor->GetFunction()->NewInstance();
|
Local<Object> fgMask = NanNew(Matrix::constructor)->GetFunction()->NewInstance();
|
||||||
Matrix *img = ObjectWrap::Unwrap<Matrix>(fgMask);
|
Matrix *img = ObjectWrap::Unwrap<Matrix>(fgMask);
|
||||||
|
|
||||||
|
|
||||||
@ -97,7 +100,7 @@ NAN_METHOD(BackgroundSubtractorWrap::ApplyMOG() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mat.empty()){
|
if (mat.empty()){
|
||||||
return v8::ThrowException(v8::Exception::TypeError(v8::String::New("Error loading file")));
|
return NanThrowTypeError("Error loading file");
|
||||||
}
|
}
|
||||||
|
|
||||||
cv::Mat _fgMask;
|
cv::Mat _fgMask;
|
||||||
@ -107,22 +110,22 @@ NAN_METHOD(BackgroundSubtractorWrap::ApplyMOG() {
|
|||||||
|
|
||||||
mat.release();
|
mat.release();
|
||||||
|
|
||||||
argv[0] = Local<Value>::New(Null());
|
argv[0] = NanNull();
|
||||||
argv[1] = fgMask;
|
argv[1] = fgMask;
|
||||||
|
|
||||||
TryCatch try_catch;
|
TryCatch try_catch;
|
||||||
|
|
||||||
cb->Call(Context::GetCurrent()->Global(), 2, argv);
|
cb->Call(NanGetCurrentContext()->Global(), 2, argv);
|
||||||
|
|
||||||
if (try_catch.HasCaught()) {
|
if (try_catch.HasCaught()) {
|
||||||
FatalException(try_catch);
|
FatalException(try_catch);
|
||||||
}
|
}
|
||||||
|
|
||||||
return scope.Close(v8::Undefined());
|
NanReturnUndefined();
|
||||||
}
|
}
|
||||||
catch( cv::Exception& e ){
|
catch( cv::Exception& e ){
|
||||||
const char* err_msg = e.what();
|
const char* err_msg = e.what();
|
||||||
return v8::ThrowException(v8::Exception::Error(v8::String::New(err_msg)));
|
NanThrowError(err_msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@ -10,12 +10,12 @@ class BackgroundSubtractorWrap: public node::ObjectWrap {
|
|||||||
|
|
||||||
static Persistent<FunctionTemplate> constructor;
|
static Persistent<FunctionTemplate> constructor;
|
||||||
static void Init(Handle<Object> target);
|
static void Init(Handle<Object> target);
|
||||||
static Handle<Value> New(const Arguments &args);
|
static NAN_METHOD(New);
|
||||||
|
|
||||||
BackgroundSubtractorWrap(cv::Ptr<cv::BackgroundSubtractor> bg);
|
BackgroundSubtractorWrap(cv::Ptr<cv::BackgroundSubtractor> bg);
|
||||||
|
|
||||||
static Handle<Value> CreateMOG(const v8::Arguments&);
|
static NAN_METHOD(CreateMOG);
|
||||||
static Handle<Value> ApplyMOG(const v8::Arguments&);
|
static NAN_METHOD(ApplyMOG);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -12,23 +12,27 @@ Persistent<FunctionTemplate> TrackedObject::constructor;
|
|||||||
|
|
||||||
void
|
void
|
||||||
TrackedObject::Init(Handle<Object> target) {
|
TrackedObject::Init(Handle<Object> target) {
|
||||||
HandleScope scope;
|
NanScope();
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
constructor = Persistent<FunctionTemplate>::New(FunctionTemplate::New(TrackedObject::New));
|
Local<FunctionTemplate> ctor = NanNew<FunctionTemplate>(TrackedObject::New);
|
||||||
constructor->InstanceTemplate()->SetInternalFieldCount(1);
|
NanAssignPersistent(constructor, ctor);
|
||||||
constructor->SetClassName(String::NewSymbol("TrackedObject"));
|
ctor->InstanceTemplate()->SetInternalFieldCount(1);
|
||||||
|
ctor->SetClassName(NanNew("TrackedObject"));
|
||||||
|
|
||||||
|
|
||||||
// Prototype
|
// Prototype
|
||||||
//Local<ObjectTemplate> proto = constructor->PrototypeTemplate();
|
//Local<ObjectTemplate> proto = constructor->PrototypeTemplate();
|
||||||
|
|
||||||
NODE_SET_PROTOTYPE_METHOD(constructor, "track", Track);
|
NODE_SET_PROTOTYPE_METHOD(ctor, "track", Track);
|
||||||
target->Set(String::NewSymbol("TrackedObject"), constructor->GetFunction());
|
|
||||||
|
//target->Set(String::NewSymbol("TrackedObject"), constructor->GetFunction());
|
||||||
|
target->Set(NanNew("TrackedObject"), ctor->GetFunction());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
NAN_METHOD(TrackedObject::New() {
|
NAN_METHOD(TrackedObject::New) {
|
||||||
HandleScope scope;
|
NanScope();
|
||||||
|
|
||||||
if (args.This()->InternalFieldCount() == 0){
|
if (args.This()->InternalFieldCount() == 0){
|
||||||
JSTHROW_TYPE("Cannot Instantiate without new")
|
JSTHROW_TYPE("Cannot Instantiate without new")
|
||||||
@ -52,8 +56,8 @@ NAN_METHOD(TrackedObject::New() {
|
|||||||
if (args[2]->IsObject()){
|
if (args[2]->IsObject()){
|
||||||
Local<Object> opts = args[2]->ToObject();
|
Local<Object> opts = args[2]->ToObject();
|
||||||
|
|
||||||
if (opts->Get(String::New("channel"))->IsString()){
|
if (opts->Get(NanNew("channel"))->IsString()){
|
||||||
v8::String::Utf8Value c(opts->Get(String::New("channel"))->ToString());
|
v8::String::Utf8Value c(opts->Get(NanNew("channel"))->ToString());
|
||||||
std::string cc = std::string(*c);
|
std::string cc = std::string(*c);
|
||||||
|
|
||||||
if (cc == "hue" || cc == "h"){
|
if (cc == "hue" || cc == "h"){
|
||||||
@ -74,7 +78,7 @@ NAN_METHOD(TrackedObject::New() {
|
|||||||
|
|
||||||
|
|
||||||
to->Wrap(args.This());
|
to->Wrap(args.This());
|
||||||
return args.This();
|
NanReturnValue(args.This());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -119,12 +123,12 @@ TrackedObject::TrackedObject(cv::Mat image, cv::Rect rect, int chan){
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
NAN_METHOD(TrackedObject::Track(const v8::Arguments& args){
|
NAN_METHOD(TrackedObject::Track){
|
||||||
SETUP_FUNCTION(TrackedObject)
|
SETUP_FUNCTION(TrackedObject)
|
||||||
|
|
||||||
if (args.Length() != 1){
|
if (args.Length() != 1){
|
||||||
v8::ThrowException(v8::Exception::TypeError(v8::String::New("track takes an image param")));
|
NanThrowTypeError("track takes an image param");
|
||||||
return Undefined();
|
NanReturnUndefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -135,7 +139,7 @@ NAN_METHOD(TrackedObject::Track(const v8::Arguments& args){
|
|||||||
self->prev_rect.y <0 ||
|
self->prev_rect.y <0 ||
|
||||||
self->prev_rect.width <= 1 ||
|
self->prev_rect.width <= 1 ||
|
||||||
self->prev_rect.height <= 1){
|
self->prev_rect.height <= 1){
|
||||||
return v8::ThrowException(v8::Exception::TypeError(v8::String::New("OPENCV ERROR: prev rectangle is illogical")));
|
return NanThrowTypeError("OPENCV ERROR: prev rectangle is illogical");
|
||||||
}
|
}
|
||||||
|
|
||||||
update_chann_image(self, im->mat);
|
update_chann_image(self, im->mat);
|
||||||
@ -165,25 +169,24 @@ NAN_METHOD(TrackedObject::Track(const v8::Arguments& args){
|
|||||||
self->prev_rect = backup_prev_rect;
|
self->prev_rect = backup_prev_rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
v8::Local<v8::Array> arr = NanNew<Array>(4);
|
||||||
v8::Local<v8::Array> arr = v8::Array::New(4);
|
|
||||||
|
|
||||||
|
|
||||||
arr->Set(0, Number::New(bounds.x));
|
arr->Set(0, NanNew<Number>(bounds.x));
|
||||||
arr->Set(1, Number::New(bounds.y));
|
arr->Set(1, NanNew<Number>(bounds.y));
|
||||||
arr->Set(2, Number::New(bounds.x + bounds.width));
|
arr->Set(2, NanNew<Number>(bounds.x + bounds.width));
|
||||||
arr->Set(3, Number::New(bounds.y + bounds.height));
|
arr->Set(3, NanNew<Number>(bounds.y + bounds.height));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
cv::Point2f pts[4];
|
cv::Point2f pts[4];
|
||||||
r.points(pts);
|
r.points(pts);
|
||||||
|
|
||||||
for (int i=0; i<8; i+=2){
|
for (int i=0; i<8; i+=2){
|
||||||
arr->Set(i, Number::New(pts[i].x));
|
arr->Set(i, NanNew<Number>(pts[i].x));
|
||||||
arr->Set(i+1, Number::New(pts[i].y));
|
arr->Set(i+1, NanNew<Number>(pts[i].y));
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
return scope.Close(arr);
|
NanReturnValue(arr);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,45 +10,44 @@ Persistent<FunctionTemplate> CascadeClassifierWrap::constructor;
|
|||||||
|
|
||||||
void
|
void
|
||||||
CascadeClassifierWrap::Init(Handle<Object> target) {
|
CascadeClassifierWrap::Init(Handle<Object> target) {
|
||||||
HandleScope scope;
|
NanScope();
|
||||||
|
|
||||||
// Constructor
|
Local<FunctionTemplate> ctor = NanNew<FunctionTemplate>(CascadeClassifierWrap::New);
|
||||||
constructor = Persistent<FunctionTemplate>::New(FunctionTemplate::New(CascadeClassifierWrap::New));
|
NanAssignPersistent(constructor, ctor);
|
||||||
constructor->InstanceTemplate()->SetInternalFieldCount(1);
|
ctor->InstanceTemplate()->SetInternalFieldCount(1);
|
||||||
constructor->SetClassName(String::NewSymbol("CascadeClassifier"));
|
ctor->SetClassName(NanNew("CascadeClassifier"));
|
||||||
|
|
||||||
// Prototype
|
// Prototype
|
||||||
//Local<ObjectTemplate> proto = constructor->PrototypeTemplate();
|
//Local<ObjectTemplate> proto = constructor->PrototypeTemplate();
|
||||||
|
|
||||||
NODE_SET_PROTOTYPE_METHOD(constructor, "detectMultiScale", DetectMultiScale);
|
NODE_SET_PROTOTYPE_METHOD(ctor, "detectMultiScale", DetectMultiScale);
|
||||||
|
|
||||||
|
target->Set(NanNew("CascadeClassifier"), ctor->GetFunction());
|
||||||
|
|
||||||
target->Set(String::NewSymbol("CascadeClassifier"), constructor->GetFunction());
|
|
||||||
};
|
};
|
||||||
|
|
||||||
NAN_METHOD(CascadeClassifierWrap::New() {
|
NAN_METHOD(CascadeClassifierWrap::New) {
|
||||||
HandleScope scope;
|
NanScope();
|
||||||
|
|
||||||
if (args.This()->InternalFieldCount() == 0)
|
if (args.This()->InternalFieldCount() == 0)
|
||||||
return v8::ThrowException(v8::Exception::TypeError(v8::String::New("Cannot Instantiate without new")));
|
NanThrowTypeError("Cannot instantiate without new");
|
||||||
|
|
||||||
CascadeClassifierWrap *pt = new CascadeClassifierWrap(*args[0]);
|
CascadeClassifierWrap *pt = new CascadeClassifierWrap(*args[0]);
|
||||||
pt->Wrap(args.This());
|
pt->Wrap(args.This());
|
||||||
return args.This();
|
NanReturnValue( args.This() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CascadeClassifierWrap::CascadeClassifierWrap(v8::Value* fileName){
|
CascadeClassifierWrap::CascadeClassifierWrap(v8::Value* fileName){
|
||||||
std::string filename;
|
std::string filename;
|
||||||
filename = std::string(*v8::String::AsciiValue(fileName->ToString()));
|
filename = std::string(*NanAsciiString(fileName->ToString()));
|
||||||
|
|
||||||
|
|
||||||
if (!cc.load(filename.c_str())){
|
if (!cc.load(filename.c_str())){
|
||||||
v8::ThrowException(v8::Exception::TypeError(v8::String::New("Error loading file")));
|
NanThrowTypeError("Error loading file");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct classifier_baton_t {
|
struct classifier_baton_t {
|
||||||
CascadeClassifierWrap *cc;
|
CascadeClassifierWrap *cc;
|
||||||
Persistent<Function> cb;
|
Persistent<Function> cb;
|
||||||
@ -65,12 +64,12 @@ struct classifier_baton_t {
|
|||||||
|
|
||||||
|
|
||||||
NAN_METHOD(CascadeClassifierWrap::DetectMultiScale){
|
NAN_METHOD(CascadeClassifierWrap::DetectMultiScale){
|
||||||
HandleScope scope;
|
NanScope();
|
||||||
|
|
||||||
CascadeClassifierWrap *self = ObjectWrap::Unwrap<CascadeClassifierWrap>(args.This());
|
CascadeClassifierWrap *self = ObjectWrap::Unwrap<CascadeClassifierWrap>(args.This());
|
||||||
|
|
||||||
if (args.Length() < 2){
|
if (args.Length() < 2){
|
||||||
v8::ThrowException(v8::Exception::TypeError(v8::String::New("detectMultiScale takes at least 2 args")));
|
NanThrowTypeError("detectMultiScale takes at least 2 args");
|
||||||
}
|
}
|
||||||
|
|
||||||
Matrix *im = ObjectWrap::Unwrap<Matrix>(args[0]->ToObject());
|
Matrix *im = ObjectWrap::Unwrap<Matrix>(args[0]->ToObject());
|
||||||
@ -91,7 +90,7 @@ NAN_METHOD(CascadeClassifierWrap::DetectMultiScale){
|
|||||||
minh = args[5]->IntegerValue();
|
minh = args[5]->IntegerValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*FIXME: convert async
|
||||||
classifier_baton_t *baton = new classifier_baton_t();
|
classifier_baton_t *baton = new classifier_baton_t();
|
||||||
baton->cc = self;
|
baton->cc = self;
|
||||||
baton->cb = Persistent<Function>::New(cb);
|
baton->cb = Persistent<Function>::New(cb);
|
||||||
@ -110,11 +109,11 @@ NAN_METHOD(CascadeClassifierWrap::DetectMultiScale){
|
|||||||
uv_queue_work(uv_default_loop(), &baton->request, AsyncDetectMultiScale, (uv_after_work_cb)AfterAsyncDetectMultiScale);
|
uv_queue_work(uv_default_loop(), &baton->request, AsyncDetectMultiScale, (uv_after_work_cb)AfterAsyncDetectMultiScale);
|
||||||
|
|
||||||
return Undefined();
|
return Undefined();
|
||||||
|
NanReturnUndefined();
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*FIXME: convert async
|
||||||
void AsyncDetectMultiScale(uv_work_t *req) {
|
void AsyncDetectMultiScale(uv_work_t *req) {
|
||||||
classifier_baton_t *baton = static_cast<classifier_baton_t *>(req->data);
|
classifier_baton_t *baton = static_cast<classifier_baton_t *>(req->data);
|
||||||
|
|
||||||
@ -138,7 +137,7 @@ void AsyncDetectMultiScale(uv_work_t *req) {
|
|||||||
|
|
||||||
void AfterAsyncDetectMultiScale(uv_work_t *req) {
|
void AfterAsyncDetectMultiScale(uv_work_t *req) {
|
||||||
|
|
||||||
HandleScope scope;
|
NanScope();
|
||||||
classifier_baton_t *baton = static_cast<classifier_baton_t *>(req->data);
|
classifier_baton_t *baton = static_cast<classifier_baton_t *>(req->data);
|
||||||
// ev_unref(EV_DEFAULT_UC);
|
// ev_unref(EV_DEFAULT_UC);
|
||||||
// baton->cc->Unref();
|
// baton->cc->Unref();
|
||||||
@ -175,4 +174,4 @@ void AfterAsyncDetectMultiScale(uv_work_t *req) {
|
|||||||
|
|
||||||
// return 0;
|
// return 0;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
#if CV_MAJOR_VERSION >= 2 && CV_MINOR_VERSION >=4
|
#if CV_MAJOR_VERSION >= 2 && CV_MINOR_VERSION >=4
|
||||||
|
|
||||||
#include "Matrix.h"
|
#include "Matrix.h"
|
||||||
|
#include <nan.h>
|
||||||
|
|
||||||
#define EIGEN 0
|
#define EIGEN 0
|
||||||
#define LBPH 1
|
#define LBPH 1
|
||||||
@ -13,7 +14,7 @@
|
|||||||
cv::Mat fromMatrixOrFilename(Local<Value> v){
|
cv::Mat fromMatrixOrFilename(Local<Value> v){
|
||||||
cv::Mat im;
|
cv::Mat im;
|
||||||
if (v->IsString()){
|
if (v->IsString()){
|
||||||
std::string filename = std::string(*v8::String::AsciiValue(v->ToString()));
|
std::string filename = std::string(*NanAsciiString(v->ToString()));
|
||||||
im = cv::imread(filename);
|
im = cv::imread(filename);
|
||||||
//std::cout<< im.size();
|
//std::cout<< im.size();
|
||||||
} else {
|
} else {
|
||||||
@ -31,30 +32,31 @@ Persistent<FunctionTemplate> FaceRecognizerWrap::constructor;
|
|||||||
|
|
||||||
void
|
void
|
||||||
FaceRecognizerWrap::Init(Handle<Object> target) {
|
FaceRecognizerWrap::Init(Handle<Object> target) {
|
||||||
HandleScope scope;
|
NanScope();
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
constructor = Persistent<FunctionTemplate>::New(FunctionTemplate::New(FaceRecognizerWrap::New));
|
Local<FunctionTemplate> ctor = NanNew<FunctionTemplate>(FaceRecognizerWrap::New);
|
||||||
constructor->InstanceTemplate()->SetInternalFieldCount(1);
|
NanAssignPersistent(constructor, ctor);
|
||||||
constructor->SetClassName(String::NewSymbol("FaceRecognizer"));
|
ctor->InstanceTemplate()->SetInternalFieldCount(1);
|
||||||
|
ctor->SetClassName(NanNew("FaceRecognizer"));
|
||||||
|
|
||||||
NODE_SET_METHOD(constructor, "createLBPHFaceRecognizer", CreateLBPH);
|
NODE_SET_METHOD(ctor, "createLBPHFaceRecognizer", CreateLBPH);
|
||||||
NODE_SET_METHOD(constructor, "createEigenFaceRecognizer", CreateEigen);
|
NODE_SET_METHOD(ctor, "createEigenFaceRecognizer", CreateEigen);
|
||||||
NODE_SET_METHOD(constructor, "createFisherFaceRecognizer", CreateFisher);
|
NODE_SET_METHOD(ctor, "createFisherFaceRecognizer", CreateFisher);
|
||||||
|
|
||||||
NODE_SET_PROTOTYPE_METHOD(constructor, "trainSync", TrainSync);
|
NODE_SET_PROTOTYPE_METHOD(ctor, "trainSync", TrainSync);
|
||||||
NODE_SET_PROTOTYPE_METHOD(constructor, "updateSync", UpdateSync);
|
NODE_SET_PROTOTYPE_METHOD(ctor, "updateSync", UpdateSync);
|
||||||
NODE_SET_PROTOTYPE_METHOD(constructor, "predictSync", PredictSync);
|
NODE_SET_PROTOTYPE_METHOD(ctor, "predictSync", PredictSync);
|
||||||
NODE_SET_PROTOTYPE_METHOD(constructor, "saveSync", SaveSync);
|
NODE_SET_PROTOTYPE_METHOD(ctor, "saveSync", SaveSync);
|
||||||
NODE_SET_PROTOTYPE_METHOD(constructor, "loadSync", LoadSync);
|
NODE_SET_PROTOTYPE_METHOD(ctor, "loadSync", LoadSync);
|
||||||
|
|
||||||
NODE_SET_PROTOTYPE_METHOD(constructor, "getMat", GetMat);
|
NODE_SET_PROTOTYPE_METHOD(ctor, "getMat", GetMat);
|
||||||
|
|
||||||
target->Set(String::NewSymbol("FaceRecognizer"), constructor->GetFunction());
|
target->Set(NanNew("FaceRecognizer"), ctor->GetFunction());
|
||||||
};
|
};
|
||||||
|
|
||||||
NAN_METHOD(FaceRecognizerWrap::New() {
|
NAN_METHOD(FaceRecognizerWrap::New) {
|
||||||
HandleScope scope;
|
NanScope();
|
||||||
|
|
||||||
if (args.This()->InternalFieldCount() == 0)
|
if (args.This()->InternalFieldCount() == 0)
|
||||||
JSTHROW_TYPE("Cannot Instantiate without new")
|
JSTHROW_TYPE("Cannot Instantiate without new")
|
||||||
@ -64,11 +66,11 @@ NAN_METHOD(FaceRecognizerWrap::New() {
|
|||||||
FaceRecognizerWrap *pt = new FaceRecognizerWrap(f, LBPH);
|
FaceRecognizerWrap *pt = new FaceRecognizerWrap(f, LBPH);
|
||||||
|
|
||||||
pt->Wrap(args.This());
|
pt->Wrap(args.This());
|
||||||
return args.This();
|
NanReturnValue(args.This());
|
||||||
}
|
}
|
||||||
|
|
||||||
NAN_METHOD(FaceRecognizerWrap::CreateLBPH() {
|
NAN_METHOD(FaceRecognizerWrap::CreateLBPH) {
|
||||||
HandleScope scope;
|
NanScope();
|
||||||
|
|
||||||
int radius = 1;
|
int radius = 1;
|
||||||
int neighbors = 8;
|
int neighbors = 8;
|
||||||
@ -82,7 +84,7 @@ NAN_METHOD(FaceRecognizerWrap::CreateLBPH() {
|
|||||||
INT_FROM_ARGS(grid_y, 3)
|
INT_FROM_ARGS(grid_y, 3)
|
||||||
DOUBLE_FROM_ARGS(threshold, 4)
|
DOUBLE_FROM_ARGS(threshold, 4)
|
||||||
|
|
||||||
Local<Object> n = FaceRecognizerWrap::constructor->GetFunction()->NewInstance();
|
Local<Object> n = NanNew(FaceRecognizerWrap::constructor)->GetFunction()->NewInstance();
|
||||||
|
|
||||||
cv::Ptr<cv::FaceRecognizer> f = cv::createLBPHFaceRecognizer(
|
cv::Ptr<cv::FaceRecognizer> f = cv::createLBPHFaceRecognizer(
|
||||||
radius, neighbors, grid_x, grid_y, threshold
|
radius, neighbors, grid_x, grid_y, threshold
|
||||||
@ -90,11 +92,11 @@ NAN_METHOD(FaceRecognizerWrap::CreateLBPH() {
|
|||||||
FaceRecognizerWrap *pt = new FaceRecognizerWrap(f, LBPH);
|
FaceRecognizerWrap *pt = new FaceRecognizerWrap(f, LBPH);
|
||||||
|
|
||||||
pt->Wrap(n);
|
pt->Wrap(n);
|
||||||
return n;
|
NanReturnValue( n );
|
||||||
}
|
}
|
||||||
|
|
||||||
NAN_METHOD(FaceRecognizerWrap::CreateEigen() {
|
NAN_METHOD(FaceRecognizerWrap::CreateEigen) {
|
||||||
HandleScope scope;
|
NanScope();
|
||||||
|
|
||||||
int components = 0;
|
int components = 0;
|
||||||
double threshold = DBL_MAX;
|
double threshold = DBL_MAX;
|
||||||
@ -102,7 +104,7 @@ NAN_METHOD(FaceRecognizerWrap::CreateEigen() {
|
|||||||
INT_FROM_ARGS(components, 0)
|
INT_FROM_ARGS(components, 0)
|
||||||
DOUBLE_FROM_ARGS(threshold, 1)
|
DOUBLE_FROM_ARGS(threshold, 1)
|
||||||
|
|
||||||
Local<Object> n = FaceRecognizerWrap::constructor->GetFunction()->NewInstance();
|
Local<Object> n = NanNew(FaceRecognizerWrap::constructor)->GetFunction()->NewInstance();
|
||||||
|
|
||||||
cv::Ptr<cv::FaceRecognizer> f = cv::createEigenFaceRecognizer(
|
cv::Ptr<cv::FaceRecognizer> f = cv::createEigenFaceRecognizer(
|
||||||
components, threshold
|
components, threshold
|
||||||
@ -110,11 +112,11 @@ NAN_METHOD(FaceRecognizerWrap::CreateEigen() {
|
|||||||
FaceRecognizerWrap *pt = new FaceRecognizerWrap(f, EIGEN);
|
FaceRecognizerWrap *pt = new FaceRecognizerWrap(f, EIGEN);
|
||||||
|
|
||||||
pt->Wrap(n);
|
pt->Wrap(n);
|
||||||
return n;
|
NanReturnValue( n );
|
||||||
}
|
}
|
||||||
|
|
||||||
NAN_METHOD(FaceRecognizerWrap::CreateFisher() {
|
NAN_METHOD(FaceRecognizerWrap::CreateFisher) {
|
||||||
HandleScope scope;
|
NanScope();
|
||||||
|
|
||||||
int components = 0;
|
int components = 0;
|
||||||
double threshold = DBL_MAX;
|
double threshold = DBL_MAX;
|
||||||
@ -122,7 +124,7 @@ NAN_METHOD(FaceRecognizerWrap::CreateFisher() {
|
|||||||
INT_FROM_ARGS(components, 0)
|
INT_FROM_ARGS(components, 0)
|
||||||
DOUBLE_FROM_ARGS(threshold, 1)
|
DOUBLE_FROM_ARGS(threshold, 1)
|
||||||
|
|
||||||
Local<Object> n = FaceRecognizerWrap::constructor->GetFunction()->NewInstance();
|
Local<Object> n = NanNew(FaceRecognizerWrap::constructor)->GetFunction()->NewInstance();
|
||||||
|
|
||||||
cv::Ptr<cv::FaceRecognizer> f = cv::createFisherFaceRecognizer(
|
cv::Ptr<cv::FaceRecognizer> f = cv::createFisherFaceRecognizer(
|
||||||
components, threshold
|
components, threshold
|
||||||
@ -130,7 +132,7 @@ NAN_METHOD(FaceRecognizerWrap::CreateFisher() {
|
|||||||
FaceRecognizerWrap *pt = new FaceRecognizerWrap(f, FISHER);
|
FaceRecognizerWrap *pt = new FaceRecognizerWrap(f, FISHER);
|
||||||
|
|
||||||
pt->Wrap(n);
|
pt->Wrap(n);
|
||||||
return n;
|
NanReturnValue( n );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -140,15 +142,20 @@ FaceRecognizerWrap::FaceRecognizerWrap(cv::Ptr<cv::FaceRecognizer> f, int type){
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Handle<Value> UnwrapTrainingData(const Arguments& args, cv::vector<cv::Mat>* images, cv::vector<int>* labels){
|
|
||||||
|
|
||||||
|
|
||||||
|
Handle<Value> UnwrapTrainingData(_NAN_METHOD_ARGS_TYPE args, cv::vector<cv::Mat>* images, cv::vector<int>* labels){
|
||||||
|
|
||||||
|
|
||||||
if (args.Length() < 1 || !args[0]->IsArray()){
|
if (args.Length() < 1 || !args[0]->IsArray()){
|
||||||
JSTHROW("FaceRecognizer.train takes a list of [<int> label, image] tuples")
|
JSTHROW("FaceRecognizer.train takes a list of [<int> label, image] tuples")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iterate through [[label, image], ...] etc, and add matrix / label to vectors
|
// Iterate through [[label, image], ...] etc, and add matrix / label to vectors
|
||||||
const Local<Array> tuples = v8::Array::Cast(*args[0]);
|
//const
|
||||||
|
//Local<Array> tuples = v8::Array::Cast(*args[0]);
|
||||||
|
const Local<Array> tuples = Local<Array>::Cast(args[0]);
|
||||||
|
|
||||||
const uint32_t length = tuples->Length();
|
const uint32_t length = tuples->Length();
|
||||||
for (uint32_t i=0 ; i<length ; ++i){
|
for (uint32_t i=0 ; i<length ; ++i){
|
||||||
const Local<Value> val = tuples->Get(i);
|
const Local<Value> val = tuples->Get(i);
|
||||||
@ -157,7 +164,7 @@ Handle<Value> UnwrapTrainingData(const Arguments& args, cv::vector<cv::Mat>* ima
|
|||||||
JSTHROW("train takes a list of [label, image] tuples")
|
JSTHROW("train takes a list of [label, image] tuples")
|
||||||
}
|
}
|
||||||
|
|
||||||
Local<Array> valarr = v8::Array::Cast(*val);
|
Local<Array> valarr = Local<Array>::Cast(val);
|
||||||
|
|
||||||
if (valarr->Length() != 2 || !valarr->Get(0)->IsInt32()){
|
if (valarr->Length() != 2 || !valarr->Get(0)->IsInt32()){
|
||||||
JSTHROW("train takes a list of [label, image] tuples")
|
JSTHROW("train takes a list of [label, image] tuples")
|
||||||
@ -170,10 +177,11 @@ Handle<Value> UnwrapTrainingData(const Arguments& args, cv::vector<cv::Mat>* ima
|
|||||||
labels->push_back(label);
|
labels->push_back(label);
|
||||||
images->push_back(im);
|
images->push_back(im);
|
||||||
}
|
}
|
||||||
return v8::Undefined();
|
return NanUndefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
NAN_METHOD(FaceRecognizerWrap::TrainSync(const Arguments& args){
|
|
||||||
|
NAN_METHOD(FaceRecognizerWrap::TrainSync){
|
||||||
SETUP_FUNCTION(FaceRecognizerWrap)
|
SETUP_FUNCTION(FaceRecognizerWrap)
|
||||||
|
|
||||||
cv::vector<cv::Mat> images;
|
cv::vector<cv::Mat> images;
|
||||||
@ -181,15 +189,15 @@ NAN_METHOD(FaceRecognizerWrap::TrainSync(const Arguments& args){
|
|||||||
|
|
||||||
Handle<Value> exception = UnwrapTrainingData(args, &images, &labels);
|
Handle<Value> exception = UnwrapTrainingData(args, &images, &labels);
|
||||||
if (!exception->IsUndefined()){
|
if (!exception->IsUndefined()){
|
||||||
return exception;
|
NanReturnValue(exception);//FIXME: not too sure about returning exceptions like this
|
||||||
}
|
}
|
||||||
|
|
||||||
self->rec->train(images, labels);
|
self->rec->train(images, labels);
|
||||||
|
|
||||||
return scope.Close(v8::Undefined());
|
NanReturnUndefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
NAN_METHOD(FaceRecognizerWrap::UpdateSync(const Arguments& args){
|
NAN_METHOD(FaceRecognizerWrap::UpdateSync){
|
||||||
SETUP_FUNCTION(FaceRecognizerWrap)
|
SETUP_FUNCTION(FaceRecognizerWrap)
|
||||||
|
|
||||||
|
|
||||||
@ -206,16 +214,16 @@ NAN_METHOD(FaceRecognizerWrap::UpdateSync(const Arguments& args){
|
|||||||
|
|
||||||
Handle<Value> exception = UnwrapTrainingData(args, &images, &labels);
|
Handle<Value> exception = UnwrapTrainingData(args, &images, &labels);
|
||||||
if (!exception->IsUndefined()){
|
if (!exception->IsUndefined()){
|
||||||
return exception;
|
JSTHROW( exception );
|
||||||
}
|
}
|
||||||
|
|
||||||
self->rec->update(images, labels);
|
self->rec->update(images, labels);
|
||||||
|
|
||||||
return scope.Close(v8::Undefined());
|
NanReturnUndefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NAN_METHOD(FaceRecognizerWrap::PredictSync(const Arguments& args){
|
NAN_METHOD(FaceRecognizerWrap::PredictSync){
|
||||||
SETUP_FUNCTION(FaceRecognizerWrap)
|
SETUP_FUNCTION(FaceRecognizerWrap)
|
||||||
|
|
||||||
cv::Mat im = fromMatrixOrFilename(args[0]);//TODO CHECK!
|
cv::Mat im = fromMatrixOrFilename(args[0]);//TODO CHECK!
|
||||||
@ -226,47 +234,47 @@ NAN_METHOD(FaceRecognizerWrap::PredictSync(const Arguments& args){
|
|||||||
double confidence = 0.0;
|
double confidence = 0.0;
|
||||||
self->rec->predict(im, predictedLabel, confidence);
|
self->rec->predict(im, predictedLabel, confidence);
|
||||||
|
|
||||||
v8::Local<v8::Object> res = v8::Object::New();
|
v8::Local<v8::Object> res = NanNew<Object>();
|
||||||
res->Set(v8::String::New("id"), v8::Number::New(predictedLabel));
|
res->Set(NanNew("id"), NanNew<Number>(predictedLabel));
|
||||||
res->Set(v8::String::New("confidence"), v8::Number::New(confidence));
|
res->Set(NanNew("confidence"), NanNew<Number>(confidence));
|
||||||
|
|
||||||
return scope.Close(res);
|
NanReturnValue(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NAN_METHOD(FaceRecognizerWrap::SaveSync(const Arguments& args){
|
NAN_METHOD(FaceRecognizerWrap::SaveSync){
|
||||||
SETUP_FUNCTION(FaceRecognizerWrap)
|
SETUP_FUNCTION(FaceRecognizerWrap)
|
||||||
if (!args[0]->IsString()){
|
if (!args[0]->IsString()){
|
||||||
JSTHROW("Save takes a filename")
|
JSTHROW("Save takes a filename")
|
||||||
}
|
}
|
||||||
std::string filename = std::string(*v8::String::AsciiValue(args[0]->ToString()));
|
std::string filename = std::string(*NanAsciiString(args[0]->ToString()));
|
||||||
self->rec->save(filename);
|
self->rec->save(filename);
|
||||||
return v8::Undefined();
|
NanReturnUndefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
NAN_METHOD(FaceRecognizerWrap::LoadSync(const Arguments& args){
|
NAN_METHOD(FaceRecognizerWrap::LoadSync){
|
||||||
SETUP_FUNCTION(FaceRecognizerWrap)
|
SETUP_FUNCTION(FaceRecognizerWrap)
|
||||||
if (!args[0]->IsString()){
|
if (!args[0]->IsString()){
|
||||||
JSTHROW("Load takes a filename")
|
JSTHROW("Load takes a filename")
|
||||||
}
|
}
|
||||||
std::string filename = std::string(*v8::String::AsciiValue(args[0]->ToString()));
|
std::string filename = std::string(*NanAsciiString(args[0]->ToString()));
|
||||||
self->rec->load(filename);
|
self->rec->load(filename);
|
||||||
return v8::Undefined();
|
NanReturnUndefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
NAN_METHOD(FaceRecognizerWrap::GetMat(const Arguments& args){
|
NAN_METHOD(FaceRecognizerWrap::GetMat){
|
||||||
SETUP_FUNCTION(FaceRecognizerWrap)
|
SETUP_FUNCTION(FaceRecognizerWrap)
|
||||||
if (!args[0]->IsString()){
|
if (!args[0]->IsString()){
|
||||||
JSTHROW("getMat takes a key")
|
JSTHROW("getMat takes a key")
|
||||||
}
|
}
|
||||||
std::string key = std::string(*v8::String::AsciiValue(args[0]->ToString()));
|
std::string key = std::string(*NanAsciiString(args[0]->ToString()));
|
||||||
cv::Mat m = self->rec->getMat(key);
|
cv::Mat m = self->rec->getMat(key);
|
||||||
|
|
||||||
Local<Object> im = Matrix::constructor->GetFunction()->NewInstance();
|
Local<Object> im = NanNew(Matrix::constructor)->GetFunction()->NewInstance();
|
||||||
Matrix *img = ObjectWrap::Unwrap<Matrix>(im);
|
Matrix *img = ObjectWrap::Unwrap<Matrix>(im);
|
||||||
img->mat = m;
|
img->mat = m;
|
||||||
|
|
||||||
return im;
|
NanReturnValue( im );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -7,25 +7,27 @@ Persistent<FunctionTemplate> NamedWindow::constructor;
|
|||||||
|
|
||||||
void
|
void
|
||||||
NamedWindow::Init(Handle<Object> target) {
|
NamedWindow::Init(Handle<Object> target) {
|
||||||
HandleScope scope;
|
NanScope();
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
constructor = Persistent<FunctionTemplate>::New(FunctionTemplate::New(NamedWindow::New));
|
Local<FunctionTemplate> ctor = NanNew<FunctionTemplate>(NamedWindow::New);
|
||||||
constructor->InstanceTemplate()->SetInternalFieldCount(1);
|
NanAssignPersistent(constructor, ctor);
|
||||||
constructor->SetClassName(String::NewSymbol("NamedWindow"));
|
ctor->InstanceTemplate()->SetInternalFieldCount(1);
|
||||||
|
ctor->SetClassName(NanNew("NamedWindow"));
|
||||||
|
|
||||||
// Prototype
|
// Prototype
|
||||||
//Local<ObjectTemplate> proto = constructor->PrototypeTemplate();
|
//Local<ObjectTemplate> proto = constructor->PrototypeTemplate();
|
||||||
|
|
||||||
NODE_SET_PROTOTYPE_METHOD(constructor, "show", Show);
|
NODE_SET_PROTOTYPE_METHOD(ctor, "show", Show);
|
||||||
NODE_SET_PROTOTYPE_METHOD(constructor, "destroy", Destroy);
|
NODE_SET_PROTOTYPE_METHOD(ctor, "destroy", Destroy);
|
||||||
NODE_SET_PROTOTYPE_METHOD(constructor, "blockingWaitKey", BlockingWaitKey);
|
NODE_SET_PROTOTYPE_METHOD(ctor, "blockingWaitKey", BlockingWaitKey);
|
||||||
target->Set(String::NewSymbol("NamedWindow"), constructor->GetFunction());
|
|
||||||
|
target->Set(NanNew("NamedWindow"), ctor->GetFunction());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
NAN_METHOD(NamedWindow::New() {
|
NAN_METHOD(NamedWindow::New) {
|
||||||
HandleScope scope;
|
NanScope();
|
||||||
|
|
||||||
if (args.This()->InternalFieldCount() == 0){
|
if (args.This()->InternalFieldCount() == 0){
|
||||||
JSTHROW_TYPE("Cannot Instantiate without new")
|
JSTHROW_TYPE("Cannot Instantiate without new")
|
||||||
@ -33,13 +35,13 @@ NAN_METHOD(NamedWindow::New() {
|
|||||||
|
|
||||||
NamedWindow* win;
|
NamedWindow* win;
|
||||||
if (args.Length() == 1){
|
if (args.Length() == 1){
|
||||||
win = new NamedWindow(std::string(*v8::String::AsciiValue(args[0]->ToString())), 0);
|
win = new NamedWindow(std::string(*NanAsciiString(args[0]->ToString())), 0);
|
||||||
} else if (args.Length() == 2){
|
} else if (args.Length() == 2){
|
||||||
win = new NamedWindow(std::string(*v8::String::AsciiValue(args[0]->ToString())), 0);
|
win = new NamedWindow(std::string(*NanAsciiString(args[0]->ToString())), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
win->Wrap(args.Holder());
|
win->Wrap(args.Holder());
|
||||||
return scope.Close(args.Holder());
|
NanReturnValue(args.Holder());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -50,23 +52,23 @@ NamedWindow::NamedWindow(const std::string& name, int f){
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NAN_METHOD(NamedWindow::Show(const v8::Arguments& args){
|
NAN_METHOD(NamedWindow::Show){
|
||||||
SETUP_FUNCTION(NamedWindow)
|
SETUP_FUNCTION(NamedWindow)
|
||||||
Matrix *im = ObjectWrap::Unwrap<Matrix>(args[0]->ToObject());
|
Matrix *im = ObjectWrap::Unwrap<Matrix>(args[0]->ToObject());
|
||||||
cv::imshow(self->winname, im->mat);
|
cv::imshow(self->winname, im->mat);
|
||||||
|
|
||||||
return scope.Close(args.Holder());
|
NanReturnValue(args.Holder());
|
||||||
}
|
}
|
||||||
|
|
||||||
NAN_METHOD(NamedWindow::Destroy(const v8::Arguments& args){
|
NAN_METHOD(NamedWindow::Destroy){
|
||||||
SETUP_FUNCTION(NamedWindow)
|
SETUP_FUNCTION(NamedWindow)
|
||||||
cv::destroyWindow(self->winname);
|
cv::destroyWindow(self->winname);
|
||||||
return scope.Close(args.Holder());
|
NanReturnValue(args.Holder());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NAN_METHOD(NamedWindow::BlockingWaitKey(const v8::Arguments& args){
|
NAN_METHOD(NamedWindow::BlockingWaitKey){
|
||||||
HandleScope scope;
|
NanScope();
|
||||||
//SETUP_FUNCTION(NamedWindow)
|
//SETUP_FUNCTION(NamedWindow)
|
||||||
int time = 0;
|
int time = 0;
|
||||||
|
|
||||||
@ -80,5 +82,5 @@ NAN_METHOD(NamedWindow::BlockingWaitKey(const v8::Arguments& args){
|
|||||||
|
|
||||||
int res = cv::waitKey(time);
|
int res = cv::waitKey(time);
|
||||||
|
|
||||||
return scope.Close(Number::New(res));
|
NanReturnValue(NanNew<Number>(res));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -109,8 +109,6 @@ Matrix::Init(Handle<Object> target) {
|
|||||||
NODE_SET_PROTOTYPE_METHOD(ctor, "meanWithMask", MeanWithMask);
|
NODE_SET_PROTOTYPE_METHOD(ctor, "meanWithMask", MeanWithMask);
|
||||||
NODE_SET_PROTOTYPE_METHOD(ctor, "shift", Shift);
|
NODE_SET_PROTOTYPE_METHOD(ctor, "shift", Shift);
|
||||||
|
|
||||||
//target->Set(NanNew<String>("Matrix"), m->GetFunction());
|
|
||||||
//target->Set( NanNew<String>("Matrix"), ctor->GetFunction() );
|
|
||||||
target->Set(NanNew("Matrix"), ctor->GetFunction());
|
target->Set(NanNew("Matrix"), ctor->GetFunction());
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -438,7 +436,7 @@ NAN_METHOD(Matrix::ToBuffer){
|
|||||||
NanReturnValue(actualBuffer);
|
NanReturnValue(actualBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*FIXME: look into this
|
/*FIXME: async look into this
|
||||||
struct matrixToBuffer_baton_t {
|
struct matrixToBuffer_baton_t {
|
||||||
Matrix *mm;
|
Matrix *mm;
|
||||||
Persistent<Function> cb;
|
Persistent<Function> cb;
|
||||||
|
|||||||
55
src/Point.cc
55
src/Point.cc
@ -6,61 +6,72 @@ v8::Persistent<FunctionTemplate> Point::constructor;
|
|||||||
|
|
||||||
void
|
void
|
||||||
Point::Init(Handle<Object> target) {
|
Point::Init(Handle<Object> target) {
|
||||||
HandleScope scope;
|
NanScope();
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
constructor = Persistent<FunctionTemplate>::New(FunctionTemplate::New(Point::New));
|
/*constructor = Persistent<FunctionTemplate>::New(FunctionTemplate::New(Point::New));
|
||||||
constructor->InstanceTemplate()->SetInternalFieldCount(1);
|
constructor->InstanceTemplate()->SetInternalFieldCount(1);
|
||||||
constructor->SetClassName(String::NewSymbol("Point"));
|
constructor->SetClassName(String::NewSymbol("Point"));
|
||||||
|
|
||||||
// Prototype
|
// Prototype
|
||||||
Local<ObjectTemplate> proto = constructor->PrototypeTemplate();
|
Local<ObjectTemplate> proto = constructor->PrototypeTemplate();
|
||||||
proto->SetAccessor(String::NewSymbol("x"), GetX, RaiseImmutable);
|
proto->SetAccessor(String::NewSymbol("x"), GetX, RaiseImmutable);
|
||||||
proto->SetAccessor(String::NewSymbol("y"), GetY, RaiseImmutable);
|
proto->SetAccessor(String::NewSymbol("y"), GetY, RaiseImmutable);*/
|
||||||
|
|
||||||
NODE_SET_PROTOTYPE_METHOD(constructor, "dot", Dot);
|
Local<FunctionTemplate> ctor = NanNew<FunctionTemplate>(Point::New);
|
||||||
|
NanAssignPersistent(constructor, ctor);
|
||||||
|
ctor->InstanceTemplate()->SetInternalFieldCount(1);
|
||||||
|
ctor->SetClassName(NanNew("Point"));
|
||||||
|
|
||||||
|
Local<ObjectTemplate> proto = ctor->PrototypeTemplate();
|
||||||
|
proto->SetAccessor(NanNew("x"), GetX);//, RaiseImmutable);
|
||||||
|
proto->SetAccessor(NanNew("y"), GetY);//, RaiseImmutable);
|
||||||
|
|
||||||
|
|
||||||
|
NODE_SET_PROTOTYPE_METHOD(ctor, "dot", Dot);
|
||||||
|
|
||||||
target->Set(String::NewSymbol("Point"), constructor->GetFunction());
|
target->Set(NanNew("Point"), ctor->GetFunction());
|
||||||
};
|
};
|
||||||
|
|
||||||
NAN_METHOD(Point::New() {
|
NAN_METHOD(Point::New) {
|
||||||
HandleScope scope;
|
NanScope();
|
||||||
|
|
||||||
if (args.This()->InternalFieldCount() == 0)
|
if (args.This()->InternalFieldCount() == 0)
|
||||||
return v8::ThrowException(v8::Exception::TypeError(v8::String::New("Cannot Instantiate without new")));
|
return NanThrowTypeError("Cannot Instantiate without new");
|
||||||
|
|
||||||
double x = 0, y = 0;
|
double x = 0, y = 0;
|
||||||
if (args[0]->IsNumber()) x = args[0]->NumberValue();
|
if (args[0]->IsNumber()) x = args[0]->NumberValue();
|
||||||
if (args[1]->IsNumber()) y = args[1]->NumberValue();
|
if (args[1]->IsNumber()) y = args[1]->NumberValue();
|
||||||
Point *pt = new Point(x, y);
|
Point *pt = new Point(x, y);
|
||||||
pt->Wrap(args.This());
|
pt->Wrap(args.This());
|
||||||
return args.This();
|
NanReturnValue(args.This());
|
||||||
}
|
}
|
||||||
|
|
||||||
NAN_METHOD(Point::GetX(Local<String> prop, const AccessorInfo &info) {
|
NAN_GETTER(Point::GetX){ //(Local<String> prop, const AccessorInfo &info) {
|
||||||
HandleScope scope;
|
NanScope();
|
||||||
Point *pt = ObjectWrap::Unwrap<Point>(info.This());
|
Point *pt = ObjectWrap::Unwrap<Point>(args.This());
|
||||||
return scope.Close(Number::New(pt->point.x));
|
NanReturnValue(NanNew<Number>(pt->point.x));
|
||||||
}
|
}
|
||||||
|
|
||||||
NAN_METHOD(Point::GetY(Local<String> prop, const AccessorInfo &info) {
|
NAN_GETTER(Point::GetY){//(Local<String> prop, const AccessorInfo &info) {
|
||||||
HandleScope scope;
|
NanScope();
|
||||||
Point *pt = ObjectWrap::Unwrap<Point>(info.This());
|
Point *pt = ObjectWrap::Unwrap<Point>(args.This());
|
||||||
return scope.Close(Number::New(pt->point.y));
|
NanReturnValue(NanNew<Number>(pt->point.y));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*FIXME: add this back, possibly in a setter
|
||||||
void
|
void
|
||||||
Point::RaiseImmutable(Local<String> property, Local<Value> value, const AccessorInfo& info) {
|
Point::RaiseImmutable(Local<String> property, Local<Value> value, const AccessorInfo& info) {
|
||||||
v8::ThrowException(v8::Exception::TypeError(v8::String::New("Point is immutable")));
|
NanThrowTypeError("Point is immutable");
|
||||||
}
|
} */
|
||||||
|
|
||||||
NAN_METHOD(Point::Dot(const v8::Arguments& args){
|
NAN_METHOD(Point::Dot){
|
||||||
HandleScope scope;
|
NanScope();
|
||||||
Point *p1 = ObjectWrap::Unwrap<Point>(args.This());
|
Point *p1 = ObjectWrap::Unwrap<Point>(args.This());
|
||||||
Point *p2 = ObjectWrap::Unwrap<Point>(args[0]->ToObject());
|
Point *p2 = ObjectWrap::Unwrap<Point>(args[0]->ToObject());
|
||||||
|
|
||||||
// Since V 2.3 Native Dot no longer supported
|
// Since V 2.3 Native Dot no longer supported
|
||||||
return scope.Close(Number::New(p1->point.x * p2->point.x + p1->point.y * p2->point.y));
|
NanReturnValue(NanNew<Number>(p1->point.x * p2->point.x + p1->point.y * p2->point.y));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -23,31 +23,32 @@ struct videocapture_baton {
|
|||||||
|
|
||||||
void
|
void
|
||||||
VideoCaptureWrap::Init(Handle<Object> target) {
|
VideoCaptureWrap::Init(Handle<Object> target) {
|
||||||
HandleScope scope;
|
NanScope();
|
||||||
|
|
||||||
// Constructor
|
|
||||||
constructor = Persistent<FunctionTemplate>::New(FunctionTemplate::New(VideoCaptureWrap::New));
|
|
||||||
constructor->InstanceTemplate()->SetInternalFieldCount(1);
|
|
||||||
constructor->SetClassName(String::NewSymbol("VideoCapture"));
|
|
||||||
|
|
||||||
// Prototype
|
// Prototype
|
||||||
//Local<ObjectTemplate> proto = constructor->PrototypeTemplate();
|
//Local<ObjectTemplate> proto = constructor->PrototypeTemplate();
|
||||||
|
|
||||||
|
//Class
|
||||||
|
Local<FunctionTemplate> ctor = NanNew<FunctionTemplate>(VideoCaptureWrap::New);
|
||||||
|
NanAssignPersistent(constructor, ctor);
|
||||||
|
ctor->InstanceTemplate()->SetInternalFieldCount(1);
|
||||||
|
ctor->SetClassName(NanNew("VideoCapture"));
|
||||||
|
|
||||||
NODE_SET_PROTOTYPE_METHOD(constructor, "read", Read);
|
NODE_SET_PROTOTYPE_METHOD(ctor, "read", Read);
|
||||||
NODE_SET_PROTOTYPE_METHOD(constructor, "setWidth", SetWidth);
|
NODE_SET_PROTOTYPE_METHOD(ctor, "setWidth", SetWidth);
|
||||||
NODE_SET_PROTOTYPE_METHOD(constructor, "setHeight", SetHeight);
|
NODE_SET_PROTOTYPE_METHOD(ctor, "setHeight", SetHeight);
|
||||||
NODE_SET_PROTOTYPE_METHOD(constructor, "setPosition", SetPosition);
|
NODE_SET_PROTOTYPE_METHOD(ctor, "setPosition", SetPosition);
|
||||||
NODE_SET_PROTOTYPE_METHOD(constructor, "close", Close);
|
NODE_SET_PROTOTYPE_METHOD(ctor, "close", Close);
|
||||||
NODE_SET_PROTOTYPE_METHOD(constructor, "ReadSync", ReadSync);
|
NODE_SET_PROTOTYPE_METHOD(ctor, "ReadSync", ReadSync);
|
||||||
|
|
||||||
target->Set(String::NewSymbol("VideoCapture"), constructor->GetFunction());
|
target->Set(NanNew("VideoCapture"), ctor->GetFunction());
|
||||||
};
|
};
|
||||||
|
|
||||||
NAN_METHOD(VideoCaptureWrap::New() {
|
NAN_METHOD(VideoCaptureWrap::New) {
|
||||||
HandleScope scope;
|
NanScope();
|
||||||
|
|
||||||
if (args.This()->InternalFieldCount() == 0)
|
if (args.This()->InternalFieldCount() == 0)
|
||||||
return v8::ThrowException(v8::Exception::TypeError(v8::String::New("Cannot Instantiate without new")));
|
return NanThrowTypeError("Cannot Instantiate without new");
|
||||||
|
|
||||||
VideoCaptureWrap *v;
|
VideoCaptureWrap *v;
|
||||||
|
|
||||||
@ -55,94 +56,95 @@ NAN_METHOD(VideoCaptureWrap::New() {
|
|||||||
v = new VideoCaptureWrap(args[0]->NumberValue());
|
v = new VideoCaptureWrap(args[0]->NumberValue());
|
||||||
} else {
|
} else {
|
||||||
//TODO - assumes that we have string, verify
|
//TODO - assumes that we have string, verify
|
||||||
v = new VideoCaptureWrap(std::string(*v8::String::AsciiValue(args[0]->ToString())));
|
v = new VideoCaptureWrap(std::string(*NanAsciiString(args[0]->ToString())));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
v->Wrap(args.This());
|
v->Wrap(args.This());
|
||||||
|
|
||||||
return args.This();
|
NanReturnValue(args.This());
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoCaptureWrap::VideoCaptureWrap(int device){
|
VideoCaptureWrap::VideoCaptureWrap(int device){
|
||||||
|
|
||||||
HandleScope scope;
|
NanScope();
|
||||||
cap.open(device);
|
cap.open(device);
|
||||||
|
|
||||||
if(!cap.isOpened()){
|
if(!cap.isOpened()){
|
||||||
v8::ThrowException(v8::Exception::Error(String::New("Camera could not be opened")));
|
NanThrowError("Camera could not be opened");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoCaptureWrap::VideoCaptureWrap(const std::string& filename){
|
VideoCaptureWrap::VideoCaptureWrap(const std::string& filename){
|
||||||
HandleScope scope;
|
NanScope();
|
||||||
cap.open(filename);
|
cap.open(filename);
|
||||||
// TODO! At the moment this only takes a full path - do relative too.
|
// TODO! At the moment this only takes a full path - do relative too.
|
||||||
if(!cap.isOpened()){
|
if(!cap.isOpened()){
|
||||||
v8::ThrowException(v8::Exception::Error(String::New("Video file could not be opened (opencv reqs. non relative paths)")));
|
NanThrowError("Video file could not be opened (opencv reqs. non relative paths)");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NAN_METHOD(VideoCaptureWrap::SetWidth(){
|
NAN_METHOD(VideoCaptureWrap::SetWidth){
|
||||||
|
|
||||||
HandleScope scope;
|
NanScope();
|
||||||
VideoCaptureWrap *v = ObjectWrap::Unwrap<VideoCaptureWrap>(args.This());
|
VideoCaptureWrap *v = ObjectWrap::Unwrap<VideoCaptureWrap>(args.This());
|
||||||
|
|
||||||
if(args.Length() != 1)
|
if(args.Length() != 1)
|
||||||
return scope.Close(Undefined());
|
NanReturnUndefined();
|
||||||
|
|
||||||
int w = args[0]->IntegerValue();
|
int w = args[0]->IntegerValue();
|
||||||
|
|
||||||
if(v->cap.isOpened())
|
if(v->cap.isOpened())
|
||||||
v->cap.set(CV_CAP_PROP_FRAME_WIDTH, w);
|
v->cap.set(CV_CAP_PROP_FRAME_WIDTH, w);
|
||||||
|
|
||||||
return scope.Close(Undefined());
|
NanReturnUndefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
NAN_METHOD(VideoCaptureWrap::SetHeight(){
|
NAN_METHOD(VideoCaptureWrap::SetHeight){
|
||||||
|
|
||||||
HandleScope scope;
|
NanScope();
|
||||||
VideoCaptureWrap *v = ObjectWrap::Unwrap<VideoCaptureWrap>(args.This());
|
VideoCaptureWrap *v = ObjectWrap::Unwrap<VideoCaptureWrap>(args.This());
|
||||||
|
|
||||||
if(args.Length() != 1)
|
if(args.Length() != 1)
|
||||||
return scope.Close(Undefined());
|
NanReturnUndefined();
|
||||||
|
|
||||||
int h = args[0]->IntegerValue();
|
int h = args[0]->IntegerValue();
|
||||||
|
|
||||||
v->cap.set(CV_CAP_PROP_FRAME_HEIGHT, h);
|
v->cap.set(CV_CAP_PROP_FRAME_HEIGHT, h);
|
||||||
|
|
||||||
return Undefined();
|
NanReturnUndefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
NAN_METHOD(VideoCaptureWrap::SetPosition(){
|
NAN_METHOD(VideoCaptureWrap::SetPosition){
|
||||||
|
|
||||||
HandleScope scope;
|
NanScope();
|
||||||
VideoCaptureWrap *v = ObjectWrap::Unwrap<VideoCaptureWrap>(args.This());
|
VideoCaptureWrap *v = ObjectWrap::Unwrap<VideoCaptureWrap>(args.This());
|
||||||
|
|
||||||
if(args.Length() != 1)
|
if(args.Length() != 1)
|
||||||
return scope.Close(Undefined());
|
NanReturnUndefined();
|
||||||
|
|
||||||
int pos = args[0]->IntegerValue();
|
int pos = args[0]->IntegerValue();
|
||||||
|
|
||||||
v->cap.set(CV_CAP_PROP_POS_FRAMES, pos);
|
v->cap.set(CV_CAP_PROP_POS_FRAMES, pos);
|
||||||
|
|
||||||
return Undefined();
|
NanReturnUndefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
NAN_METHOD(VideoCaptureWrap::Close(){
|
NAN_METHOD(VideoCaptureWrap::Close){
|
||||||
|
|
||||||
HandleScope scope;
|
NanScope();
|
||||||
VideoCaptureWrap *v = ObjectWrap::Unwrap<VideoCaptureWrap>(args.This());
|
VideoCaptureWrap *v = ObjectWrap::Unwrap<VideoCaptureWrap>(args.This());
|
||||||
|
|
||||||
v->cap.release();
|
v->cap.release();
|
||||||
|
|
||||||
return Undefined();
|
NanReturnUndefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
NAN_METHOD(VideoCaptureWrap::Read() {
|
/*FIXME: migrate async method
|
||||||
|
NAN_METHOD(VideoCaptureWrap::Read) {
|
||||||
|
|
||||||
HandleScope scope;
|
NanScope();
|
||||||
VideoCaptureWrap *v = ObjectWrap::Unwrap<VideoCaptureWrap>(args.This());
|
VideoCaptureWrap *v = ObjectWrap::Unwrap<VideoCaptureWrap>(args.This());
|
||||||
|
|
||||||
REQ_FUN_ARG(0, cb);
|
REQ_FUN_ARG(0, cb);
|
||||||
@ -154,10 +156,12 @@ NAN_METHOD(VideoCaptureWrap::Read() {
|
|||||||
baton->request.data = baton;
|
baton->request.data = baton;
|
||||||
|
|
||||||
uv_queue_work(uv_default_loop(), &baton->request, AsyncRead, (uv_after_work_cb)AfterAsyncRead);
|
uv_queue_work(uv_default_loop(), &baton->request, AsyncRead, (uv_after_work_cb)AfterAsyncRead);
|
||||||
return Undefined();
|
|
||||||
|
NanReturnUndefined();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void AsyncRead(uv_work_t *req) {
|
void AsyncRead(uv_work_t *req) {
|
||||||
videocapture_baton *baton = static_cast<videocapture_baton *>(req->data);
|
videocapture_baton *baton = static_cast<videocapture_baton *>(req->data);
|
||||||
|
|
||||||
@ -167,7 +171,7 @@ void AsyncRead(uv_work_t *req) {
|
|||||||
|
|
||||||
void AfterAsyncRead(uv_work_t *req) {
|
void AfterAsyncRead(uv_work_t *req) {
|
||||||
|
|
||||||
HandleScope scope;
|
NanScope();
|
||||||
|
|
||||||
videocapture_baton *baton = static_cast<videocapture_baton *>(req->data);
|
videocapture_baton *baton = static_cast<videocapture_baton *>(req->data);
|
||||||
|
|
||||||
@ -188,19 +192,19 @@ void AfterAsyncRead(uv_work_t *req) {
|
|||||||
delete baton;
|
delete baton;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
NAN_METHOD(VideoCaptureWrap::ReadSync) {
|
||||||
|
|
||||||
NAN_METHOD(VideoCaptureWrap::ReadSync() {
|
NanScope();
|
||||||
|
|
||||||
HandleScope scope;
|
|
||||||
VideoCaptureWrap *v = ObjectWrap::Unwrap<VideoCaptureWrap>(args.This());
|
VideoCaptureWrap *v = ObjectWrap::Unwrap<VideoCaptureWrap>(args.This());
|
||||||
|
|
||||||
Local<Object> im_to_return= Matrix::constructor->GetFunction()->NewInstance();
|
Local<Object> im_to_return= NanNew(Matrix::constructor)->GetFunction()->NewInstance();
|
||||||
Matrix *img = ObjectWrap::Unwrap<Matrix>(im_to_return);
|
Matrix *img = ObjectWrap::Unwrap<Matrix>(im_to_return);
|
||||||
|
|
||||||
v->cap.read(img->mat);
|
v->cap.read(img->mat);
|
||||||
|
|
||||||
return scope.Close(im_to_return);
|
NanReturnValue(im_to_return);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
11
src/init.cc
11
src/init.cc
@ -1,20 +1,21 @@
|
|||||||
#include "OpenCV.h"
|
#include "OpenCV.h"
|
||||||
/*#include "Point.h"
|
|
||||||
|
#include "Point.h"
|
||||||
#include "Matrix.h"
|
#include "Matrix.h"
|
||||||
#include "CascadeClassifierWrap.h"
|
#include "CascadeClassifierWrap.h"
|
||||||
#include "VideoCaptureWrap.h"
|
#include "VideoCaptureWrap.h"
|
||||||
#include "Contours.h"
|
#include "Contours.h"
|
||||||
#include "CamShift.h"
|
#include "CamShift.h"
|
||||||
#include "HighGUI.h"
|
#include "HighGUI.h"
|
||||||
#include "FaceRecognizer.h"*/
|
#include "FaceRecognizer.h"
|
||||||
|
|
||||||
|
|
||||||
extern "C" void
|
extern "C" void
|
||||||
init(Handle<Object> target) {
|
init(Handle<Object> target) {
|
||||||
//HandleScope scope;
|
|
||||||
NanScope();
|
NanScope();
|
||||||
OpenCV::Init(target);
|
OpenCV::Init(target);
|
||||||
/*Point::Init(target);
|
|
||||||
|
Point::Init(target);
|
||||||
Matrix::Init(target);
|
Matrix::Init(target);
|
||||||
CascadeClassifierWrap::Init(target);
|
CascadeClassifierWrap::Init(target);
|
||||||
VideoCaptureWrap::Init(target);
|
VideoCaptureWrap::Init(target);
|
||||||
@ -24,7 +25,7 @@ init(Handle<Object> target) {
|
|||||||
|
|
||||||
#if CV_MAJOR_VERSION >= 2 && CV_MINOR_VERSION >=4
|
#if CV_MAJOR_VERSION >= 2 && CV_MINOR_VERSION >=4
|
||||||
FaceRecognizerWrap::Init(target);
|
FaceRecognizerWrap::Init(target);
|
||||||
#endif*/
|
#endif
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user