node-opencv/src/CascadeClassifierWrap.cc
2013-03-19 16:53:50 -07:00

184 lines
4.5 KiB
C++
Executable File

#include "CascadeClassifierWrap.h"
#include "OpenCV.h"
#include "Matrix.h"
void AsyncDetectMultiScale(uv_work_t *req);
void AfterAsyncDetectMultiScale(uv_work_t *req);
Persistent<FunctionTemplate> CascadeClassifierWrap::constructor;
void
CascadeClassifierWrap::Init(Handle<Object> target) {
HandleScope scope;
// Constructor
constructor = Persistent<FunctionTemplate>::New(FunctionTemplate::New(CascadeClassifierWrap::New));
constructor->InstanceTemplate()->SetInternalFieldCount(1);
constructor->SetClassName(String::NewSymbol("CascadeClassifier"));
// Prototype
//Local<ObjectTemplate> proto = constructor->PrototypeTemplate();
NODE_SET_PROTOTYPE_METHOD(constructor, "detectMultiScale", DetectMultiScale);
target->Set(String::NewSymbol("CascadeClassifier"), constructor->GetFunction());
};
Handle<Value>
CascadeClassifierWrap::New(const Arguments &args) {
HandleScope scope;
if (args.This()->InternalFieldCount() == 0)
return v8::ThrowException(v8::Exception::TypeError(v8::String::New("Cannot Instantiate without new")));
CascadeClassifierWrap *pt = new CascadeClassifierWrap(*args[0]);
pt->Wrap(args.This());
return args.This();
}
CascadeClassifierWrap::CascadeClassifierWrap(v8::Value* fileName){
std::string filename;
filename = std::string(*v8::String::AsciiValue(fileName->ToString()));
if (!cc.load(filename.c_str())){
v8::ThrowException(v8::Exception::TypeError(v8::String::New("Error loading file")));
}
}
struct classifier_baton_t {
CascadeClassifierWrap *cc;
Persistent<Function> cb;
Matrix *im;
double scale;
int neighbors;
int minw;
int minh;
int sleep_for;
std::vector<cv::Rect> res;
uv_work_t request;
};
Handle<Value>
CascadeClassifierWrap::DetectMultiScale(const v8::Arguments& args){
HandleScope scope;
CascadeClassifierWrap *self = ObjectWrap::Unwrap<CascadeClassifierWrap>(args.This());
if (args.Length() < 2){
v8::ThrowException(v8::Exception::TypeError(v8::String::New("detectMultiScale takes at least 2 args")));
}
Matrix *im = ObjectWrap::Unwrap<Matrix>(args[0]->ToObject());
REQ_FUN_ARG(1, cb);
double scale = 1.1;
if (args.Length() > 2 && args[2]->IsNumber())
scale = args[2]->NumberValue();
int neighbors = 2;
if (args.Length() > 3 && args[3]->IsInt32())
neighbors = args[3]->IntegerValue();
int minw = 30;
int minh = 30;
if (args.Length() > 5 && args[4]->IsInt32() && args[5]->IsInt32()){
minw = args[4]->IntegerValue();
minh = args[5]->IntegerValue();
}
classifier_baton_t *baton = new classifier_baton_t();
baton->cc = self;
baton->cb = Persistent<Function>::New(cb);
baton->im = im;
baton->scale = scale;
baton->neighbors = neighbors;
baton->minw = minw;
baton->minh = minh;
baton->sleep_for = 1;
baton->request.data = baton;
// self->Ref();
// eio_custom(EIO_DetectMultiScale, EIO_PRI_DEFAULT, EIO_AfterDetectMultiScale, baton);
// ev_ref(EV_DEFAULT_UC);
uv_queue_work(uv_default_loop(), &baton->request, AsyncDetectMultiScale, (uv_after_work_cb)AfterAsyncDetectMultiScale);
return Undefined();
}
void AsyncDetectMultiScale(uv_work_t *req) {
classifier_baton_t *baton = static_cast<classifier_baton_t *>(req->data);
// sleep(baton->sleep_for);
std::vector<cv::Rect> objects;
cv::Mat gray;
if(baton->im->mat.channels() != 1)
cvtColor(baton->im->mat, gray, CV_BGR2GRAY);
equalizeHist( gray, gray);
baton->cc->cc.detectMultiScale(gray, objects, baton->scale, baton->neighbors, 0 | CV_HAAR_SCALE_IMAGE, cv::Size(baton->minw, baton->minh));
baton->res = objects;
}
void AfterAsyncDetectMultiScale(uv_work_t *req) {
HandleScope scope;
classifier_baton_t *baton = static_cast<classifier_baton_t *>(req->data);
// ev_unref(EV_DEFAULT_UC);
// baton->cc->Unref();
Local<Value> argv[2];
argv[0] = Local<Value>::New(Null());
v8::Local<v8::Array> arr = v8::Array::New(baton->res.size());
for(unsigned int i = 0; i < baton->res.size(); i++ ){
v8::Local<v8::Object> x = v8::Object::New();
x->Set(v8::String::New("x"), v8::Number::New(baton->res[i].x));
x->Set(v8::String::New("y"), v8::Number::New(baton->res[i].y));
x->Set(v8::String::New("width"), v8::Number::New(baton->res[i].width));
x->Set(v8::String::New("height"), v8::Number::New(baton->res[i].height));
arr->Set(i, x);
}
argv[1] = arr;
TryCatch try_catch;
baton->cb->Call(Context::GetCurrent()->Global(), 2, argv);
if (try_catch.HasCaught()) {
FatalException(try_catch);
}
baton->cb.Dispose();
delete baton;
// return 0;
}