1

我目前正在开发一个nodejs用 C++ 编写的模块,我一直在寻找一种将 a 转换v8::Objectcv::Mat对象的方法opencv,目前没有任何运气。

我看到nan 库可以帮助转换对象,但我找不到方法,我什至不知道在我的情况下是否可以转换它们。

v8 juice项目可以满足我的期望,但由于它已被放弃,我只是不知道该怎么做。

这是我正在尝试做的一个片段:

void
BRMatcher::run(const v8::FunctionCallbackInfo<v8::Value>& args)
{
  v8::Isolate* isolate = v8::Isolate::GetCurrent();
  v8::HandleScope scope(isolate);

  if (args.Length() < 1)
  {
    isolate->ThrowException(v8::Exception::TypeError(v8::String::NewFromUtf8(isolate, "Missing parameter [Mat img].")));
    return ;
  }

  if (!args[0]->IsObject())
  {
    isolate->ThrowException(v8::Exception::TypeError(v8::String::NewFromUtf8(isolate, "Parameter [Mat img] must be an object.")));
    return ;
  }

  v8::Local<v8::Object> cvMat(args[0]->ToObject());

  Mat img = ??? // This is where I ended up...
  // ...
}

StackOverflow 上所有关于此的帖子都已过时(旧版本或不再工作的工具......)

所以我的问题是:如何将我在函数中收到的参数转换为cv::Mat对象?我想要的任何类型?

任何帮助将不胜感激,谢谢!

4

2 回答 2

2

首先,我建议查看 Node.js 的现有 openCV 绑定,例如node-opencv

如果您需要绑定 C++ 和 JavaScript 代码,有几个库。作为其中一个v8pp的作者,我知道其他几个:

据我所知,要将 C++ 对象转换为 v8::Object 所有这些都使用v8::Object::SetAlignedPointerInInternalField()函数。

C++ 对象到v8::Object转换通常通过将 C++ 指针映射到映射容器中的 V8 对象的持久句柄来执行。

于 2015-06-02T09:04:30.787 回答
1

看看Nodejs.orgC++ 插件和Nan教程。尽管两者都有点误导,但它们无论如何都描述了规范的方式。使用Nan直接V8API,因为尤其是这部分(过去和现在)正在发生很大变化。

Nan您正在寻找的是传递包装的对象。更确切地说,这条线是它的核心。

Node-OpenCV的这个分支中,我正在这样做,以使其成为 JS-land 的一流对象。也许这个实现可以帮助你。cv::Mat

TL;博士

用包裹物体Nan::ObjectWrap并传递它。内部v8::SetInternalFieldPointer();为您使用。这基本上是可以复制粘贴的。

// lib/mat.js
var cv = require('./bindings')('addon');

function Mat() {

}

/**
 * returns the wrapped c++ object
 * [arguments optional]
 */
Mat.prototype.createMat = function (a) {
  var args = Array.prototype.slice.call(arguments);
  return cv.Mat.createMat(args[0])
}
// src/addon.cc
// just initializes all your modules. Magic happening in mat.h and matwrap.h 
// matwrap.cc is the implementation of the wrapped object. mat.cc holds 
// JS-libarary specific methods 

#include <nan.h>
#include "opencv.h"
#include "imgproc.h"
#include "mat.h"
#include "matwrap.h"

void InitAll(v8::Local<v8::Object> exports) {
   Opencv::Init(exports);
   ImgProc::Init(exports);
   Matwrap::Init();
   Mat::Init(exports);
}

NODE_MODULE(addon, InitAll)

重要的东西在这里...

// src/matwrap.h
#ifndef MATWRAP_H
#define MATWRAP_H

#include <opencv2/opencv.hpp>
#include <nan.h>

class Matwrap : public Nan::ObjectWrap {
 public:
  static void Init();
  static v8::Local<v8::Object> NewInstance(v8::Local<v8::Value> arg);
  cv::Mat Val() const { return val_; }

 private:
  Matwrap();
  ~Matwrap();

  static Nan::Persistent<v8::Function> constructor;
  static void New(const Nan::FunctionCallbackInfo<v8::Value>& info);
  cv::Mat val_;
};

#endif

...在这里,您将其包装起来(基本上就是这样;请按照以下说明进行消费):

// src/matwrap.cc
#include <node.h>
#include "matwrap.h"
#include <opencv2/opencv.hpp>

