当前位置: 首页 > news >正文

yolov8 模型部署--TensorRT部署-c++服务化部署

写目录

  • yolov8 模型部署--TensorRT部署
    • 1、模型导出为onnx格式
    • 2、模型onnx格式转engine 部署

yolov8 模型部署–TensorRT部署

1、模型导出为onnx格式

  • 如果要用TensorRT部署YOLOv8,需要先使用下面的命令将模型导出为onnx格式:

    yolo export model=yolov8n.pt format=onnx 
    
  • YOLOv8的3个检测头一共有80x80+40x40+20x20=8400个输出单元格,每个单元格包含x,y,w,h这4项再加80个类别的置信度总共84项内容,所以通过上面命令导出的onnx模型的输出维度为1x84x8400

  • 模型输出维度
    在这里插入图片描述

  • 这样的通道排列顺序有个问题,那就是后处理的时候会造成内存访问不连续。

  • 为了解决这个问题,我们可以修改一下代码,具体做法是把ultralytics/nn/modules.py文件中的代码做如下修改,交换一下张量y的通道顺序:

    def forward(self, x):shape = x[0].shape  # BCHWfor i in range(self.nl):x[i] = torch.cat((self.cv2[i](x[i]), self.cv3[i](x[i])), 1)if self.training:return xelif self.dynamic or self.shape != shape:self.anchors, self.strides = (x.transpose(0, 1) for x in make_anchors(x, self.stride, 0.5))self.shape = shapex_cat = torch.cat([xi.view(shape[0], self.no, -1) for xi in x], 2)if self.export and self.format in ('saved_model', 'pb', 'tflite', 'edgetpu', 'tfjs'):  # avoid TF FlexSplitV opsbox = x_cat[:, :self.reg_max * 4]cls = x_cat[:, self.reg_max * 4:]else:box, cls = x_cat.split((self.reg_max * 4, self.nc), 1)dbox = dist2bbox(self.dfl(box), self.anchors.unsqueeze(0), xywh=True, dim=1) * self.stridesy = torch.cat((dbox, cls.sigmoid()), 1)# 修改模型输出维度y=y.permute(0,2,1)return y if self.export else (y, x)

在这里插入图片描述

  • 这样修改后再执行上面的模型导出命令,模型的输出维度变为1x8400x84
    在这里插入图片描述

