opencv C++ onnx 模型如何得到多个输出

有时候咱的模型会输出多个值,怎么拿到呢?
如果只输出一个值,我看很多博客都写了,这篇水文给个例子来看怎么拿到多个返回值

#include <opencv2/core.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/opencv.hpp>

如果你暂时还没搞定 opencv 的 C++ 环境问题,可以看一下介篇水文:
https://blog.csdn.net/HaoZiHuang/article/details/127288350
只针对 Linux/mac 哈,windows 自己搜搜吧hhhh


下边是 onnx 模型前向传播的一个demo

// 读入 onnx 模型
std::string model = "onnx_model/xxxxx.onnx";
cv::dnn::Net net = cv::dnn::readNetFromONNX(model);

// 读图
std::string image_path = 图片路径;
cv::Mat frame = cv::imread(image_path);

// OpenCV预处理图片
const float scalefactor = 1.0;
const bool swapRB = true;
const bool crop = false;
const int ddepth = CV_32F;
cv::Size new_size(960, 540);

cv::Mat input_blob = cv::dnn::blobFromImage(frame, scalefactor, new_size, cv::Scalar(), swapRB, crop, ddepth);

// 设置模型输入
net.setInput(input_blob);
std::vector<cv::Mat> output_probs;
net.forward(output_probs, std::vector<cv::String>{"xx", "keps", "offset", "instance", "mhu"});

单输入与多输入不同的是,要用一个 std::vector<cv::Mat> 来接收一下
同时,forward 的第二个参数要传入一个 std::vector<cv::String> 来拿需要的输出值

但是有时候不知道 onnx 模型的输出怎么办,可以用 Python API 搞一下, 看看输入输出名字:
https://blog.csdn.net/HaoZiHuang/article/details/126168132

from pprint import pprint
import onnxruntime

onnx_path = "xxxx.onnx"

provider = "CPUExecutionProvider"
onnx_session = onnxruntime.InferenceSession(onnx_path, providers=[provider])

print("----------------- 输入部分 -----------------")
input_tensors = onnx_session.get_inputs()  # 该 API 会返回列表
for input_tensor in input_tensors:         # 因为可能有多个输入,所以为列表
    
    input_info = {
        "name" : input_tensor.name,
        "type" : input_tensor.type,
        "shape": input_tensor.shape,
    }
    pprint(input_info)

print("----------------- 输出部分 -----------------")
output_tensors = onnx_session.get_outputs()  # 该 API 会返回列表
for output_tensor in output_tensors:         # 因为可能有多个输出,所以为列表
    
    output_info = {
        "name" : output_tensor.name,
        "type" : output_tensor.type,
        "shape": output_tensor.shape,
    }
    pprint(output_info)

----------------- 输入部分 -----------------
{'name': 'input', 'shape': [1, 3, 540, 960], 'type': 'tensor(float)'}
----------------- 输出部分 -----------------
{'name': 'xx', 'shape': [1, 1, 168, 120], 'type': 'tensor(float)'}
{'name': 'keps', 'shape': [1, 1, 168, 120], 'type': 'tensor(float)'}
{'name': 'offset', 'shape': [1, 2, 168, 120], 'type': 'tensor(float)'}
{'name': 'instance', 'shape': [1, 16, 168, 120], 'type': 'tensor(float)'}
{'name': 'mhu', 'shape': [1, 9, 168, 120], 'type': 'tensor(float)'}

