于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
    评论
使用OpenCV调用ONNX需要以下步骤: 1. 首先,确保已经安装了OpenCV和ONNX的库和依赖项,并且正确地配置了环境变量。 2. 导入必要的库文件,包括opencv2和onnxruntime。 3. 加载ONNX模型使用onnxruntime的InferenceSession类加载ONNX模型,将模型文件路径作为参数传递给构造函数。 4. 准备输入数据。根据模型的输入要求,准备输入数据。可以从图像文件读取图像数据,然后调整大小和归一化。 5. 运行推理。使用OpenCV的cv::dnn::Net类创建网络,并使用onnx模型初始化。将准备好的图像数据传递给网络,然后调用前向传播方法。 6. 获取输出结果。从网络获取输出结果,可以通过cv::Mat对象来处理和显示。 7. 后处理。根据模型的输出要求,对输出进行后处理,例如解码类别标签或进行特定的处理。 8. 显示结果。可以使用OpenCV的函数显示结果图像,例如cv::imshow或cv::imwrite。 需要注意的是,ONNX模型的输入和输出要求可能有所不同,因此在调用模型之前,需要仔细了解模型的结构和要求。此外,还应该处理异常情况,例如模型加载失败或输入数据不符合要求的情况。 总结起来,使用OpenCV调用ONNX模型需要加载模型、准备输入数据、运行推理、获取输出结果、后处理和显示结果等步骤。通过仔细理解模型的要求和OpenCV的接口,可以成功地调用ONNX模型

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值