onnxruntime yolov5s
时间: 2023-10-26 12:03:04 浏览: 63
ONNX Runtime是一个高性能、跨平台的推理引擎,用于在各种硬件和操作系统上运行机器学习模型。YOLOv5s是一种轻量级的目标检测模型,具有较快的推理速度和较高的准确率。
在使用ONNX Runtime运行YOLOv5s时,首先需要将YOLOv5s模型转换为ONNX格式。这可以通过使用YOLOv5官方提供的工具或用其他框架(如PyTorch或TensorFlow)实现的脚本来完成。转换后的ONNX模型将包含YOLOv5s网络架构的图像和权重。
然后,将转换后的ONNX模型加载到ONNX Runtime中,准备进行推理。可以使用ONNX Runtime提供的C++、Python或C# API来加载模型,并设置相应的推理会话。之后,可以将输入数据传递给模型,并使用ONNX Runtime进行推理。在YOLOv5s中,输入数据是图像,可以是单个图像或一批图像。
当推理过程开始时,ONNX Runtime会根据YOLOv5s模型的结构和权重,在输入图像上执行前向计算。这将产生包含检测到的目标及其位置的边界框。在YOLOv5s中,这些目标可以是各种物体,如人、车辆、动物等。
最后,ONNX Runtime会返回推理结果,即检测到的目标边界框。可以通过解析这些结果来获取检测到的目标的类别和位置信息。针对每个目标,可以提取其类别标签和在图像中的位置(边界框的左上角和右下角坐标)。
综上所述,ONNX Runtime可以用于加载、执行和推理YOLOv5s模型,以便检测图像中的目标。它提供了一个跨平台的解决方案,使得运行YOLOv5s模型的推理过程变得高效、灵活且易于使用。
相关问题
onnxruntime c++部署yolov5
### 回答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模型的基本步骤。当然,如果我们要获得更高的精度和更快的速度,还可以使用各种技术来优化模型和代码。
onnxruntime c++部署yolov5 seg
对于部署 YOLOv5 Segmentation 模型,可以通过以下步骤:
1. 将模型转换成 ONNX 格式
使用 PyTorch 软件包将 YOLOv5 Segmentation 模型训练并导出为 ONNX 格式。可以使用以下 Python 代码:
```
import torch
model = torch.hub.load('ultralytics/yolov5', 'yolov5s', pretrained=True)
model.eval()
# Export the model to ONNX format
torch.onnx.export(model, # PyTorch model
torch.rand(1, 3, 640, 640), # Input tensor shape
"yolov5s.onnx", # Output ONNX model name
export_params=True) # Export weights and biases
```
2. 使用 ONNX Runtime 部署模型
使用 ONNX Runtime C API,可以部署 ONNX 模型。可以使用以下 C++ 代码:
```
#include <stdio.h>
#include <assert.h>
#include <fstream>
#include <iostream>
#include <vector>
#include "onnxruntime_c_api.h"
int main()
{
OrtEnv* env;
OrtCreateEnv(ORT_LOGGING_LEVEL_WARNING, "test", &env);
OrtSession* session;
OrtStatus* status;
const char* model_path = "yolov5s.onnx";
OrtSessionOptions* session_options;
OrtCreateSessionOptions(&session_options);
status = OrtSessionOptionsAppendExecutionProvider_CPU(session_options, ORT_ENABLE_ALL);
status = OrtCreateSession(env, model_path, session_options, &session);
OrtMemoryInfo* memory_info;
OrtCreateCpuMemoryInfo(OrtArenaAllocator, OrtMemTypeDefault, &memory_info);
// Prepare input
OrtValue* input_tensor = NULL;
size_t input_size = 1 * 3 * 640 * 640;
void* input_data = malloc(input_size);
// TODO: Populate input_data with image data in BGR format
status = OrtCreateTensorWithDataAsOrtValue(memory_info, input_data, input_size, {1, 3, 640, 640}, ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT, &input_tensor);
// Prepare output
OrtValue* output_tensor = NULL;
const char* output_name = "output"; // TODO: Replace with the actual output name of the YOLOv5 Segmentation model
status = OrtSessionGetOutputCount(session, &output_count);
std::vector<const char*> output_names(output_count);
std::vector<int64_t> output_shapes(output_count);
for (int i = 0; i < output_count; i++) {
char* output_name_temp;
status = OrtSessionGetOutputName(session, i, memory_info, &output_name_temp);
assert(status == NULL);
output_names[i] = output_name_temp;
OrtTensorTypeAndShapeInfo* output_info;
OrtSessionGetOutputTypeInfo(session, i, &output_info);
assert(status == NULL);
size_t num_dims;
OrtTensorTypeAndShapeInfoGetShape(output_info, &output_shapes[i], 1, &num_dims);
assert(status == NULL);
OrtReleaseTensorTypeAndShapeInfo(output_info);
}
status = OrtSessionRun(session, NULL, &input_names[0], &input_tensors[0], 1, &output_names[0], 1, &output_tensor);
assert(status == NULL);
// TODO: Process output_tensor
// Clean up
OrtReleaseValue(input_tensor);
OrtReleaseValue(output_tensor);
OrtReleaseSession(session);
OrtReleaseSessionOptions(session_options);
OrtReleaseMemoryInfo(memory_info);
OrtReleaseEnv(env);
free(input_data);
return 0;
}
```
3. 处理输出张量
YOLOv5 Segmentation 模型的输出张量是一个 4 维的张量,形状为 `[batch_size, num_classes, height, width]`,其中 `batch_size` 表示批大小,`num_classes` 表示类别数量,`height` 和 `width` 表示图像中每个像素的标签。可以使用以下 C++ 代码来解析输出张量:
```
OrtStatus* status;
float* output_data = OrtGetFloatPtr(output_tensor, &num_elements);
status = OrtGetValueCount(output_tensor, &output_count);
assert(status == NULL);
const int num_classes = output_shapes[1];
const int height = output_shapes[2];
const int width = output_shapes[3];
std::vector<int> predictions(num_elements);
for (int i = 0; i < num_elements; i++) {
predictions[i] = (int) (output_data[i] * num_classes);
}
// TODO: Process predictions
```
4. 可视化分割结果
可以使用 OpenCV C++ 库来可视化分割结果,代码如下:
```
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
// TODO: Replace with the actual image path
const char* image_path = "test.jpg";
// TODO: Replace with the actual output post-processing code
std::vector<int> predictions = postprocess_output(output_data, output_shapes);
cv::Mat image = cv::imread(image_path);
cv::Mat seg_image(height, width, CV_8UC3, cv::Scalar(0, 0, 0));
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int prediction = predictions[y * width + x];
if (prediction == 0) {
seg_image.at<cv::Vec3b>(y, x) = cv::Vec3b(255, 255, 255); // Background
} else {
seg_image.at<cv::Vec3b>(y, x) = cv::Vec3b(0, 0, 255); // Object
}
}
}
cv::Mat result;
cv::addWeighted(image, 0.5, seg_image, 0.5, 0, result);
cv::imshow("Result", result);
cv::waitKey(0);
cv::destroyAllWindows();
```