于c++中使用onnxruntime调用ppyoloe的onnx模型

于c++中使用onnxruntime调用ppyoloe的onnx模型

因为项目中要用到百度飞浆训练好的模型,但苦于opencv似乎无法直接导入,所以自己写了一个类,方便后续需要的时候调用所有onnx模型

#include "onnxruntime_cxx_api.h"
#include "onnxruntime_c_api.h"
#include "opencv2/opencv.hpp"

#ifdef _WIN32
typedef std::wstring ortstring;
#else
typedef std::string ortstring;
#endif

#define NUM_THREADS 1

using namespace std;

class OnnxModel{
public:
    OnnxModel(ortstring Path){
        this->Enviro = Ort::Env(ORT_LOGGING_LEVEL_ERROR, "Defalut");
        this->SessOpts = Ort::SessionOptions();
        this->SessOpts.SetIntraOpNumThreads(NUM_THREADS);

        Ort::AllocatorWithDefaultOptions Allocator;
        this->Sess = new Ort::Session(Enviro, Path.c_str(), SessOpts);

        //获取输入、输出的数量
        this->InputCount = this->Sess->GetInputCount();
        this->OutputCount = this->Sess->GetOutputCount();

        //获取onnx输入名
        for(int i = 0;i < InputCount;i++){
            InputName.push_back(this->Sess->GetInputName(i, Allocator));
        }

        //获取onnx输出名
        for(int i = 0;i < OutputCount;i++){
            OutputName.push_back(this->Sess->GetOutputName(i, Allocator));
        }

        //获取onnx输入格式
        std::vector<std::vector<int64_t> > InputDims;
        for(int i = 0;i < this->InputCount;i++){
            std::vector<int64_t> Shape = this->Sess->GetInputTypeInfo(i).GetTensorTypeAndShapeInfo().GetShape();

            //不定长batchsize改成定长且为1
            Shape[0] = 1;
            this->InputDims.push_back(Shape);
        }
    }


    //对预处理完的图像进行推理
    std::vector<vector<float> > Predict(cv::Mat Src){
        std::vector<vector<float> >InputData = this->PreProcess(Src);
        Ort::MemoryInfo MemInfo = Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault);

        //创建输入tensor
        std::vector<Ort::Value> InputTensor;
        for(int i = 0;i < this->InputCount;i++){
            std::vector<int64_t>& InputDim = this->InputDims[i];
            InputTensor.push_back(Ort::Value::CreateTensor<float>(MemInfo, InputData[i].data(),
                InputData[i].size(), InputDim.data(), InputDim.size()));
        }

        //进行推理
        auto OutputTensor = this->Sess->Run(Ort::RunOptions{nullptr}, this->InputName.data(),
            InputTensor.data(), this->InputCount, this->OutputName.data(), this->OutputCount);

        //获取推理结果
        std::vector<vector<float> > OutputDatas;
        for(int i = 0;i < this->OutputCount;i++){
            float* TempFloat = OutputTensor[i].GetTensorMutableData<float>();
            size_t TempLen = OutputTensor[i].GetTensorTypeAndShapeInfo().GetElementCount();
            std::vector<float> OutputData;
            for(int j = 0;j < TempLen;j++){
                OutputData.push_back(TempFloat[j]);
            }
            OutputDatas.push_back(OutputData);
        }
        return OutputDatas;
    }

protected:
    //对图像预处理
    virtual std::vector<vector<float> > PreProcess(cv::Mat& Src) = 0;

private:
    Ort::Env Enviro;
    Ort::SessionOptions SessOpts;
    Ort::Session* Sess{nullptr};
    size_t InputCount;
    size_t OutputCount;
    std::vector<std::vector<int64_t> > InputDims;
    std::vector<const char*> InputName;
    std::vector<const char*> OutputName;
    OnnxModel() = delete;
};

/*****************另一个文件中调用,调用模型为ppyoloe下的行人检测************************/
#include <iostream>
#include "opencv2/opencv.hpp"
#include "onnxruntime_cxx_api.h"
#include "onnxruntime_c_api.h"
#include "onnxmodel.h"
using namespace cv;

class HumanDetect:public OnnxModel{
public:
    HumanDetect(std::wstring Path):OnnxModel(Path){};

private:
	//自己重写预处理函数
    virtual std::vector<vector<float> > PreProcess(Mat& Src){
        vector<vector<float> > Result;

        Mat Dst = dnn::blobFromImage(Src, 1.0,Size(640,640),Scalar());
        vector<float> TempFloat;
        for(int i = 0;i < Dst.total();i++){
            TempFloat.push_back(*(Dst.ptr<float>()+i));
        }
        Result.push_back(TempFloat);

        vector<float> TempScalar = { 640.0f / Src.rows,640.0f / Src.cols };
        Result.push_back(TempScalar);
        return Result;
    }
};
int main(){
    std::wstring Path = L"./model/humandetect.onnx";
    HumanDetect HD(Path);
    cv::Mat temp = cv::imread("./1.jpg");
    vector<vector<float>> Result = HD.Predict(temp);

}
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
Onnxruntime是一个用于推理和训练的开源深度学习库,它支持多种硬件平台和编程语言,包括C++。要在C++使用Onnxruntime进行半精度推理,你需要按照以下步骤进行操作: 1. 首先,确保你已经安装了Onnxruntime库。你可以从Onnxruntime的官方GitHub页面下载并编译源代码,或者使用预编译的二进制文件。 2. 在你的C++项目,包含Onnxruntime的头文件和库文件。你可以在编译选项添加Onnxruntime的头文件路径和库文件路径,或者将它们复制到你的项目目录。 3. 加载和初始化模型。在C++,你可以使用onnxruntime::InferenceSession类来加载和运行模型使用onnxruntime::SessionOptions类可以设置推理选项,包括精度设置。 4. 设置输入数据。使用onnxruntime::RunOptions类可以设置运行选项,包括精度设置。使用onnxruntime::Value类可以创建和设置输入数据。 5. 执行推理。调用onnxruntime::InferenceSession的Run函数来执行推理。在Run函数,你可以指定输入和输出张量的名称,以及精度设置。 6. 获取输出结果。使用onnxruntime::Value类可以获取输出数据。 7. 清理资源。在推理完成后,记得释放所有分配的资源。 需要注意的是,在进行半精度推理时,你需要确保模型已经经过了半精度训练,并且Onnxruntime版本支持使用半精度进行推理。你可以查阅Onnxruntime的官方文档,了解更多关于在C++使用Onnxruntime进行推理的详细信息和示例代码。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值