onnxruntime c++部署yolov5
时间: 2023-05-31 08:19:04 浏览: 307
### 回答1:
首先,您需要将Yolov5模型转换为ONNX格式。您可以使用PyTorch将模型转换为ONNX格式,然后使用ONNX Runtime C++ API加载和运行模型。
以下是一些步骤:
1. 安装PyTorch和ONNX Runtime
2. 使用PyTorch将Yolov5模型转换为ONNX格式。您可以使用以下代码:
```
import torch
import torchvision
# Load the model
model = torch.hub.load('ultralytics/yolov5', 'yolov5s', pretrained=True)
# Export the model to ONNX format
input_shape = (1, 3, 640, 640)
torch.onnx.export(model, torch.randn(*input_shape), "yolov5s.onnx", opset_version=11)
```
3. 在C++中加载和运行模型。您可以使用以下代码:
```
#include <iostream>
#include <vector>
#include <chrono>
#include <opencv2/opencv.hpp>
#include "onnxruntime_cxx_api.h"
using namespace std;
using namespace cv;
using namespace std::chrono;
using namespace onnxruntime;
int main() {
// Load the model
Ort::SessionOptions session_options;
session_options.SetIntraOpNumThreads(1);
session_options.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_ALL);
Ort::Env env(ORT_LOGGING_LEVEL_WARNING, "test");
Ort::Session session(env, "yolov5s.onnx", session_options);
// Get input and output names
auto input_names = session.GetInputNames();
auto output_names = session.GetOutputNames();
// Create input tensor
Ort::AllocatorWithDefaultOptions allocator;
Ort::Value input_tensor(nullptr);
Ort::MemoryInfo memory_info = Ort::MemoryInfo::CreateCpu(OrtDeviceAllocator, OrtMemTypeCPU);
vector<int64_t> input_shape = {1, 3, 640, 640};
input_tensor = Ort::Value::CreateTensor<float>(memory_info, reinterpret_cast<float*>(new float[input_shape[0] * input_shape[1] * input_shape[2] * input_shape[3]]), input_shape.data(), input_shape.size());
// Load image
Mat image = imread("test.jpg");
cvtColor(image, image, COLOR_BGR2RGB);
resize(image, image, Size(640, 640));
float* input_data = input_tensor.GetTensorMutableData<float>();
for (int i = 0; i < 640 * 640 * 3; i++) {
input_data[i] = image.data[i] / 255.0;
}
// Run inference
auto start = high_resolution_clock::now();
vector<Ort::Value> output_tensors = session.Run(output_names, &input_names[0], &input_tensor, 1);
auto end = high_resolution_clock::now();
auto duration = duration_cast<milliseconds>(end - start);
cout << "Inference time: " << duration.count() << " ms" << endl;
// Get output tensor
Ort::Value& output_tensor = output_tensors[0];
float* output_data = output_tensor.GetTensorMutableData<float>();
// Process output
for (int i = 0; i < 25200; i++) {
if (output_data[i * 6 + 4] > 0.5) {
int x1 = output_data[i * 6 + 0] * 640;
int y1 = output_data[i * 6 + 1] * 640;
int x2 = output_data[i * 6 + 2] * 640;
int y2 = output_data[i * 6 + 3] * 640;
cout << "Object detected: " << output_data[i * 6 + 5] << " (" << x1 << ", " << y1 << ") (" << x2 << ", " << y2 << ")" << endl;
}
}
return 0;
}
```
这个例子假设您有一张名为“test.jpg”的图像,它将被用作模型的输入。它还假设您的模型输出是一个大小为[1, 25200, 6]的张量,其中25200是预测的边界框数,6是每个边界框的属性数(左上角和右下角坐标,置信度和类别)。
请注意,这只是一个简单的例子,您需要根据您的模型和数据进行适当的修改。
### 回答2:
在使用ONNXRuntime C部署Yolov5之前,首先需要明确的是Yolov5是目标检测算法,而ONNXRuntime C则是一个高性能的推理框架,可以用来推理基于ONNX格式的深度学习模型,这包括Yolov5。
以下是ONNXRuntime C部署Yolov5的步骤参考:
1. 转换模型:由于Yolov5模型原先是以PyTorch格式存储,因此需要将其转化为ONNX格式。具体的转换方法可以参考ONNX官方文档,或者使用现成的转换脚本,如https://github.com/jkjung-avt/yolov5_onnx/blob/main/yolov5_onnx.py。
2. 编写C程序:根据ONNXRuntime C的API,编写C语言程序实现Yolov5模型的加载和推理。可以参考ONNXRuntime官方示例中的代码模板,进行修改和调整,完成模型的加载和推理功能。关键代码如下:
```c
// 运行初始化,加载模型
OrtEnv* env;
OrtCreateEnv(ORT_LOGGING_LEVEL_WARNING, "test", &env);
OrtSessionOptions* session_options = OrtCreateSessionOptions();
OrtSession* session;
OrtCreateSession(env, model_path, session_options, &session);
// 获取模型输入输出信息
OrtStatus* status;
OrtTensorTypeAndShapeInfo* input_info;
OrtSessionGetInputTypeInfo(session, 0, &input_info);
OrtAllocator* allocator;
OrtCreateDefaultAllocator(&allocator);
size_t num_inputs;
OrtStatus* get_num_input = OrtSessionGetInputCount(session, &num_inputs);
OrtValue** input_tensor = (OrtValue**)malloc(num_inputs * sizeof(OrtValue*));
OrtStatus* input_status = OrtCreateTensorAsOrtValue(allocator, input_info, &input_tensor[0]);
OrtTypeInfo* type_info;
OrtStatus* output_status = OrtSessionGetOutputTypeInfo(session, 0, &type_info);
// 给输入tensor赋值
float* input = input_tensor[0]->GetTensorMutableData<float>();
for (int i = 0; i < input_size; i++) {
input[i] = input_data[i];
}
// 运行模型,获取结果
OrtValue* output_tensor = NULL;
const char* output_names[] = { output_name };
OrtStatus* run_status = OrtRun(session, NULL, input_names, &input_tensor[0], num_inputs, output_names, 1, &output_tensor);
float* output = output_tensor->GetTensorMutableData<float>();
```
3. 编译C程序:使用C编译器,如gcc,编译C程序,并将ONNXRuntime C的库文件链接到程序中,如:
```bash
gcc main.c -lonnxruntime
```
4. 运行C程序:运行编译后的程序,并输入Yolov5需要检测的图片或视频数据,程序将输出检测结果,包括检测框、置信度和类别等信息。
需要注意的几个点:
1. ONNXRuntime C需要先安装ONNXRuntime库,并将其包含到系统路径中。
2. 在程序中需要指定Yolov5的输入尺寸和类别数等信息。
3. 在使用Yolov5推理时,需要先对输入数据进行预处理,如尺寸缩放、通道变换和数据类型转换等。
4. 在编程时,需要对ONNXRuntime C的API进行深入学习,以保证程序的正确性和稳定性。同时,还需要对Yolov5的算法和原理有一定的了解,以便进行模型的参数调整和优化。
### 回答3:
随着深度学习的广泛应用,越来越多的框架和工具被开发出来,但由于它们之间的差异,将模型从一个框架转换到另一个框架是一项具有挑战性和耗费时间的工作。ONNX(Runtime)是一种广泛接受的中间表示,它可以使不同的框架之间的模型转换变得容易。这篇文章将介绍如何使用ONNXRuntime C++ API来部署一个YOLOv5的模型。
首先,我们需要下载YOLOv5模型的权重和cfg文件,可以从Github上的YOLOv5仓库中下载。在下载完这两个文件后,我们需要用Python中的train.py将它们转换成ONNX文件,具体地,可以使用如下命令:
```
python3 train.py --weights yolov5s.pt --cfg models/yolov5s.yaml --img 640 --batch 1 --no-autoanchor --fuse
python3 models/yolo.py --cfg models/yolov5s.yaml --weights yolov5s.pt --names models/coco.names
```
这将生成名为“yolov5s.onnx”的模型文件。现在,我们可以使用ONNXRuntime C++ API加载和运行它。
首先,我们需要在C++中安装ONNXRuntime的API,可以从官方网站(https://www.onnxruntime.ai/)下载ONNXRuntime C++ API安装文件。安装完成后,我们可以开始编写C++代码来加载和运行YOLOv5模型。
我们需要使用以下头文件:
```
#include "onnxruntime_cxx_api.h"
#include <opencv2/opencv.hpp>
```
接下来,我们需要定义一些变量来存储模型信息。我们可以使用onnxruntime::Env类初始化ONNXRuntime。
```
std::string model_path = "yolov5s.onnx";
std::shared_ptr<onnxruntime::Environment> env = onnxruntime::Environment::Create();
```
然后,我们需要创建一个会话,该会话将包含模型。通过onnxruntime::Session类,我们可以加载模型并返回一个会话句柄。
```
std::shared_ptr<onnxruntime::Session> session = std::make_shared<onnxruntime::Session>(*env, model_path, nullptr);
```
我们还需要创建一个输入模型。我们需要使用onnxruntime::Tensor类,它将用于加载输入数据。
```
std::vector<int64_t> input_node_dims = { 1, 3, 640, 640 };
auto memory_info = onnxruntime::MemoryInfo::CreateCpu(ONNXRUNTIME_CPU, onnxruntime::DeviceAllocatorRegistrationFlags::None);
auto input_tensor = onnxruntime::make_unique<onnxruntime::Tensor>(onnxruntime::DataType::Float, onnxruntime::TensorShape(input_node_dims), memory_info);
```
现在,我们有了将图像转换为ONNX模型所需的一切。我们需要加载图像,将其尺寸调整为模型的输入大小,并使用OpenCV库将图像像素值转换为浮点数。然后我们可以将数据复制到输入_tensor中。
```
cv::Mat img = cv::imread("test.jpg");
cv::resize(img, img, cv::Size(640, 640), cv::INTER_AREA);
img.convertTo(img, CV_32FC3, 1 / 255.0);
memcpy(input_tensor->MutableData<float>(), img.data, img.total() * img.elemSize());
```
现在,我们可以将输入_tensor传递给模型并运行。
```
std::vector<const char*> input_node_names = { "input" };
std::vector<const char*> output_node_names = { "output" };
std::vector<OrtValue> output_tensors;
OrtTensorScales scales = { nullptr, 0 };
session->Run(Ort::RunOptions{ nullptr }, input_node_names.data(), &input_tensor, input_node_dims.size(), output_node_names.data(), output_node_names.size(), output_tensors, scales);
```
最后,我们可以使用输出张量中的数据进行后处理,以获得目标框位置和类别预测结果等信息。
这些就是使用ONNXRuntime C++ API来部署YOLOv5模型的基本步骤。当然,如果我们要获得更高的精度和更快的速度,还可以使用各种技术来优化模型和代码。
阅读全文