Thursday, 4 May 2017

Make c++ addon asynchronous

I have managed to integrate the dlib video tracker to my node application. The problem I have now is to make it non-blocking. Any help will be appreciated. Thank you.

Here is my code

#ifndef MYOBJECT_H
#define MYOBJECT_H

#include "ImageDetails.h"
#include "opencv2/core/core_c.h"
#include "../dlib/opencv/cv_image.h"
#include "../dlib/image_processing.h"
#include "../dlib/gui_widgets.h"
#include "../dlib/image_io.h"
#include "../dlib/dir_nav.h"

#include "/home/pi/projects/lib/node-opencv-master/src/Matrix.h"
#include "/home/pi/projects/lib/node-opencv-master/src/Contours.h"


#include <nan.h>
//#include <node_object_wrap.h>
using namespace dlib;
using namespace cv;
using namespace std;

class MyObject : public Nan::ObjectWrap {
 public:
  static void Init(v8::Local<v8::Object> exports);

 private:
  explicit MyObject(std::vector<ImageDetails> details, cv::Mat img);
  ~MyObject();

  static void New(const Nan::FunctionCallbackInfo<v8::Value>& args);
  static void UpdateImage(const Nan::FunctionCallbackInfo<v8::Value>& args);
  static Nan::Persistent<v8::Function> constructor;
  std::vector <correlation_tracker> value_;
};


#endif

Imagedetails.h

#ifndef IMAGEDETAILS_H
#define IMAGEDETAILS_H



class ImageDetails {
public:
  int width;
  int height;
  int xpoint;
  int ypoint;
};



#endif

//

#include "VideoTracking.h"


Nan::Persistent<v8::Function> MyObject::constructor;
ImageDetails unpack_details(Isolate * , const Handle<Object> sample_obj);

MyObject::MyObject(std::vector<ImageDetails> details, cv::Mat img){

value_.resize(details.size());
dlib::array2d<bgr_pixel> dlibImage;
dlib::assign_image(dlibImage, dlib::cv_image<bgr_pixel>(img));

//value_.start_track(dlibImage, centered_rect(point(93,110), 38, 86));

    for (unsigned int i=0; i < details.size(); i++){
    cout << details[i].xpoint << endl;
    cout << details[i].ypoint << endl;
    cout << details[i].width << endl;
    cout << details[i].height << endl;

        value_[i].start_track(dlibImage, centered_rect(point(details[i].xpoint, details[i].ypoint), details[i].width, details[i].height));
    }
}

MyObject::~MyObject() {
}

void MyObject::Init(v8::Local<v8::Object> exports) {
Nan::HandleScope scope;

  // Prepare constructor template
 v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
  tpl->SetClassName(Nan::New("MyObject").ToLocalChecked());
  tpl->InstanceTemplate()->SetInternalFieldCount(1);

  Nan::SetPrototypeMethod(tpl, "updateImage", UpdateImage);
  constructor.Reset(tpl->GetFunction());
    exports->Set(Nan::New("MyObject").ToLocalChecked(), tpl->GetFunction());
}

void MyObject::New(const Nan::FunctionCallbackInfo<v8::Value>& args) {
      Isolate* isolate = args.GetIsolate();


      v8::Local<v8::Object> location_obj = args[1]->ToObject();
      v8::Handle<v8::Value> img_Value = location_obj->Get(v8::String::NewFromUtf8(isolate,"img"));
      v8::Local<v8::Array> input = v8::Local<v8::Array>::Cast(args[0]);
      unsigned int num_locations = input->Length();

            std::vector<ImageDetails> tmp;
//            tmp.resize(num_locations);

        for (unsigned int i = 0; i < num_locations; i++) {
          tmp.push_back(unpack_details(isolate, v8::Local<v8::Object>::Cast(input->Get(i))));
        }

    MyObject* obj = new MyObject(tmp, Nan::ObjectWrap::Unwrap<node_opencv::Matrix>(img_Value->ToObject())->mat);
    obj->Wrap(args.This());
    args.GetReturnValue().Set(args.This());

}

