0

I get about 20 frames per second. If I run it like this, it causes the computer to freeze. I think it is because it processes a large number at a time. how can I limit a function to a maximum number of processes it can have.I looked at kue but it requires redis. How can I handle this? Thank you

The js calls a c++ addon to do the works.

addon.addonFunction(img, function(err, detobjs) {//this takes about 1sec
    //do stuff
});

c++ code

#include "HogPeopleDetectdvr.h"
#include <string>
#include <iostream>
#include <vector>
#include <algorithm>
#include <chrono>
#include <thread>
// #include "inc/Matrix.h"
// Nan::Persistent<FunctionTemplate> Matrix::constructor1;

// #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
using namespace v8;
using v8::Local;
using v8::Object;

// Nan::Persistent<FunctionTemplate> Matrix::constructor;
// Nan::Persistent<FunctionTemplate> Matrix::constructor;
location unpack_location(Isolate * , const Handle<Object> sample_obj);

struct Work {
  uv_work_t  request;
  Persistent<Function> callback;

  std::vector<location> locations;
  std::vector<detect_result> results;
};

// called by libuv worker in separate thread
static void WorkAsync(uv_work_t *req)
{
    Work *work = static_cast<Work *>(req->data);

    work->results.resize(work->locations.size());
    std::transform(work->locations.begin(), work->locations.end(), work->results.begin(), CalculateRectHog);
}

static void WorkAsyncComplete(uv_work_t *req,int status)
{
    Isolate * isolate = Isolate::GetCurrent();

     v8::HandleScope handleScope(isolate);

    Work *work = static_cast<Work *>(req->data);

     Local<Array> arr = Array::New(isolate);

    for (unsigned int i = 0; i < work->results[0].found.size(); i++) {
      v8::Local < v8::Object > x = Nan::New<v8::Object>();
      x->Set(Nan::New("x").ToLocalChecked(), Nan::New < Number > (work->results[0].found[i].x));
      x->Set(Nan::New("y").ToLocalChecked(), Nan::New < Number > (work->results[0].found[i].y));
      x->Set(Nan::New("width").ToLocalChecked(), Nan::New < Number > (work->results[0].found[i].width));
      x->Set(Nan::New("height").ToLocalChecked(), Nan::New < Number > (work->results[0].found[i].height));
      arr->Set(i, x);
    }

   Handle<Value> argv1[] = { Null(isolate) , arr};

    // execute the callback
    // https://stackoverflow.com/questions/13826803/calling-javascript-function-from-a-c-callback-in-v8/28554065#28554065
    Local<Function>::New(isolate, work->callback)->Call(isolate->GetCurrentContext()->Global(), 2, argv1);

    work->callback.Reset();
    delete work;

}

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

    Work * work = new Work();
    work->request.data = work;

    Local<Array> input = Local<Array>::Cast(args[0]);
    unsigned int num_locations = input->Length();
    for (unsigned int i = 0; i < num_locations; i++) {
      work->locations.push_back(unpack_location(isolate, Local<Object>::Cast(input->Get(i))));
    }

    Local<Function> callback = Local<Function>::Cast(args[1]);
    work->callback.Reset(isolate, callback);

    uv_queue_work(uv_default_loop(),&work->request,WorkAsync,WorkAsyncComplete);

    args.GetReturnValue().Set(Undefined(isolate));

}


location unpack_location(Isolate * isolate, const Handle<Object> location_obj) {
  location loc;
  Handle<Value> hit_threshold = location_obj->Get(v8::String::NewFromUtf8(isolate,"hit_threshold"));
  Handle<Value> wins_tride = location_obj->Get(v8::String::NewFromUtf8(isolate,"wins_tride"));
  Handle<Value> padding = location_obj->Get(v8::String::NewFromUtf8(isolate,"padding"));
  Handle<Value> scale = location_obj->Get(v8::String::NewFromUtf8(isolate,"scale"));
  Handle<Value> group_threshold = location_obj->Get(v8::String::NewFromUtf8(isolate,"group_threshold"));
  Handle<Value> img_Value = location_obj->Get(v8::String::NewFromUtf8(isolate,"img"));

  loc.hit_threshold = hit_threshold->NumberValue();
  loc.wins_tride = wins_tride->NumberValue();
  loc.padding = padding->NumberValue();
  loc.scale = scale->NumberValue();
  loc.group_threshold = group_threshold->NumberValue();
  loc.img = Nan::ObjectWrap::Unwrap<node_opencv::Matrix>(img_Value->ToObject())->mat;
  return loc;
}

void init(Handle <Object> exports, Handle<Object> module) {
    Nan::HandleScope scope;
  NODE_SET_METHOD(exports, "HogPeopleDetectorDvr", PeopleDetectdvr);

}

NODE_MODULE(hog_people_detect, init)

Its in this function.

detect_result CalculateRectHog(location &loc) {

  detect_result result;

    HOGDescriptor hog;
    hog.winSize = Size(48, 96);
    hog.setSVMDetector(HOGDescriptor::getDaimlerPeopleDetector());

    vector<Rect> found, found_filtered;

    hog.detectMultiScale(loc.img, found, loc.hit_threshold, Size(),
     Size(), loc.scale, loc.group_threshold); //this line

        result.img = loc.img;
        result.found = found;
      // imwrite("wwww.jpg",loc.img);

  return result;
}
kg99
  • 117
  • 1
  • 11
  • if the processing is done in your c++ addon, why don't you start a worked thread and return to js immediately? – pergy Feb 01 '17 at 08:55

1 Answers1

2

This is due to javascript by default being run as a single thread. So your c++ addon will block the execution of your javascript program.

You might want to use a child process to do the processing since that way you won't be blocking your main execution and thus it shouldn't halt.

There should be enough information to get you going here: https://nodejs.org/api/child_process.html

Emil B
  • 41
  • 4
  • How about using async and limiting it. Will that be suffiecient? – kg99 Feb 01 '17 at 09:08
  • 1
    As long as your async lib spawns a new thread, then your execution won't stutter. If it truly is async, it should encapsulate the process of spawning a new thread, so I say give it a go and find out :) – Emil B Feb 01 '17 at 09:30