把那几个输出的名字传入就行

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 好的,这是一个比较复杂的任务,需要分几个步骤来完成。下面是大致的步骤: 1. 使用 C++ 编写动态链接库封装 YOLOv5,可以使用 OpenCV 库来读取图像和进行预处理。 2. 导入 ONNX 模型,可以使用 ONNX Runtime 库来加载和运行 ONNX 模型。 3. 实现前向推理代码,将输入图像喂给 ONNX 模型,并获取输出结果。 4. 将输出结果进行解析,得到检测框和分类结果。 5. 使用 LaView 软件进行调用和测试。 下面是详细的步骤: 1. 使用 C++ 编写动态链接库封装 YOLOv5,可以使用 OpenCV 库来读取图像和进行预处理。 首先,需要下载 YOLOv5 的源码,并编译生成可执行文件。然后,将可执行文件中的预测部分封装成一个动态链接库,提供给其他程序调用。 以下是一个简单的示例代码,它使用 OpenCV 库读取图像,对图像进行预处理(将图像缩放到模型输入大小),并将预处理后的图像传递给 YOLOv5 进行预测: ```cpp #include "yolov5.h" #include <opencv2/opencv.hpp> YoloV5::YoloV5() { // 初始化 YOLOv5 模型 // ... } std::vector<ObjectDetectionResult> YoloV5::detect(const cv::Mat& image) { // 对图像进行预处理 cv::Mat input_image; cv::resize(image, input_image, cv::Size(640, 640)); // 将图像缩放到模型输入大小 // 将输入图像传递给 YOLOv5 进行预测 // ... // 解析输出结果,得到检测框和分类结果 std::vector<ObjectDetectionResult> results; // ... return results; } ``` 2. 导入 ONNX 模型,可以使用 ONNX Runtime 库来加载和运行 ONNX 模型。 首先,需要将 YOLOv5 的 PyTorch 模型导出为 ONNX 格式。然后,可以使用 ONNX Runtime 库来加载和运行 ONNX 模型。 以下是一个简单的示例代码,它使用 ONNX Runtime 库加载和运行 ONNX 模型: ```cpp #include <onnxruntime_cxx_api.h> Ort::Env env(ORT_LOGGING_LEVEL_WARNING, "test"); // 初始化 ONNX Runtime 环境 Ort::SessionOptions session_options; session_options.SetIntraOpNumThreads(1); session_options.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_ALL); Ort::Session session(env, "model.onnx", session_options); // 加载 ONNX 模型 Ort::AllocatorWithDefaultOptions allocator; // 准备输入数据 std::vector<int64_t> input_shape = {1, 3, 640, 640}; Ort::Value input_tensor = Ort::Value::CreateTensor<float>(allocator, input_data.data(), input_shape.data(), input_shape.size()); // 运行模型 auto output_tensors = session.Run(Ort::RunOptions{nullptr}, input_names.data(), &input_tensor, input_names.size(), output_names.data(), output_names.size()); ``` 3. 实现前向推理代码,将输入图像喂给 ONNX 模型,并获取输出结果。 在使用 ONNX Runtime 运行 ONNX 模型之前,需要先准备输入数据,然后将输入数据传递给模型。在获取输出结果后,需要对输出结果进行解析,得到检测框和分类结果。 以下是一个简单的示例代码,它实现了前向推理代码: ```cpp #include <onnxruntime_cxx_api.h> std::vector<ObjectDetectionResult> YoloV5::detect(const cv::Mat& image) { // 对图像进行预处理 cv::Mat input_image; cv::resize(image, input_image, cv::Size(640, 640)); // 将图像缩放到模型输入大小 // 准备输入数据 std::vector<float> input_data = prepare_input_data(input_image); // 运行模型 auto output_tensors = session.Run(Ort::RunOptions{nullptr}, input_names.data(), &input_tensor, input_names.size(), output_names.data(), output_names.size()); // 解析输出结果,得到检测框和分类结果 std::vector<ObjectDetectionResult> results = parse_output_data(output_tensors); return results; } ``` 4. 将输出结果进行解析,得到检测框和分类结果。 解析输出结果是实现动态链接库的一个重要部分。在解析输出结果之前,需要先了解模型输出格式。 YOLOv5 模型输出格式为一个包含多个数组的结构体,每个数组对应一个输出层的输出。每个数组的形状为 (batch_size, num_anchors * (num_classes + 5), grid_size, grid_size),其中,batch_size 为 1,num_anchors 为每个格子预测的锚框数量,num_classes 为类别数量,grid_size 为输出特征图的大小。 以下是一个简单的示例代码,它解析了 YOLOv5 模型输出结果,得到检测框和分类结果: ```cpp #include <onnxruntime_cxx_api.h> std::vector<ObjectDetectionResult> YoloV5::parse_output_data(const Ort::Value& output_tensor) { std::vector<ObjectDetectionResult> results; // 获取输出数据 auto output_data = output_tensor.GetTensorMutableData<float>(); // 解析输出数据 // ... return results; } ``` 5. 使用 LaView 软件进行调用和测试。 最后,可以使用 LaView 软件调用动态链接库,并测试模型的性能和准确度。 在 LaView 中,可以使用 DLL 节点调用动态链接库,通过设置节点的输入和输出参数,将图像传递给动态链接库,获取检测框和分类结果。 以下是一个简单的示例代码,它在 LaView 中使用 DLL 节点调用动态链接库: ```cpp #include <opencv2/opencv.hpp> #include "yolov5.h" YoloV5 yolo_v5; int main() { // 读取图像 cv::Mat image = cv::imread("test.jpg"); // 调用动态链接库进行检测 auto results = yolo_v5.detect(image); // 显示结果 for (auto& result : results) { cv::rectangle(image, result.rect, cv::Scalar(0, 255, 0), 2); cv::putText(image, result.label, result.rect.tl(), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(0, 0, 255), 2); } cv::imshow("result", image); cv::waitKey(0); return 0; } ``` ### 回答2: 首先,编写动态链接库封装yolov5可以按以下步骤操作: 1. 下载yolov5的源码并解压。 2. 在C语言中创建一个动态链接库的项目。 3. 在项目中包含yolov5的源码文件,并根据需要进行配置。 4. 编写C语言代码来调用yolov5的函数和方法,例如加载模型、进行目标检测等。 5. 编译项目生成动态链接库文件(.dll或.so文件)。 然后,导入onnx模型可以按以下步骤操作: 1. 将onnx模型文件拷贝到你的项目文件夹中。 2. 在C代码中使用相应的库来导入onnx模型。 3. 调用相应的函数或方法来加载导入的模型。 最后,使用laview进行调用测试可以按以下步骤操作: 1. 下载laview,并安装到你的计算机上。 2. 在laview中创建一个测试项目,导入你编写的动态链接库文件。 3. 使用laview提供的界面和功能,调用动态链接库中的函数来进行yolov5目标检测测试。 4. 检查测试结果,并根据需要进行调试和优化。 总之,根据以上步骤,你可以使用C语言编写动态链接库封装yolov5,导入onnx模型,并使用laview进行调用测试。 ### 回答3: 要使用C语言编写动态链接库封装Yolov5并导入ONNX模型,可以按照以下步骤进行: 1. 首先,你需要了解Yolov5的模型结构和ONNX模型的导入方式。Yolov5是一个目标检测算法,可以使用C语言实现其网络结构和相关函数。而ONNX模型可以使用相关的C库导入并进行推理。 2. 在C语言中,你需要编写一个动态链接库,其中封装了Yolov5的模型结构和相关函数。你可以创建一个名为"yolov5.c"的文件,并在其中实现Yolov5的网络结构和相关函数。 3. 下一步是导入ONNX模型。你可以使用ONNX Runtime库来加载ONNX模型,并进行推理。在"yolov5.c"文件中,你需要添加相应的ONNX Runtime库的引用,并编写导入ONNX模型的代码。 4. 在导入ONNX模型后,你可以使用LaView库进行调用和测试。LaView是一个图像处理库,可以用于在视觉算法中加载和处理图像数据。你可以在"yolov5.c"文件中添加相应的LaView库的引用,并编写相应的调用和测试代码。 5. 最后,你需要编译动态链接库。使用适当的编译器命令,将"yolov5.c"文件编译成动态链接库。确保将ONNX Runtime库和LaView库链接到动态链接库中。 完成以上步骤后,你就可以使用这个动态链接库进行Yolov5的目标检测,并使用LaView库对图像进行处理和展示。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值