Я в настоящее время разрабатываю nodejs
модуль, написанный на C ++, и я искал способ преобразовать v8::Object
к cv::Mat
объект из opencv
без всякой удачи сейчас.
я видел это НАН библиотека может помочь конвертировать объекты, но я не могу найти как, я даже не знаю, возможно ли конвертировать их в моем случае.
V8 сок Проект оправдал бы мои ожидания, но так как он был заброшен, я просто не знаю, как это сделать.
Вот фрагмент того, что я пытаюсь сделать:
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
объект? Для любого типа я хочу?
Любая помощь будет оценена, спасибо!
Сначала я бы порекомендовал посмотреть на существующие привязки openCV для Node.js вроде Узел-OpenCV.
Если вам нужно связать код C ++ и JavaScript, есть несколько библиотек. Как автор одного из них, v8pp, Я знаю о нескольких других:
Как я знаю, для преобразования объекта C ++ в v8 :: Object все они используют v8::Object::SetAlignedPointerInInternalField()
функция.
C ++ объект для v8::Object
преобразования обычно выполняются с отображением указателя C ++ на постоянный дескриптор объекта V8 в контейнере карты.
Посмотрите на Nodejs.org
C ++ аддон и Nan
учебные пособия. Хотя оба немного вводят в заблуждение, они так или иначе описывают канонический путь. использование Nan
по прямой V8
API, так как особенно эта часть (была и остается) сильно меняется.
С Nan
что вы ищете прохождение обернутых предметов. Точнее это линия это сердце этого.
В эта вилка из Узел OpenCV, Я делаю именно это с cv::Mat
чтобы сделать его первоклассным объектом для JS-land. Может быть, эта реализация может помочь вам.
TL; DR
Оберните объект
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());
}
}