2、模型onnx格式转engine 部署

  • 配置好TensorRTNVIDIA环境
  • 使用trtexec 转换格式
    trtexec --onnx=coco/best.onnx --saveEngine=coco/best.onnx.engine --workspace=32 
    
  • 模型部署部分代码-c++
    #ifndef MyController_hpp
    #define MyController_hpp#include <ctime>
    #include <chrono>
    #include <sstream>
    #include <iomanip>#include <iostream>
    #include <numeric>
    #include <vector>#include "oatpp/web/server/api/ApiController.hpp"
    #include "oatpp/core/macro/codegen.hpp"
    #include "oatpp/core/macro/component.hpp"#include "opencv2/opencv.hpp"
    #include "../dto/DTOs.hpp" // 定义数据格式,用于在不同组件之间传输数据#include "../yoloApp/simple_yolo.hpp"
    #include "../byteTrackApp/logging.h"
    #include "../byteTrackApp/BYTETracker.h"// high performance
    #include "../yoloHighPer/cpm.hpp"
    #include "../yoloHighPer/infer.hpp"
    #include "../yoloHighPer/yolo.hpp"#	include <dirent.h>
    #	include <sys/types.h>
    #	include <sys/stat.h>
    #	include <unistd.h>
    # include <stdarg.h>using namespace std;
    using namespace cv;#include OATPP_CODEGEN_BEGIN(ApiController) //<-- Begin Codegenstatic bool exists(const string& path){#ifdef _WIN32return ::PathFileExistsA(path.c_str());
    #elsereturn access(path.c_str(), R_OK) == 0;
    #endif
    }static std::vector<std::string> cocolabels = {"car", "excavator", "loader", "dumpTruck", "person"
    };class InferInstance{
    public:InferInstance(std::string onnx_model_path, std::string trt_model_path){onnx_model = onnx_model_path;trt_model = trt_model_path;startup();}bool startup(){// if(!exists(trt_model)){// 	SimpleYolo::compile(// 		SimpleYolo::Mode::FP32,                 // FP32、FP16、INT8// 		SimpleYolo::Type::V8, // 		1,            // max batch size// 		onnx_model,                  // source // 		trt_model,                   // save to// 		1 << 30,// 		"inference"// 	);// }infer_ = yolo::load(trt_model, yolo::Type::V8);return infer_ != nullptr;}int inference(const Mat& image_input, yolo::BoxArray& boxarray){if(infer_ == nullptr){// INFOE("Not Initialize.");return 1;}if(image_input.empty()){// INFOE("Image is empty.");return 1;}boxarray = infer_->forward(cvimg(image_input));return 0;}private:yolo::Image cvimg(const cv::Mat &image) { return yolo::Image(image.data, image.cols, image.rows);}private:std::string onnx_model = "best.onnx";std::string trt_model = "best.onnx.engine";shared_ptr<yolo::Infer> infer_;
    };///
    std::string onnx_model = "coco/best.onnx";
    std::string engine_label = "coco/best.onnx.engine";
    std::unique_ptr<InferInstance> infer_instance1(new InferInstance(onnx_model, engine_label));int frame_rate = 10;
    int track_buffer = 30;
    std::unique_ptr<BYTETracker> tracker_instance1(new BYTETracker(frame_rate, track_buffer));////*** 建议使用 Api 控制器,而不是使用裸 HttpRequestHandler 为每个新端点创建新的请求处理程序。* API 控制器通过为您生成样板代码,使添加新端点的过程变得更加容易。 它还有助于组织您的端点,* 将它们分组到不同的 API 控制器中。*//*** Sample Api Controller.*/
    class MyController : public oatpp::web::server::api::ApiController {
    protected:/*** Constructor with object mapper.* @param objectMapper - default object mapper used to serialize/deserialize DTOs.*/MyController(const std::shared_ptr<ObjectMapper>& objectMapper): oatpp::web::server::api::ApiController(objectMapper){}public:  static std::shared_ptr<MyController> createShared(OATPP_COMPONENT(std::shared_ptr<ObjectMapper>, objectMapper)){return std::shared_ptr<MyController>(new MyController(objectMapper));}// TODO Insert Your endpoints here !!!/--data--// 多目标追踪ENDPOINT_ASYNC("POST", "/car1", tracker1){ENDPOINT_ASYNC_INIT(tracker1)Action act() override {return request->readBodyToStringAsync().callbackTo(&tracker1::returnResponse);}Action returnResponse(const oatpp::String& body_){auto response = tracker_inference(*infer_instance1, *tracker_instance1, body_, controller);return _return(response);}};//public:// 多目标追踪static std::shared_ptr<OutgoingResponse> tracker_inference(InferInstance& infer_, BYTETracker& track_infer, std::string body_, auto* controller){auto base64Image = base64_decode(body_);if(base64Image.empty()){return controller->createResponse(Status::CODE_400, "The image is empty!");}std::vector<char> base64_img(base64Image.begin(), base64Image.end());cv::Mat image = cv::imdecode(base64_img, 1);// 获取程序开始时间点auto start_time = std::chrono::high_resolution_clock::now();// 推理yolo::BoxArray boxarray;CV_Assert(0 == infer_.inference(image, boxarray));// 获取程序结束时间点auto end_time = std::chrono::high_resolution_clock::now();// 计算运行时间auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time);// 打印运行时间(以微秒为单位)// std::cout << "程序运行时间: " << duration.count() << " 毫秒" << std::endl;// 结果处理vector<Objects> objects;objects.resize(boxarray.size());int index = 0;for(auto& box : boxarray) {objects[index].rect.x = box.left;;objects[index].rect.y = box.top;objects[index].rect.width = box.right - box.left;objects[index].rect.height = box.bottom - box.top;objects[index].prob = box.confidence;objects[index].label = box.class_label;index++;std::cout << "left: " << box.left << ", top: " << box.top<< ", right: " << box.right << ", bottom: " << box.bottom<< ", confidence: " << box.confidence << ", class_label: " << box.class_label << std::endl;}auto yoloDto = TrackYoloDto::createShared();auto boxList = TrackBoxList::createShared();std::vector<STrack> output_stracks = track_infer.update(objects);for (int i = 0; i < output_stracks.size(); i++){auto trackBoxDto = TrackerBboxes::createShared();vector<float> tlwh = output_stracks[i].tlwh; // 方框的位置trackBoxDto->class_id = cocolabels[output_stracks[i].class_id];trackBoxDto->track_id = output_stracks[i].track_id;trackBoxDto->x        = tlwh[0];trackBoxDto->y        = tlwh[1];trackBoxDto->width    = tlwh[2];trackBoxDto->height   = tlwh[3];boxList->push_back(trackBoxDto);}output_stracks.clear();yoloDto->data = boxList;yoloDto->status = "successful";yoloDto->time = currentDateTime();return controller->createDtoResponse(Status::CODE_200, yoloDto);}static std::string currentDateTime(){auto now = std::chrono::system_clock::now();auto now_c = std::chrono::system_clock::to_time_t(now);auto now_ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()) % 1000;std::stringstream ss;ss << std::put_time(std::localtime(&now_c), "%Y-%m-%d %H:%M:%S") << '.' << std::setfill('0') << std::setw(3) << now_ms.count();return ss.str();}static unsigned char from_b64(unsigned char ch){/* Inverse lookup map */static const unsigned char tab[128] = {255, 255, 255, 255,255, 255, 255, 255, /*  0 */255, 255, 255, 255,255, 255, 255, 255, /*  8 */255, 255, 255, 255,255, 255, 255, 255, /*  16 */255, 255, 255, 255,255, 255, 255, 255, /*  24 */255, 255, 255, 255,255, 255, 255, 255, /*  32 */255, 255, 255, 62,255, 255, 255, 63, /*  40 */52,  53,  54,  55,56,  57,  58,  59, /*  48 */60,  61,  255, 255,255, 200, 255, 255, /*  56   '=' is 200, on index 61 */255, 0,   1,   2,3,   4,   5,   6, /*  64 */7,   8,   9,   10,11,  12,  13,  14, /*  72 */15,  16,  17,  18,19,  20,  21,  22, /*  80 */23,  24,  25,  255,255, 255, 255, 255, /*  88 */255, 26,  27,  28,29,  30,  31,  32, /*  96 */33,  34,  35,  36,37,  38,  39,  40, /*  104 */41,  42,  43,  44,45,  46,  47,  48, /*  112 */49,  50,  51,  255,255, 255, 255, 255, /*  120 */};return tab[ch & 127];}static std::string base64_decode(const std::string& base64){if(base64.empty())return "";int len = base64.size();auto s = (const unsigned char*)base64.data();unsigned char a, b, c, d;int orig_len = len;int dec_len = 0;string out_data;auto end_s = s + base64.size();int count_eq = 0;while(*--end_s == '='){count_eq ++;}out_data.resize(len / 4 * 3 - count_eq);char *dst = const_cast<char*>(out_data.data());char *orig_dst = dst;while (len >= 4 && (a = from_b64(s[0])) != 255 &&(b = from_b64(s[1])) != 255 && (c = from_b64(s[2])) != 255 &&(d = from_b64(s[3])) != 255) {s += 4;len -= 4;if (a == 200 || b == 200) break; /* '=' can't be there */*dst++ = a << 2 | b >> 4;if (c == 200) break;*dst++ = b << 4 | c >> 2;if (d == 200) break;*dst++ = c << 6 | d;}dec_len = (dst - orig_dst);// dec_len必定等于out_data.size()return out_data;}
    };#include OATPP_CODEGEN_END(ApiController) //<-- End Codegen#endif /* MyController_hpp */
  • 启动模型
    在这里插入图片描述
  • 请求接口进行推理

yolov8 模型部署测试

相关文章:

yolov8 模型部署--TensorRT部署-c++服务化部署

写目录 yolov8 模型部署--TensorRT部署1、模型导出为onnx格式2、模型onnx格式转engine 部署 yolov8 模型部署–TensorRT部署 1、模型导出为onnx格式 如果要用TensorRT部署YOLOv8&#xff0c;需要先使用下面的命令将模型导出为onnx格式&#xff1a; yolo export modelyolov8n.p…...

自适应迭代扩展卡尔曼滤波算法AIEKF估计SOC VS 扩展卡尔曼估计SOC

自适应迭代扩展卡尔曼滤波算法&#xff08;AIEK&#xff09; 自适应迭代扩展卡尔曼滤波算法&#xff08;AIEK&#xff09;是一种滤波算法&#xff0c;其目的是通过迭代过程来逐渐适应不同的状态和环境&#xff0c;从而优化滤波效果。 该算法的基本思路是在每一步迭代过程中&a…...

2023-亲测有效-git clone失败怎么办?用代理?加git?

git 克隆不下来&#xff0c;超时 用以下格式&#xff1a; git clone https://ghproxy.com/https://github.com/Tencent/ncnn.git 你的网站前面加上 https://ghproxy.com/ 刷的一下就下完了&#xff01;&#xff01;...

An Empirical Study of GPT-3 for Few-Shot Knowledge-Based VQA

本文是LLM系列文章&#xff0c;针对《An Empirical Study of GPT-3 for Few-Shot Knowledge-Based VQA》的翻译。 GPT-3对基于小样本知识的VQA的实证研究 摘要引言相关工作方法OK-VQA上的实验VQAv2上的实验结论 摘要 基于知识的视觉问答&#xff08;VQA&#xff09;涉及回答需…...

2023高教社杯数学建模B题思路分析 - 多波束测线问题

# 1 赛题 B 题 多波束测线问题 单波束测深是利用声波在水中的传播特性来测量水体深度的技术。声波在均匀介质中作匀 速直线传播&#xff0c; 在不同界面上产生反射&#xff0c; 利用这一原理&#xff0c;从测量船换能器垂直向海底发射声波信 号&#xff0c;并记录从声波发射到…...

02-docker network

Docker网络 Docker网络是什么 Docker 网络是 Docker 容器之间进行通信和连接的网络环境。在 Docker 中&#xff0c;每个容器都有自己的网络命名空间&#xff0c;这意味着每个容器都有自己的网络接口、IP 地址和网络配置 Docker网络启动后&#xff0c;会在宿主机中建立一个名…...

栈和队列经典笔试题

文章目录 栈和队列的回顾&#x1f4bb;栈&#x1fa73;队列&#x1f45f; 栈和队列经典笔试题&#x1f50b;有效的括号&#x1f3b8;用队列实现栈 &#x1f56f;用栈实现队列&#x1f52d;设计循环队列&#x1f9fc; 安静的夜晚 你在想谁吗 栈和队列的回顾&#x1f4bb; 栈&am…...

No5.9:多边形内角和公式

#!/usr/bin/python # -*- coding: UTF-8 -*-#指定了编码&#xff0c;中文就能正常展示 # codingutf-8def calc_degree(n):#n代表边形的总数degree (n - 2) * 180#多边形内角和公式return degreeprint(calc_degree(3))#三角形的内角和 print(calc_degree(4))#四边形的内角和【小…...

EditPlus 配置python 及Anaconda中的python

若不是pycharm vscode 太大&#xff0c;太占内存&#xff0c;谁会想到用Notepad&#xff0c;EdirPlus 配置python呢&#xff01;&#xff01;&#xff01; 话不多说&#xff0c;首先你自己安装好EditPlus。开始 菜单栏 选择 工具 -> 配置自定义工具 组名:python 命令:d:\*…...

linux 编译 llvm + clang

1. 需要下载以下三个压缩包&#xff0c;下载源码&#xff1a;Release LLVM 15.0.7 llvm/llvm-project GitHub clang-15.0.7.src.tar.xzcmake-15.0.7.src.tar.xzllvm-15.0.7.src.tar.xz​​​​​ 2. 解压后将 clang 源码放入 llvm/tools/ 下 3. 将解压后的 cmake-15.0.7…...

Mybatis 框架 ( 四 ) QueryWrapper

4.5.Wrapper条件构造器 Wrapper &#xff1a; 条件构造抽象类&#xff0c;最顶端父类 AbstractWrapper &#xff1a; 用于查询条件封装&#xff0c;生成 sql 的 where 条件 QueryWrapper &#xff1a; Entity 对象封装操作类&#xff0c;不是用lambda语法 UpdateWrapper &am…...

数据结构和算法之二分法查找

二分法查找&#xff0c;也称作二分查找或折半查找&#xff0c;是一种在有序数组中快速查找特定元素的算法。它采用分治法思想&#xff0c;通过将问题划分为规模更小的子问题&#xff0c;并且通过对子问题的查找来解决原问题。 二分法查找的思路是不断地将数组一分为二&#xf…...

系统日期如何在页面展示,框架是react或者vue3

安装插件dayjs或者moment.js 2.使用setInterval&#xff08;useInterval&#xff09;或者requestAnimationFrame react项目中useInterval的代码示例&#xff1a; import React, {useState } from react; import { useInterval } from "ahooks"; import moment fro…...

(二十二)大数据实战——Flume数据采集之故障转移案例实战

前言 本节内容我们完成Flume数据采集的故障转移案例&#xff0c;使用三台服务器&#xff0c;一台服务器负责采集nc数据&#xff0c;通过使用failover模式的Sink处理器完成监控数据的故障转移&#xff0c;使用Avro的方式完成flume之间采集数据的传输。整体架构如下&#xff1a;…...

前端小案例3:Flex弹性布局行内元素宽度自适应

前端小案例3&#xff1a;Flex弹性布局行内元素宽度自适应 项目背景&#xff1a;需要在一行上展示空调设备的三个模式&#xff08;制冷、制热、通风&#xff09;或者两个模式&#xff08;制冷、制热&#xff09;&#xff1b;因为不同产品的模式数量不同&#xff0c;因此需要让模…...

纳尼?小说还要用看的?这可以听!无广!

这是一款听书软件&#xff0c;可以自定义书源&#xff0c;自己设置书架&#xff0c;页面简单易操作&#xff0c;无广告。 支持直接搜索书名&#xff0c;链接&#xff0c;图文&#xff0c;本地文件等方式听书 拥有30多主播声音&#xff0c;分类细致 支持倍速、添加BGM等...

【微服务部署】四、Jenkins一键打包部署NodeJS(Vue)前端项目步骤详解

本文介绍使用Jenkins一键将NodeJS&#xff08;Vue&#xff09;前端项目打包并上传到生产环境服务器&#xff0c;这里使用的是直接打包静态页面&#xff0c;发送到远程服务器Nginx配置目录的方式&#xff0c;首先确保服务器环境配置好&#xff0c;安装Nginx&#xff0c;运行目录…...

【前端】禁止别人调试自己的前端页面代码

无限debugger 前端页面防止调试的方法主要是通过不断 debugger 来疯狂输出断点&#xff0c;因为 debugger 在控制台被打开的时候就会执行由于程序被 debugger 阻止&#xff0c;所以无法进行断点调试&#xff0c;所以网页的请求也是看不到的代码如下&#xff1a; /** * 基础禁止…...

UDP的可靠性传输

UDP系列文章目录 第一章 UDP的可靠性传输-理论篇&#xff08;一&#xff09; 第二章 UDP的可靠性传输-理论篇&#xff08;二&#xff09; 文章目录 UDP系列文章目录前言1.TCP 和UDP格式对比2.UDP分片原理3.UDP 传输层应该注意问题4.MTU5.UDP 分片机制设计重点 一、ARQ协议什么…...

科研笔记:TPAMI submission guideline

1 author information Author Information - IEEE Transactions on Pattern Analysis and Machine Intelligence | IEEE Computer Society Digital Library 1.1 会议期刊extension 当一个TPAMI的提交基于之前的会议论文时&#xff0c;IEEE要求期刊论文是之前出版物的“实质…...

centos 7 部署awstats 网站访问检测

一、基础环境准备&#xff08;两种安装方式都要做&#xff09; bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats&#xff0…...

系统设计 --- MongoDB亿级数据查询优化策略

系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log&#xff0c;共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题&#xff0c;不能使用ELK只能使用…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

C#学习第29天:表达式树(Expression Trees)

目录 什么是表达式树&#xff1f; 核心概念 1.表达式树的构建 2. 表达式树与Lambda表达式 3.解析和访问表达式树 4.动态条件查询 表达式树的优势 1.动态构建查询 2.LINQ 提供程序支持&#xff1a; 3.性能优化 4.元数据处理 5.代码转换和重写 适用场景 代码复杂性…...

Go语言多线程问题

打印零与奇偶数&#xff08;leetcode 1116&#xff09; 方法1&#xff1a;使用互斥锁和条件变量 package mainimport ("fmt""sync" )type ZeroEvenOdd struct {n intzeroMutex sync.MutexevenMutex sync.MutexoddMutex sync.Mutexcurrent int…...

【Linux】自动化构建-Make/Makefile

前言 上文我们讲到了Linux中的编译器gcc/g 【Linux】编译器gcc/g及其库的详细介绍-CSDN博客 本来我们将一个对于编译来说很重要的工具&#xff1a;make/makfile 1.背景 在一个工程中源文件不计其数&#xff0c;其按类型、功能、模块分别放在若干个目录中&#xff0c;mak…...

篇章二 论坛系统——系统设计

目录 2.系统设计 2.1 技术选型 2.2 设计数据库结构 2.2.1 数据库实体 1. 数据库设计 1.1 数据库名: forum db 1.2 表的设计 1.3 编写SQL 2.系统设计 2.1 技术选型 2.2 设计数据库结构 2.2.1 数据库实体 通过需求分析获得概念类并结合业务实现过程中的技术需要&#x…...

Xcode 16 集成 cocoapods 报错

基于 Xcode 16 新建工程项目&#xff0c;集成 cocoapods 执行 pod init 报错 ### Error RuntimeError - PBXGroup attempted to initialize an object with unknown ISA PBXFileSystemSynchronizedRootGroup from attributes: {"isa">"PBXFileSystemSynchro…...

中科院1区顶刊|IF14+:多组学MR联合单细胞时空分析,锁定心血管代谢疾病的免疫治疗新靶点

中科院1区顶刊|IF14&#xff1a;多组学MR联合单细胞时空分析&#xff0c;锁定心血管代谢疾病的免疫治疗新靶点 当下&#xff0c;免疫与代谢性疾病的关联研究已成为生命科学领域的前沿热点。随着研究的深入&#xff0c;我们愈发清晰地认识到免疫系统与代谢系统之间存在着极为复…...

VASP软件在第一性原理计算中的应用-测试GO

VASP软件在第一性原理计算中的应用 VASP是由维也纳大学Hafner小组开发的一款功能强大的第一性原理计算软件&#xff0c;广泛应用于材料科学、凝聚态物理、化学和纳米技术等领域。 VASP的核心功能与应用 1. 电子结构计算 VASP最突出的功能是进行高精度的电子结构计算&#xff…...