Matwrap::Matwrap() {};
Matwrap::~Matwrap() {};

Nan::Persistent<v8::Function> Matwrap::constructor;

void Matwrap::Init() {
  Nan::HandleScope scope;

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

  constructor.Reset(tpl->GetFunction());
}

void Matwrap::New(const Nan::FunctionCallbackInfo<v8::Value>& info) {
  // wrap it...
  Matwrap* obj = new Matwrap();
  cv::Mat src;
  obj->val_ = src;
  obj->Wrap(info.This());
  // return wrapped here...
  info.GetReturnValue().Set(info.This());
}

v8::Local<v8::Object> Matwrap::NewInstance(v8::Local<v8::Value> arg) {
  Nan::EscapableHandleScope scope;

  // const unsigned argc = 1;
  // v8::Local<v8::Value> argv[argc] = { arg };
  v8::Local<v8::Function> cons = Nan::New<v8::Function>(constructor);
  v8::Local<v8::Object> instance = cons->NewInstance();

  return scope.Escape(instance);
}

对于消费,您可以执行以下操作:

// lib/mat.js
/**
 * Returns true if the array has no elements.
 * @param  {Object} mat - native cv::Mat
 * @return {Boolean}
 */
Mat.prototype.empty = function (mat) {
  var args = Array.prototype.slice.call(arguments);
  return cv.Mat.empty(args[0])
}
// src/mat.h
// This is your API
#ifndef MAT_H
#define MAT_H

// #include <opencv2/opencv.hpp>
#include <nan.h>

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

 private:
  explicit Mat(double value = 0);
  ~Mat();

  static void New(const Nan::FunctionCallbackInfo<v8::Value>& info);
  static void CreateMat(const Nan::FunctionCallbackInfo<v8::Value>& info);
  static void Empty(const Nan::FunctionCallbackInfo<v8::Value>& info);
  static void Total(const Nan::FunctionCallbackInfo<v8::Value>& info);
  static void Type(const Nan::FunctionCallbackInfo<v8::Value>& info);
  static Nan::Persistent<v8::Function> constructor;
  double value_;
};
#endif
// src/mat.cc
#include "mat.h"
#include "matwrap.h"
#include <opencv2/opencv.hpp>

Nan::Persistent<v8::Function> Mat::constructor;

Mat::Mat(double value) : value_(value) {
}

Mat::~Mat() {
}

void Mat::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("Mat").ToLocalChecked());
  tpl->InstanceTemplate()->SetInternalFieldCount(1);

  // Prototype
  Nan::SetPrototypeMethod(tpl, "createMat", CreateMat);
  Nan::SetPrototypeMethod(tpl, "empty", Empty);
  Nan::SetPrototypeMethod(tpl, "total", Total);
  Nan::SetPrototypeMethod(tpl, "type", Type);

  constructor.Reset(tpl->GetFunction());
  exports->Set(Nan::New("Mat").ToLocalChecked(), tpl->GetFunction());
}

void Mat::New(const Nan::FunctionCallbackInfo<v8::Value>& info) {
  if (info.IsConstructCall()) {
    // Invoked as constructor: `new Opencv(...)`
    double value = info[0]->IsUndefined() ? 0 : info[0]->NumberValue();
    Mat* obj = new Mat(value);
    obj->Wrap(info.This());
    info.GetReturnValue().Set(info.This());
  } else {
    // Invoked as plain function `Opencv(...)`, turn into construct call.
    const int argc = 1;
    v8::Local<v8::Value> argv[argc] = { info[0] };
    v8::Local<v8::Function> cons = Nan::New<v8::Function>(constructor);
    info.GetReturnValue().Set(cons->NewInstance(argc, argv));
  }
}

void Mat::CreateMat(const Nan::FunctionCallbackInfo<v8::Value>& info) {

  info.GetReturnValue().Set(Matwrap::NewInstance(info[0]));
}

void Mat::Empty(const Nan::FunctionCallbackInfo<v8::Value>& info) {

  Matwrap* obj = Nan::ObjectWrap::Unwrap<Matwrap>(info[0]->ToObject());
  // check through cv::Mat::empty()
  if (obj->Val().empty()) {
    // return JS bool
    info.GetReturnValue().Set(Nan::True());
  } else {
    // TODO: logically not correct
    info.GetReturnValue().Set(Nan::False());
  }
}
于 2015-09-03T16:29:57.090 回答