kg99
kg99

Reputation: 117

Node.js Processing lots of images

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;
}

Upvotes: 0

Views: 162

Answers (1)

Emil B
Emil B

Reputation: 41

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

Upvotes: 2

Related Questions