初次提交
This commit is contained in:
24
cxx/common/node.h
Normal file
24
cxx/common/node.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef __COMMON_NODE_H__
|
||||
#define __COMMON_NODE_H__
|
||||
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <napi.h>
|
||||
|
||||
#define NODE_INIT_OBJECT(name, function) \
|
||||
do \
|
||||
{ \
|
||||
auto obj = Napi::Object::New(env); \
|
||||
function(env, obj); \
|
||||
exports.Set(Napi::String::New(env, #name), obj); \
|
||||
} while (0)
|
||||
|
||||
inline uint64_t __node_ptr_of__(Napi::Value value)
|
||||
{
|
||||
bool lossless;
|
||||
return value.As<Napi::BigInt>().Uint64Value(&lossless);
|
||||
}
|
||||
|
||||
#define NODE_PTR_OF(type, value) (reinterpret_cast<type *>(__node_ptr_of__(value)))
|
||||
|
||||
#endif
|
24
cxx/common/session.h
Normal file
24
cxx/common/session.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef __COMMON_SESSION_H__
|
||||
#define __COMMON_SESSION_H__
|
||||
#include <iostream>
|
||||
|
||||
namespace ai
|
||||
{
|
||||
|
||||
class Tensor
|
||||
{
|
||||
public:
|
||||
virtual ~Tensor() {}
|
||||
};
|
||||
|
||||
class Session
|
||||
{
|
||||
public:
|
||||
virtual ~Session() {}
|
||||
|
||||
virtual const std::map<std::string, std::vector<int>> &getInputShapes() const = 0;
|
||||
virtual const std::map<std::string, std::vector<int>> &getOutputShapes() const = 0;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
145
cxx/cv/node.cc
Normal file
145
cxx/cv/node.cc
Normal file
@ -0,0 +1,145 @@
|
||||
#include <iostream>
|
||||
#include <functional>
|
||||
#include <opencv2/opencv.hpp>
|
||||
#include "node.h"
|
||||
|
||||
using namespace Napi;
|
||||
|
||||
#define MAT_INSTANCE_METHOD(method) InstanceMethod<&CVMat::method>(#method, static_cast<napi_property_attributes>(napi_writable | napi_configurable))
|
||||
|
||||
static FunctionReference *constructor = nullptr;
|
||||
|
||||
class CVMat : public ObjectWrap<CVMat> {
|
||||
public:
|
||||
static Napi::Object Init(Napi::Env env, Napi::Object exports)
|
||||
{
|
||||
Function func = DefineClass(env, "Mat", {
|
||||
MAT_INSTANCE_METHOD(IsEmpty),
|
||||
MAT_INSTANCE_METHOD(GetCols),
|
||||
MAT_INSTANCE_METHOD(GetRows),
|
||||
MAT_INSTANCE_METHOD(GetChannels),
|
||||
MAT_INSTANCE_METHOD(Resize),
|
||||
MAT_INSTANCE_METHOD(Crop),
|
||||
MAT_INSTANCE_METHOD(Rotate),
|
||||
MAT_INSTANCE_METHOD(Clone),
|
||||
|
||||
MAT_INSTANCE_METHOD(DrawCircle),
|
||||
|
||||
MAT_INSTANCE_METHOD(Data),
|
||||
MAT_INSTANCE_METHOD(Encode),
|
||||
});
|
||||
constructor = new FunctionReference();
|
||||
*constructor = Napi::Persistent(func);
|
||||
exports.Set("Mat", func);
|
||||
env.SetInstanceData<FunctionReference>(constructor);
|
||||
return exports;
|
||||
}
|
||||
|
||||
CVMat(const CallbackInfo &info)
|
||||
: ObjectWrap<CVMat>(info)
|
||||
{
|
||||
int mode = cv::IMREAD_COLOR_BGR;
|
||||
if (info.Length() > 1 && info[1].IsObject()) {
|
||||
Object options = info[1].As<Object>();
|
||||
if (options.Has("mode") && options.Get("mode").IsNumber()) mode = options.Get("mode").As<Number>().Int32Value();
|
||||
}
|
||||
|
||||
if (info[0].IsString()) im_ = cv::imread(info[0].As<String>().Utf8Value(), mode);
|
||||
else if (info[0].IsTypedArray()) {
|
||||
auto buffer = info[0].As<TypedArray>().ArrayBuffer();
|
||||
uint8_t *bufferPtr = static_cast<uint8_t *>(buffer.Data());
|
||||
std::vector<uint8_t> data(bufferPtr, bufferPtr + buffer.ByteLength());
|
||||
im_ = cv::imdecode(data, mode);
|
||||
}
|
||||
}
|
||||
|
||||
~CVMat() { im_.release(); }
|
||||
|
||||
Napi::Value IsEmpty(const Napi::CallbackInfo &info) { return Boolean::New(info.Env(), im_.empty()); }
|
||||
Napi::Value GetCols(const Napi::CallbackInfo &info) { return Number::New(info.Env(), im_.cols); }
|
||||
Napi::Value GetRows(const Napi::CallbackInfo &info) { return Number::New(info.Env(), im_.rows); }
|
||||
Napi::Value GetChannels(const Napi::CallbackInfo &info) { return Number::New(info.Env(), im_.channels()); }
|
||||
Napi::Value Resize(const Napi::CallbackInfo &info)
|
||||
{
|
||||
return CreateMat(info.Env(), [this, &info](auto &mat) { cv::resize(im_, mat.im_, cv::Size(info[0].As<Number>().Int32Value(), info[1].As<Number>().Int32Value())); });
|
||||
}
|
||||
Napi::Value Crop(const Napi::CallbackInfo &info)
|
||||
{
|
||||
return CreateMat(info.Env(), [this, &info](auto &mat) {
|
||||
mat.im_ = im_(cv::Rect(
|
||||
info[0].As<Number>().Int32Value(), info[1].As<Number>().Int32Value(),
|
||||
info[2].As<Number>().Int32Value(), info[3].As<Number>().Int32Value()));
|
||||
});
|
||||
}
|
||||
Napi::Value Rotate(const Napi::CallbackInfo &info)
|
||||
{
|
||||
return CreateMat(info.Env(), [this, &info](auto &mat) {
|
||||
auto x = info[0].As<Number>().DoubleValue();
|
||||
auto y = info[1].As<Number>().DoubleValue();
|
||||
auto angle = info[2].As<Number>().DoubleValue();
|
||||
cv::Mat rotation_matix = cv::getRotationMatrix2D(cv::Point2f(x, y), angle, 1.0);
|
||||
cv::warpAffine(im_, mat.im_, rotation_matix, im_.size());
|
||||
});
|
||||
}
|
||||
|
||||
Napi::Value Clone(const Napi::CallbackInfo &info)
|
||||
{
|
||||
return CreateMat(info.Env(), [this, &info](auto &mat) { mat.im_ = im_.clone(); });
|
||||
}
|
||||
|
||||
Napi::Value DrawCircle(const Napi::CallbackInfo &info)
|
||||
{
|
||||
int x = info[0].As<Number>().Int32Value();
|
||||
int y = info[1].As<Number>().Int32Value();
|
||||
int radius = info[2].As<Number>().Int32Value();
|
||||
int b = info[3].As<Number>().Int32Value();
|
||||
int g = info[4].As<Number>().Int32Value();
|
||||
int r = info[5].As<Number>().Int32Value();
|
||||
int thickness = info[6].As<Number>().Int32Value();
|
||||
int lineType = info[7].As<Number>().Int32Value();
|
||||
int shift = info[8].As<Number>().Int32Value();
|
||||
|
||||
cv::circle(im_, cv::Point(x, y), radius, cv::Scalar(b, g, r), thickness, lineType, shift);
|
||||
return info.Env().Undefined();
|
||||
}
|
||||
|
||||
Napi::Value Data(const Napi::CallbackInfo &info) { return ArrayBuffer::New(info.Env(), im_.ptr(), im_.elemSize() * im_.total()); }
|
||||
Napi::Value Encode(const Napi::CallbackInfo &info)
|
||||
{
|
||||
auto options = info[0].As<Object>();
|
||||
auto extname = options.Get("extname").As<String>().Utf8Value();
|
||||
cv::imencode(extname, im_, encoded_);
|
||||
return ArrayBuffer::New(info.Env(), encoded_.data(), encoded_.size());
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
inline Napi::Object EmptyMat(Napi::Env env) { return constructor->New({}).As<Object>(); }
|
||||
inline CVMat &GetMat(Napi::Object obj) { return *ObjectWrap<CVMat>::Unwrap(obj); }
|
||||
inline Napi::Object CreateMat(Napi::Env env, std::function<void(CVMat &mat)> callback)
|
||||
{
|
||||
auto obj = EmptyMat(env);
|
||||
callback(GetMat(obj));
|
||||
return obj;
|
||||
}
|
||||
|
||||
private:
|
||||
cv::Mat im_;
|
||||
std::vector<uint8_t> encoded_;
|
||||
};
|
||||
|
||||
|
||||
void InstallOpenCVAPI(Env env, Object exports)
|
||||
{
|
||||
CVMat::Init(env, exports);
|
||||
}
|
||||
|
||||
#ifdef USE_OPENCV
|
||||
static Object Init(Env env, Object exports)
|
||||
{
|
||||
InstallOpenCVAPI(env, exports);
|
||||
return exports;
|
||||
}
|
||||
NODE_API_MODULE(addon, Init)
|
||||
|
||||
#endif
|
8
cxx/cv/node.h
Normal file
8
cxx/cv/node.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef __CV_NODE_H__
|
||||
#define __CV_NODE_H__
|
||||
|
||||
#include "common/node.h"
|
||||
|
||||
void InstallOpenCVAPI(Napi::Env env, Napi::Object exports);
|
||||
|
||||
#endif
|
19
cxx/mnn/session.h
Normal file
19
cxx/mnn/session.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef __MNN_SESSION_H__
|
||||
#define __MNN_SESSION_H__
|
||||
|
||||
#include <MNN/Interpreter.hpp>
|
||||
#include <MNN/ImageProcess.hpp>
|
||||
|
||||
#include "common/session.h"
|
||||
|
||||
namespace ai
|
||||
{
|
||||
class MNNSession : public Session
|
||||
{
|
||||
public:
|
||||
MNNSession(const void *modelData, size_t size);
|
||||
~MNNSession();
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
65
cxx/node.cc
Normal file
65
cxx/node.cc
Normal file
@ -0,0 +1,65 @@
|
||||
#include <unistd.h>
|
||||
#include <napi.h>
|
||||
#include "cv/node.h"
|
||||
#ifdef USE_ORT
|
||||
#include "ort/node.h"
|
||||
#endif
|
||||
|
||||
using namespace Napi;
|
||||
|
||||
class TestWork : public AsyncWorker
|
||||
{
|
||||
public:
|
||||
TestWork(const Napi::Function &callback, int value) : Napi::AsyncWorker(callback), val_(value) {}
|
||||
~TestWork() {}
|
||||
|
||||
void Execute()
|
||||
{
|
||||
printf("the worker-thread doing! %d \n", val_);
|
||||
sleep(3);
|
||||
printf("the worker-thread done! %d \n", val_);
|
||||
}
|
||||
|
||||
void OnOK()
|
||||
{
|
||||
Callback().Call({Env().Undefined(), Number::New(Env(), 0)});
|
||||
}
|
||||
|
||||
private:
|
||||
int val_;
|
||||
};
|
||||
|
||||
Value test(const CallbackInfo &info)
|
||||
{
|
||||
// ai::ORTSession(nullptr, 0);
|
||||
|
||||
// Function callback = info[1].As<Function>();
|
||||
// TestWork *work = new TestWork(callback, info[0].As<Number>().Int32Value());
|
||||
// work->Queue();
|
||||
return info.Env().Undefined();
|
||||
}
|
||||
|
||||
Object Init(Env env, Object exports)
|
||||
{
|
||||
//OpenCV
|
||||
NODE_INIT_OBJECT(cv, InstallOpenCVAPI);
|
||||
//OnnxRuntime
|
||||
#ifdef USE_ORT
|
||||
NODE_INIT_OBJECT(ort, InstallOrtAPI);
|
||||
#endif
|
||||
|
||||
Napi::Number::New(env, 0);
|
||||
|
||||
#define ADD_FUNCTION(name) exports.Set(Napi::String::New(env, #name), Napi::Function::New(env, name))
|
||||
// ADD_FUNCTION(facedetPredict);
|
||||
// ADD_FUNCTION(facedetRelease);
|
||||
|
||||
// ADD_FUNCTION(faceRecognitionCreate);
|
||||
// ADD_FUNCTION(faceRecognitionPredict);
|
||||
// ADD_FUNCTION(faceRecognitionRelease);
|
||||
|
||||
// ADD_FUNCTION(getDistance);
|
||||
#undef ADD_FUNCTION
|
||||
return exports;
|
||||
}
|
||||
NODE_API_MODULE(addon, Init)
|
292
cxx/ort/node.cc
Normal file
292
cxx/ort/node.cc
Normal file
@ -0,0 +1,292 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <onnxruntime_cxx_api.h>
|
||||
#include "node.h"
|
||||
|
||||
using namespace Napi;
|
||||
|
||||
#define SESSION_INSTANCE_METHOD(method) InstanceMethod<&OrtSession::method>(#method, static_cast<napi_property_attributes>(napi_writable | napi_configurable))
|
||||
|
||||
static ONNXTensorElementDataType getDataTypeFromString(const std::string &name)
|
||||
{
|
||||
static const std::map<std::string, ONNXTensorElementDataType> dataTypeNameMap = {
|
||||
{"float32", ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT},
|
||||
{"float", ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT},
|
||||
{"float64", ONNX_TENSOR_ELEMENT_DATA_TYPE_DOUBLE},
|
||||
{"double", ONNX_TENSOR_ELEMENT_DATA_TYPE_DOUBLE},
|
||||
{"int8", ONNX_TENSOR_ELEMENT_DATA_TYPE_INT8},
|
||||
{"uint8", ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT8},
|
||||
{"int16", ONNX_TENSOR_ELEMENT_DATA_TYPE_INT16},
|
||||
{"uint16", ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT16},
|
||||
{"int32", ONNX_TENSOR_ELEMENT_DATA_TYPE_INT32},
|
||||
{"uint32", ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT32},
|
||||
{"int64", ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64},
|
||||
{"uint64", ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT64},
|
||||
};
|
||||
auto it = dataTypeNameMap.find(name);
|
||||
return (it == dataTypeNameMap.end()) ? ONNX_TENSOR_ELEMENT_DATA_TYPE_UNDEFINED : it->second;
|
||||
}
|
||||
|
||||
static size_t getDataTypeSize(ONNXTensorElementDataType type)
|
||||
{
|
||||
static const std::map<ONNXTensorElementDataType, size_t> dataTypeSizeMap = {
|
||||
{ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT, 4},
|
||||
{ONNX_TENSOR_ELEMENT_DATA_TYPE_DOUBLE, 8},
|
||||
{ONNX_TENSOR_ELEMENT_DATA_TYPE_INT8, 1},
|
||||
{ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT8, 1},
|
||||
{ONNX_TENSOR_ELEMENT_DATA_TYPE_INT16, 2},
|
||||
{ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT16, 2},
|
||||
{ONNX_TENSOR_ELEMENT_DATA_TYPE_INT32, 4},
|
||||
{ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT32, 4},
|
||||
{ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64, 8},
|
||||
{ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT64, 8},
|
||||
};
|
||||
auto it = dataTypeSizeMap.find(type);
|
||||
return (it == dataTypeSizeMap.end()) ? 0 : it->second;
|
||||
}
|
||||
|
||||
static void *dataFromTypedArray(const Napi::Value &val, size_t &bytes)
|
||||
{
|
||||
auto arr = val.As<TypedArray>();
|
||||
auto data = static_cast<uint8_t *>(arr.ArrayBuffer().Data());
|
||||
bytes = arr.ByteLength();
|
||||
return static_cast<void *>(data + arr.ByteOffset());
|
||||
}
|
||||
|
||||
class OrtSessionNodeInfo {
|
||||
public:
|
||||
inline OrtSessionNodeInfo(const std::string &name, const Ort::TypeInfo &typeInfo)
|
||||
: name_(name), shape_(typeInfo.GetTensorTypeAndShapeInfo().GetShape()), type_(typeInfo.GetTensorTypeAndShapeInfo().GetElementType()) {}
|
||||
|
||||
inline const std::string &GetName() const { return name_; }
|
||||
inline const std::vector<int64_t> &GetShape() const { return shape_; }
|
||||
inline ONNXTensorElementDataType GetType() const { return type_; }
|
||||
inline size_t GetElementSize() const { return getDataTypeSize(type_); }
|
||||
size_t GetElementCount() const
|
||||
{
|
||||
if (!shape_.size()) return 0;
|
||||
size_t result = 1;
|
||||
for (auto dim : shape_) {
|
||||
if (dim <= 0) continue;
|
||||
result *= dim;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
inline size_t GetElementBytes() const { return GetElementSize() * GetElementCount(); }
|
||||
|
||||
private:
|
||||
std::string name_;
|
||||
std::vector<int64_t> shape_;
|
||||
ONNXTensorElementDataType type_;
|
||||
};
|
||||
|
||||
class OrtSessionRunWorker : public AsyncWorker {
|
||||
public:
|
||||
OrtSessionRunWorker(std::shared_ptr<Ort::Session> session, const Napi::Function &callback)
|
||||
: Napi::AsyncWorker(callback), session_(session) {}
|
||||
~OrtSessionRunWorker() {}
|
||||
|
||||
void Execute()
|
||||
{
|
||||
if (!HasError()) {
|
||||
try {
|
||||
Ort::RunOptions runOption;
|
||||
session_->Run(runOption, &inputNames_[0], &inputValues_[0], inputNames_.size(), &outputNames_[0], &outputValues_[0], outputNames_.size());
|
||||
}
|
||||
catch (std::exception &err) {
|
||||
SetError(err.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OnOK()
|
||||
{
|
||||
if (HasError()) {
|
||||
Callback().Call({Error::New(Env(), errorMessage_.c_str()).Value(), Env().Undefined()});
|
||||
}
|
||||
else {
|
||||
auto result = Object::New(Env());
|
||||
for (int i = 0; i < outputNames_.size(); ++i) {
|
||||
size_t bytes = outputElementBytes_[i];
|
||||
Ort::Value &value = outputValues_[i];
|
||||
auto buffer = ArrayBuffer::New(Env(), value.GetTensorMutableRawData(), bytes);
|
||||
result.Set(String::New(Env(), outputNames_[i]), buffer);
|
||||
}
|
||||
Callback().Call({Env().Undefined(), result});
|
||||
}
|
||||
}
|
||||
|
||||
inline void AddInput(const Ort::MemoryInfo &memoryInfo, const std::string &name, ONNXTensorElementDataType type, const std::vector<int64_t> &shape, void *data, size_t dataByteLen)
|
||||
{
|
||||
try {
|
||||
inputNames_.push_back(name.c_str());
|
||||
inputValues_.push_back(Ort::Value::CreateTensor(memoryInfo, data, dataByteLen, &shape[0], shape.size(), type));
|
||||
}
|
||||
catch (std::exception &err) {
|
||||
SetError(err.what());
|
||||
}
|
||||
}
|
||||
|
||||
inline void AddOutput(const std::string &name, size_t elementBytes)
|
||||
{
|
||||
outputNames_.push_back(name.c_str());
|
||||
outputValues_.push_back(Ort::Value{nullptr});
|
||||
outputElementBytes_.push_back(elementBytes);
|
||||
}
|
||||
|
||||
inline void SetError(const std::string &what) { errorMessage_ = what; }
|
||||
|
||||
inline bool HasError() { return errorMessage_.size() > 0; }
|
||||
|
||||
public:
|
||||
std::shared_ptr<Ort::Session> session_;
|
||||
std::vector<const char *> inputNames_;
|
||||
std::vector<Ort::Value> inputValues_;
|
||||
std::vector<const char *> outputNames_;
|
||||
std::vector<Ort::Value> outputValues_;
|
||||
std::vector<size_t> outputElementBytes_;
|
||||
std::string errorMessage_;
|
||||
};
|
||||
|
||||
class OrtSession : public ObjectWrap<OrtSession> {
|
||||
public:
|
||||
static Napi::Object Init(Napi::Env env, Napi::Object exports)
|
||||
{
|
||||
Function func = DefineClass(env, "OrtSession", {
|
||||
SESSION_INSTANCE_METHOD(GetInputsInfo),
|
||||
SESSION_INSTANCE_METHOD(GetOutputsInfo),
|
||||
SESSION_INSTANCE_METHOD(Run),
|
||||
});
|
||||
FunctionReference *constructor = new FunctionReference();
|
||||
*constructor = Napi::Persistent(func);
|
||||
exports.Set("OrtSession", func);
|
||||
env.SetInstanceData<FunctionReference>(constructor);
|
||||
return exports;
|
||||
}
|
||||
|
||||
OrtSession(const CallbackInfo &info)
|
||||
: ObjectWrap(info)
|
||||
{
|
||||
try {
|
||||
if (info[0].IsString()) session_ = std::make_shared<Ort::Session>(env, info[0].As<String>().Utf8Value().c_str(), sessionOptions);
|
||||
else if (info[0].IsTypedArray()) {
|
||||
size_t bufferBytes;
|
||||
auto buffer = dataFromTypedArray(info[0], bufferBytes);
|
||||
session_ = std::make_shared<Ort::Session>(env, buffer, bufferBytes, sessionOptions);
|
||||
}
|
||||
else session_ = nullptr;
|
||||
|
||||
if (session_ != nullptr) {
|
||||
Ort::AllocatorWithDefaultOptions allocator;
|
||||
for (int i = 0; i < session_->GetInputCount(); ++i) {
|
||||
std::string name = session_->GetInputNameAllocated(i, allocator).get();
|
||||
auto typeInfo = session_->GetInputTypeInfo(i);
|
||||
inputs_.emplace(name, std::make_shared<OrtSessionNodeInfo>(name, typeInfo));
|
||||
}
|
||||
for (int i = 0; i < session_->GetOutputCount(); ++i) {
|
||||
std::string name = session_->GetOutputNameAllocated(i, allocator).get();
|
||||
auto typeInfo = session_->GetOutputTypeInfo(i);
|
||||
outputs_.emplace(name, std::make_shared<OrtSessionNodeInfo>(name, typeInfo));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
Error::New(info.Env(), e.what()).ThrowAsJavaScriptException();
|
||||
}
|
||||
}
|
||||
|
||||
~OrtSession() {}
|
||||
|
||||
Napi::Value GetInputsInfo(const Napi::CallbackInfo &info) { return BuildNodeInfoToJavascript(info.Env(), inputs_); }
|
||||
|
||||
Napi::Value GetOutputsInfo(const Napi::CallbackInfo &info) { return BuildNodeInfoToJavascript(info.Env(), outputs_); }
|
||||
|
||||
Napi::Value Run(const Napi::CallbackInfo &info)
|
||||
{
|
||||
auto worker = new OrtSessionRunWorker(session_, info[1].As<Function>());
|
||||
auto inputArgument = info[0].As<Object>();
|
||||
auto memoryInfo = Ort::MemoryInfo::CreateCpu(OrtDeviceAllocator, OrtMemTypeDefault);
|
||||
for (auto it = inputArgument.begin(); it != inputArgument.end(); ++it) {
|
||||
auto name = (*it).first.As<String>().Utf8Value();
|
||||
auto input = GetInput(name);
|
||||
if (!input) worker->SetError(std::string("input name #" + name + " not exists"));
|
||||
else {
|
||||
auto inputOption = static_cast<Napi::Value>((*it).second).As<Object>();
|
||||
if (!inputOption.Has("data") || !inputOption.Get("data").IsTypedArray()) worker->SetError((std::string("data is required in inputs #" + name)));
|
||||
else {
|
||||
auto type = inputOption.Has("type") ? getDataTypeFromString(inputOption.Get("type").As<String>().Utf8Value()) : input->GetType();
|
||||
size_t dataByteLen;
|
||||
void *data = dataFromTypedArray(inputOption.Get("data"), dataByteLen);
|
||||
auto shape = inputOption.Has("shape") ? GetShapeFromJavascript(inputOption.Get("shape").As<Array>()) : input->GetShape();
|
||||
worker->AddInput(memoryInfo, input->GetName(), type, shape, data, dataByteLen);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto &it : outputs_) {
|
||||
worker->AddOutput(it.second->GetName(), it.second->GetElementBytes());
|
||||
}
|
||||
worker->Queue();
|
||||
|
||||
return info.Env().Undefined();
|
||||
}
|
||||
|
||||
private:
|
||||
static std::vector<int64_t> GetShapeFromJavascript(Napi::Array arr)
|
||||
{
|
||||
std::vector<int64_t> res(arr.Length());
|
||||
for (int i = 0; i < res.size(); ++i) res[i] = arr.Get(i).As<Number>().Int32Value();
|
||||
return res;
|
||||
}
|
||||
|
||||
inline std::shared_ptr<OrtSessionNodeInfo> GetInput(const std::string &name) const
|
||||
{
|
||||
auto it = inputs_.find(name);
|
||||
return (it == inputs_.end()) ? nullptr : it->second;
|
||||
}
|
||||
|
||||
inline std::shared_ptr<OrtSessionNodeInfo> GetOutput(const std::string &name) const
|
||||
{
|
||||
auto it = outputs_.find(name);
|
||||
return (it == outputs_.end()) ? nullptr : it->second;
|
||||
}
|
||||
|
||||
Napi::Value BuildNodeInfoToJavascript(Napi::Env env, const std::map<std::string, std::shared_ptr<OrtSessionNodeInfo>> &nodes)
|
||||
{
|
||||
auto result = Object::New(env);
|
||||
for (auto it : nodes) {
|
||||
auto &node = *it.second;
|
||||
auto item = Object::New(env);
|
||||
item.Set(String::New(env, "name"), String::New(env, node.GetName()));
|
||||
item.Set(String::New(env, "type"), Number::New(env, node.GetType()));
|
||||
auto &shapeVec = node.GetShape();
|
||||
auto shape = Array::New(env, shapeVec.size());
|
||||
for (int i = 0; i < shapeVec.size(); ++i) shape.Set(i, Number::New(env, shapeVec[i]));
|
||||
item.Set(String::New(env, "shape"), shape);
|
||||
result.Set(String::New(env, node.GetName()), item);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
Ort::Env env;
|
||||
Ort::SessionOptions sessionOptions;
|
||||
std::shared_ptr<Ort::Session> session_;
|
||||
std::map<std::string, std::shared_ptr<OrtSessionNodeInfo>> inputs_;
|
||||
std::map<std::string, std::shared_ptr<OrtSessionNodeInfo>> outputs_;
|
||||
};
|
||||
|
||||
void InstallOrtAPI(Napi::Env env, Napi::Object exports)
|
||||
{
|
||||
OrtSession::Init(env, exports);
|
||||
}
|
||||
|
||||
#ifdef USE_ONNXRUNTIME
|
||||
static Object Init(Env env, Object exports)
|
||||
{
|
||||
InstallOrtAPI(env, exports);
|
||||
return exports;
|
||||
}
|
||||
NODE_API_MODULE(addon, Init)
|
||||
|
||||
#endif
|
8
cxx/ort/node.h
Normal file
8
cxx/ort/node.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef __ORT_NODE_H__
|
||||
#define __ORT_NODE_H__
|
||||
|
||||
#include "common/node.h"
|
||||
|
||||
void InstallOrtAPI(Napi::Env env, Napi::Object exports);
|
||||
|
||||
#endif
|
53
cxx/test.cc
Normal file
53
cxx/test.cc
Normal file
@ -0,0 +1,53 @@
|
||||
#include <onnxruntime_cxx_api.h>
|
||||
|
||||
static void buildNames(const std::vector<std::string> &input, std::vector<const char *> &output)
|
||||
{
|
||||
if (input.size() == output.size())
|
||||
return;
|
||||
for (auto &it : input)
|
||||
output.push_back(it.c_str());
|
||||
}
|
||||
|
||||
void test()
|
||||
{
|
||||
static Ort::Env env;
|
||||
static Ort::SessionOptions sessionOptions;
|
||||
static Ort::Session *session_ = new Ort::Session(env, "/home/yizhi/Develop/ai-box/models/test.onnx", sessionOptions);
|
||||
static std::vector<std::string> inputNames_;
|
||||
static std::vector<const char *> inputNames_c_;
|
||||
static std::vector<Ort::Value> inputValues_;
|
||||
static std::vector<std::string> outputNames_;
|
||||
static std::vector<const char *> outputNames_c_;
|
||||
static std::vector<Ort::Value> outputValues_;
|
||||
|
||||
inputNames_.emplace_back("a");
|
||||
inputNames_.emplace_back("b");
|
||||
outputNames_.emplace_back("c");
|
||||
outputValues_.emplace_back(Ort::Value{nullptr});
|
||||
static std::vector<int64_t> shapeA = {3, 4};
|
||||
static std::vector<int64_t> shapeB = {4, 3};
|
||||
static float inputA[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
|
||||
static float inputB[] = {10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120};
|
||||
auto memoryInfo = Ort::MemoryInfo::CreateCpu(OrtDeviceAllocator, OrtMemTypeDefault);
|
||||
inputValues_.emplace_back(Ort::Value::CreateTensor(memoryInfo, inputA, sizeof(inputA), &shapeA[0], shapeA.size(), ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT));
|
||||
inputValues_.emplace_back(Ort::Value::CreateTensor(memoryInfo, inputB, sizeof(inputB), &shapeB[0], shapeB.size(), ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT));
|
||||
buildNames(inputNames_, inputNames_c_);
|
||||
buildNames(outputNames_, outputNames_c_);
|
||||
const char **ptr = &inputNames_c_[0];
|
||||
for (int i = 0; i < inputNames_c_.size(); ++i)
|
||||
{
|
||||
printf("input [%d] = %s\n", i, ptr[i]);
|
||||
}
|
||||
Ort::RunOptions runOption;
|
||||
printf("start run\n");
|
||||
session_->Run(runOption, &inputNames_c_[0], &inputValues_[0], inputNames_.size(), &outputNames_c_[0], &outputValues_[0], outputNames_.size());
|
||||
printf("end run\n");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
Ort::Env env;
|
||||
test();
|
||||
// ai::ORTSession session(nullptr, 0);
|
||||
return 0;
|
||||
}
|
Reference in New Issue
Block a user