ImageDetails unpack_details(Isolate * isolate, const v8::Handle<v8::Object> location_obj) {
  ImageDetails tmp;
  v8::Handle<v8::Value> width = location_obj->Get(v8::String::NewFromUtf8(isolate,"width"));
  v8::Handle<v8::Value> heigth = location_obj->Get(v8::String::NewFromUtf8(isolate,"heigth"));
  v8::Handle<v8::Value> xpoint = location_obj->Get(v8::String::NewFromUtf8(isolate,"xpoint"));
  v8::Handle<v8::Value> ypoint = location_obj->Get(v8::String::NewFromUtf8(isolate,"ypoint"));

  tmp.width = width->NumberValue();
  tmp.height = heigth->NumberValue();
  tmp.xpoint = xpoint->NumberValue();
  tmp.ypoint = ypoint->NumberValue();

  return tmp;
}

void MyObject::UpdateImage(const Nan::FunctionCallbackInfo<v8::Value>& args) {
//    image_window win;
    Isolate* isolate = args.GetIsolate();

    v8::Local<v8::Object> location_obj = args[0]->ToObject();
    v8::Handle<v8::Value> img_Value = location_obj->Get(v8::String::NewFromUtf8(isolate,"img"));

    dlib::array2d<bgr_pixel> dlibImage;
    dlib::assign_image(dlibImage, dlib::cv_image<bgr_pixel>(Nan::ObjectWrap::Unwrap<node_opencv::Matrix>(img_Value->ToObject())->mat));

    MyObject* obj = ObjectWrap::Unwrap<MyObject>(args.Holder());
    v8::Local<v8::Array> arr = Array::New(isolate);

    for (unsigned int i=0; i < obj->value_.size(); i++){
         obj->value_[i].update(dlibImage);

         cv::Rect r = cv::Rect(obj->value_[i].get_position().left(), obj->value_[i].get_position().top(), obj->value_[i].get_position().width(), obj->value_[i].get_position().height());

          v8::Local < v8::Object > x = Nan::New<v8::Object>();
          x->Set(Nan::New("x").ToLocalChecked(), Nan::New < Number > (r.x));
          x->Set(Nan::New("y").ToLocalChecked(), Nan::New < Number > (r.y));
          x->Set(Nan::New("width").ToLocalChecked(), Nan::New < Number > (r.width));
          x->Set(Nan::New("height").ToLocalChecked(), Nan::New < Number > (r.height));
          arr->Set(i, x);
    }
//    obj->value_.update(dlibImage);
//
//     win.set_image(dlibImage);
//     win.clear_overlay();
//     win.add_overlay(obj->value_.get_position());
////     sleep(10000);
//    cout << obj->value_.get_position().top() <<endl;
//    cin.get();
//     Handle<Value> argv1[] = { Null(isolate) , arr};
    args.GetReturnValue().Set(arr);
}

Basically I need one way to create the tracker and update it later on. Hence, I decided to create the tracker when I create a new object and just update it after whats. Currently this is how it is called in my js file.

This is how I create it

var loc = {
                        xpoint: detobj.x,
                        ypoint: detobj.y,
                        heigth: detobj.height,
                        width: detobj.width
                    };
                    details.push(loc);
var image_obj = new addon.MyObject(details, obj1);

This is how I update the image

    var obj = {img:matrix}
    var detobjs = image_obj.updateImage(obj1);
    for(var i =0; i < detobjs.length; i++){
      var detobj = detobjs[i];
     matrix.rectangle([detobj.x, detobj.y], [detobj.width, detobj.height], COLORRED, 1);

   }
 procobj.frame.imagejpg = matrix.toBuffer();

Thank you.



via vladimir999

No comments:

Post a Comment