[C++]使用C++部署yolov10目标检测的tensorrt模型支持图片视频推理windows测试通过

【测试通过环境】
vs2019
cmake==3.24.3
cuda11.7.1+cudnn8.8.0
tensorrt==8.6.1.6
opencv==4.8.0

【部署步骤】
获取pt模型:https://github.com/THU-MIG/yolov10训练自己的模型或者直接使用yolov10官方预训练模型
下载源码:https://github.com/laugh12321/yolov10/tree/nms并安装到环境中
导出onnx:
yolo export model=yolov10n.pt format=onnx opset=13 simplify max_det=100 conf=0.25 iou=0.65 nms

注意导出模型和官方yolov10指令导出的onnx是不一样的,使用yolov10-nms导出模型结构如图

注意一定要是上面类似结构图才能用于这个C++项目
导出tensorrt:

等20分钟左右即可导出需要耐心等待一段时间视个人电脑性能决定,由于tensorrt依赖硬件不一样电脑可能无法共用tensorrt模型,所以必须要重新转换onnx模型到engine才可以运行。请勿直接使用提供的engine模型进行直接测试,否则可能无法正常运行
trtexec --onnx=yolov10n.onnx --saveEngine=yolov10n.engine --fp16

下载安装vs2019勾选桌面C++安装
git clone https://github.com/laugh12321/TensorRT-YOLO
cd TensorRT-YOLO
xmake f -k shared --tensorrt="C:/Program Files/NVIDIA GPU Computing Toolkit/TensorRT/v8.6.1.6"
xmake -P . -r
将编译好的deploy.dll和deploy.lib文件放到yolov10-tensorrt-cplus/lib文件夹
编译源码yolov10-tensorrt-cplus
运行命令:
推理图片:
yolov10.exe -e C:\Users\Administrator\Desktop\yolov10-tensorrt-cplus\yolov10n.engine -i C:\Users\Administrator\Desktop\yolov10-tensorrt-cplus\images\bus.jpg -o ./out -l C:\Users\Administrator\Desktop\yolov10-tensorrt-cplus\labels.txt

推理视频:
yolov10.exe -e C:\Users\Administrator\Desktop\yolov10-tensorrt-cplus\yolov10n.engine -i D:\car.mp4 -o ./out -l C:\Users\Administrator\Desktop\yolov10-tensorrt-cplus\labels.txt

【视频演示】

使用C++部署yolov10目标检测的tensorrt模型支持图片视频推理windows测试通过_哔哩哔哩_bilibili【测试通过环境】vs2019cmake==3.24.3cuda11.7.1+cudnn8.8.0tensorrt==8.6.1.6opencv==4.8.0更多信息参考博文:https://blog.csdn.net/FL1623863129/article/details/139693743, 视频播放量 3、弹幕量 0、点赞数 0、投硬币枚数 0、收藏人数 0、转发人数 0, 视频作者 未来自主研究中心, 作者简介 未来自主研究中心,相关视频:4060Ti 16G显卡安装Ollama+ChatTTS打造智能语音秘书(突破30秒限制),AI换脸最全面部细节演示:眨眼,捏眉毛,斗鸡眼,戳鼻子,做猪鼻子……认识ai换脸,警惕Ai换脸,Ai变声诈骗!,基于yolo的骑行速度检测,labelme json转yolo工具用于目标检测训练数据集使用教程,使用纯opencv部署yolov8目标检测模型onnx,rk3588 yolov5 目标检测推流rtsp,[深度学习][目标检测][面试提问]Batch Normalization批归一化,[数据集介绍][目标检测]城市街道垃圾数据集VOC格式5266张,GPT:可恶!我好不容易才建立的三观啊!,毕设项目—基于最新YOLOv10+ByteTrack+PaddleOCR实现交通状态分析 (功能:目标检测、轨迹跟踪、车牌检测、车牌号识别、单目测速及目标计数)icon-default.png?t=N7T8https://www.bilibili.com/video/BV13S411P7XL/

【部分实现代码】

#include <CLI/CLI.hpp>
#include <chrono>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <memory>
#include <opencv2/opencv.hpp>
#include <random>
#include <string>  
#include <algorithm> 
#include "deploy/utils/utils.hpp"
#include "deploy/vision/detection.hpp"
#include "deploy/vision/result.hpp"
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
using namespace std;namespace fs = std::filesystem;
std::string getFileExtension(const std::string& filePath) {  size_t dotPosition = filePath.rfind('.'); // 从右向左查找'.'的位置  if (dotPosition == std::string::npos) {  // 没有找到'.',返回空字符串  return "";  }  return filePath.substr(dotPosition + 1); // 返回'.'之后的所有字符  
}  
// Get image files in a directory
std::vector<std::string> getImagesInDirectory(const std::string &folderPath)
{std::vector<std::string> imageFiles;for (const auto &entry : fs::directory_iterator(folderPath)){const auto extension = entry.path().extension().string();if (fs::is_regular_file(entry) && (extension == ".jpg" || extension == ".png" || extension == ".jpeg" || extension == ".bmp")){imageFiles.push_back(entry.path().string());}}return imageFiles;
}// Get file name from file path
std::string getFileName(const std::string &filePath)
{return fs::path(filePath).filename().string();
}// Create output directory
void createOutputDirectory(const std::string &outputPath)
{if (!fs::exists(outputPath) && !fs::create_directories(outputPath)){std::cerr << "Failed to create output directory: " << outputPath << std::endl;exit(1);}else if (!fs::is_directory(outputPath)){std::cerr << "Output path exists but is not a directory: " << outputPath << std::endl;exit(1);}
}// Generate label and color pairs
std::vector<std::pair<std::string, cv::Scalar>> generateLabelColorPairs(const std::string &labelFile)
{std::vector<std::pair<std::string, cv::Scalar>> labelColorPairs;std::ifstream file(labelFile);if (!file.is_open()){std::cerr << "Failed to open labels file: " << labelFile << std::endl;return labelColorPairs;}auto generateRandomColor = [](){std::random_device rd;std::mt19937 gen(rd());std::uniform_int_distribution<int> dis(0, 255);return cv::Scalar(dis(gen), dis(gen), dis(gen));};std::string label;while (std::getline(file, label)){labelColorPairs.emplace_back(label, generateRandomColor());}return labelColorPairs;
}// Visualize detection results
void visualize(cv::Mat &image, const deploy::DetectionResult &result, const std::vector<std::pair<std::string, cv::Scalar>> &labelColorPairs)
{for (size_t i = 0; i < result.num; ++i){const auto &box = result.boxes[i];int cls = result.classes[i];float score = result.scores[i];const auto &label = labelColorPairs[cls].first;const auto &color = labelColorPairs[cls].second;std::string labelText = label + " " + cv::format("%.2f", score);// Draw rectangle and labelcv::rectangle(image, cv::Point(box.left, box.top), cv::Point(box.right, box.bottom), color, 2, cv::LINE_AA);int baseLine;cv::Size labelSize = cv::getTextSize(labelText, cv::FONT_HERSHEY_SIMPLEX, 0.6, 1, &baseLine);cv::rectangle(image, cv::Point(box.left, box.top - labelSize.height), cv::Point(box.left + labelSize.width, box.top), color, -1);cv::putText(image, labelText, cv::Point(box.left, box.top), cv::FONT_HERSHEY_SIMPLEX, 0.6, cv::Scalar(255, 255, 255), 1);}
}// Process a single image
void processSingleImage(const std::string &imagePath, const std::shared_ptr<deploy::DeployDet> &model, const std::string &outputPath, const std::vector<std::pair<std::string, cv::Scalar>> &labels)
{cv::Mat cvimage = cv::imread(imagePath, cv::IMREAD_COLOR);if (cvimage.empty()){std::cerr << "Failed to read image: " << imagePath << std::endl;return;}// cv::cvtColor(cvimage, cvimage, cv::COLOR_BGR2RGB);  // It is better to use RGB images, but the impact of using BGR on the results is not significant.deploy::Image image(cvimage.data, cvimage.cols, cvimage.rows);std::cout << "start inference\n";auto result = model->predict(image);std::cout << "inference over!\n";if (!outputPath.empty()){std::cout << "show result\n";// cv::cvtColor(cvimage, cvimage, cv::COLOR_RGB2BGR);visualize(cvimage, result, labels);cv::imwrite(outputPath + "/" + getFileName(imagePath), cvimage);}else{std::cout << "outputPath is empty\n";}
}void processVideo(const std::string &videoPath, const std::shared_ptr<deploy::DeployDet> &model, const std::vector<std::pair<std::string, cv::Scalar>> &labels)
{VideoCapture capture(videoPath);if (!capture.isOpened())return;double fps = capture.get(cv::CAP_PROP_FPS);          // 帧率int width = capture.get(cv::CAP_PROP_FRAME_WIDTH);   // 视频帧宽度int height = capture.get(cv::CAP_PROP_FRAME_HEIGHT); // 视频帧高度while (1){Mat frame;capture >> frame; // 从相机读取新一帧if (frame.empty()){std::cout << "read over!\n";break;}deploy::Image image(frame.data, frame.cols, frame.rows);auto result = model->predict(image);// cv::cvtColor(cvimage, cvimage, cv::COLOR_RGB2BGR);visualize(frame, result, labels);cv::imshow("result", frame);if (char(waitKey(2)) == 'q'){break;}}capture.release();cv::destroyAllWindows();
}// Process a batch of images
void processBatchImages(const std::vector<std::string> &imageFiles, const std::shared_ptr<deploy::DeployDet> &model, const std::string &outputPath, const std::vector<std::pair<std::string, cv::Scalar>> &labels)
{const size_t batchSize = model->batch;deploy::GpuTimer gpuTimer;deploy::CpuTimer<std::chrono::high_resolution_clock> cpuTimer;int count = 0;for (size_t i = 0; i < imageFiles.size(); i += batchSize){std::vector<cv::Mat> images;std::vector<std::string> imgNameBatch;for (size_t j = i; j < i + batchSize && j < imageFiles.size(); ++j){cv::Mat image = cv::imread(imageFiles[j], cv::IMREAD_COLOR);if (image.empty()){std::cerr << "Failed to read image: " << imageFiles[j] << std::endl;continue;}// cv::cvtColor(image, image, cv::COLOR_BGR2RGB); // It is better to use RGB images, but the impact of using BGR on the results is not significant.images.push_back(image);imgNameBatch.push_back(getFileName(imageFiles[j]));}if (images.empty())continue;std::vector<deploy::Image> imgBatch;for (const auto &image : images){imgBatch.emplace_back(image.data, image.cols, image.rows);}if (i > 5){cpuTimer.start();gpuTimer.start();}auto results = model->predict(imgBatch);if (i > 5){cpuTimer.stop();gpuTimer.stop();count++;}if (!outputPath.empty()){for (size_t j = 0; j < images.size(); ++j){// cv::cvtColor(images[j], images[j], cv::COLOR_RGB2BGR);visualize(images[j], results[j], labels);cv::imwrite(outputPath + "/" + imgNameBatch[j], images[j]);}}}if (count > 0){std::cout << "Average infer CPU elapsed time: " << cpuTimer.microseconds() / 1000 / count << " ms" << std::endl;std::cout << "Average infer GPU elapsed time: " << gpuTimer.microseconds() / 1000 / count << " ms" << std::endl;}
}int main(int argc, char **argv)
{CLI::App app{"YOLO Series Inference Script"};std::string enginePath, inputPath, outputPath, labelPath;app.add_option("-e,--engine", enginePath, "Serialized TensorRT engine")->required()->check(CLI::ExistingFile);app.add_option("-i,--input", inputPath, "Path to image or directory")->required()->check(CLI::ExistingPath);app.add_option("-o,--output", outputPath, "Directory to save results");app.add_option("-l,--labels", labelPath, "File to use for reading the class labels from")->check(CLI::ExistingFile);CLI11_PARSE(app, argc, argv);std::cout << "load engine...\n";auto model = std::make_shared<deploy::DeployDet>(enginePath);std::cout << "engine loaded!\n";std::vector<std::pair<std::string, cv::Scalar>> labels;if (!outputPath.empty()){labels = generateLabelColorPairs(labelPath);createOutputDirectory(outputPath);}if (fs::is_regular_file(inputPath)){if(getFileExtension(inputPath)=="mp4"){processVideo(inputPath, model, labels);}else{std::cout << "start process image file\n";processSingleImage(inputPath, model, outputPath, labels);}}else{std::cout << "start process image directory\n";auto imageFiles = getImagesInDirectory(inputPath);if (!imageFiles.empty()){processBatchImages(imageFiles, model, outputPath, labels);}else{std::cerr << "No images found in directory: " << inputPath << std::endl;return 1;}}std::cout << "Inference completed." << std::endl;return 0;
}

【源码下载】https://download.csdn.net/download/FL1623863129/89436042

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/28036.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

波卡近期活动一览| Polkadot Decoded 2024 重磅来袭,300 万 DOT 将用于 DeFi 增长

Polkadot 生态近期活动精彩纷呈&#xff0c;线上线下火热进行中&#xff01;此外&#xff0c;Polkadot 2.0 的关键升级即将到来&#xff0c;Gavin Wood 博士也将在最新访谈节目中分享更多关于波卡的未来发展蓝图。波卡 DAO 通过提案&#xff0c;分配 300 万 DOT 支持 DeFi 生态…

房地产房型展示信息小程序的内容是什么

地产业规模之大且品牌众多&#xff0c;还有房屋租赁、中介等&#xff0c;无论开发商公司还是衍生行业商家都需要多渠道宣传品牌和客户触达沟通转化&#xff0c;除了线下各种传单&#xff0c;线上也是主要场景&#xff0c;通过各种连接来达到相应目标。 也因此需符合平台生态开…

读AI新生:破解人机共存密码笔记01以史为鉴

1. 科学突破是很难预测的 1.1. 20世纪初&#xff0c;也许没有哪位核物理学家比质子的发现者、“分裂原子的人”欧内斯特卢瑟福&#xff3b;Ernest Rutherford&#xff3d;更为杰出 1.1.1. 卢瑟福早就意识到原子核储存了巨大的能量&#xff0c;然而&#xff0c;主流观点认为开…

Qt 6.13

作业&#xff1a; #include "mywidget.h"mywidget::mywidget(QWidget *parent): QWidget(parent) {this->setStyleSheet("background-color:white");this->resize(600,600);this->setWindowFlag(Qt::FramelessWindowHint);this->setWindowTit…

Opencv数一数有多少个水晶贴纸?

1.目标-数出有多少个贴纸 好久没更新博客了&#xff0c;最近家里小朋友在一张A3纸上贴了很多水晶贴纸&#xff0c;要让我帮他数有多少个&#xff0c;看上去有点多&#xff0c;贴的也比较随意&#xff0c;于是想着使用Opencv来识别一下有多少个。 原图如下&#xff1a; 代码…

centos7系统使用docker-compose安装部署jenkins

CentOS7系统使用docker-compose安装部署jenkins&#xff0c;并实现前后端自动构建 记录一次在给公司部署jenkins的真实经历&#xff0c;总结了相关经验 1.准备环境 1.java 由于最新的jenkins需要jdk11以上才能支持&#xff0c;而系统里的jdk是1.8的&#xff0c;因此等jenkins…

vue项目问题汇总

1.el-select&#xff1a; 下拉框显示到了top:-2183px , 添加属性 :popper-append-to-body"false" 2. el-upload: 选过的文件在使用过后记得清空&#xff0c;因为如果有limit1的时候&#xff0c;没有清空会导致不触发onchange 使用自定义上传方法http-request的时…

Swift开发——输出格式化字符

Swift语言是开发iOS和macOS等Apple计算机和移动设备系统应用程序的官方语言。Swift语言是一种类型安全的语言,语法优美自然,其程序从main.swift文件开始执行,程序代码按先后顺序执行,同一个工程的程序文件中的类和函数直接被main.swift文件调用,除了main.swift文件外,工程…

工业自动化领域常见的通讯协议

工业自动化领域常见的通讯协议&#xff0c;包括PROFINET、PROFIBUS、Modbus、Ethernet/IP、CANopen、DeviceNet和BACnet。通过分析这些协议的技术特点、应用场景及优势&#xff0c;比较它们在工业自动化中的性能和适用性&#xff0c;帮助选择最合适的协议以优化系统性能和可靠性…

Transformer系列:图文详解Decoder解码器原理

从本节开始本系列将对Transformer的Decoder解码器进行深入分析。 内容摘要 Encoder-Decoder框架简介shifted right移位训练解码器的并行训练和串行预测解码器自注意力层和掩码解码器交互注意力层和掩码解码器输出和损失函数 Encoder-Decoder框架简介 在原论文中Transformer用…

论文发表CN期刊《高考》是什么级别的刊物?

论文发表CN期刊《高考》是什么级别的刊物&#xff1f; 《高考》是由吉林省长春出版社主管并主办的省级教育类期刊&#xff0c;期刊以科教兴国战略为服务宗旨&#xff0c;专门反映和探索国内外教育教学和科研实践的最新成果。该期刊致力于为广大教育工作者提供一个高质量的学术…

idea自定义注释模板

1、打开配置 setting -> Editor -> Live Template 2、添加TemplateGroup&#xff0c;并在添加的TemplateGroup下加LiveTemplate 3、配置Live Template 内容&#xff1a; **** Description: * $param$* return $return$ * author $user$* date $date$ $time$**/变量…

oracle RAC安装 保姆级教程

使用SSHXmanager 我的本地IP是172.17.68.68 服务器配置 [rootrac12-1 ~]# cat /etc/hosts 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 #Public IP …

ARP协议相关

把ip地址解析成mac地址这里的mac地址就是路由器的mac地址 免费ARP 源ip和目的ip都是一样的&#xff0c;那怎么让其他人更新arp表呢&#xff1f;&#xff1f; 是因为目标mac是全f&#xff0c;是一个广播报文 如果冲突就是ip一样但是mac又不一样 代理ARP pc1和pc4是在同一个子网…

[DDR4] DDR1 ~ DDR4 发展史导论

依公知及经验整理&#xff0c;原创保护&#xff0c;禁止转载。 专栏 《深入理解DDR4》 内存和硬盘是电脑的左膀右臂&#xff0c; 挑起存储的大梁。因为内存的存取速度超凡地快&#xff0c; 但内存上的数据掉电又会丢失&#xff0c;一直其中缓存的作用&#xff0c;就像是我们的工…

四川汇聚荣聚荣科技有限公司是干什么的,拼多多运营如何做?

四川汇聚荣聚荣科技有限公司是干什么的&#xff0c;拼多多运营如何做?随着电商行业的快速发展&#xff0c;越来越多的企业开始涉足这一领域。其中&#xff0c;四川汇聚荣聚荣科技有限公司便是其中的一员。那么&#xff0c;这家公司究竟是做什么的呢?简单来说&#xff0c;它是…

WSL Ubuntu安装TensorFlow-GPU、PyTorch-GPU

在Windows 11的WSL Ubuntu中安装TensorFlow-GPU、PyTorch-GPU 0、WSL Ubuntu安装 在Windows 11的商店中下载即可&#xff0c;此处以Ubuntu22.04.3为例 1、CUDA Toolkit安装 参考公孙启的文章Windows11 WSL Ubuntu Pycharm Conda for deeplearning前往nVidia官网下载CUDA …

靠谱放心!康姿百德柔压磁性豪华枕质量大揭秘

康姿百德柔压磁性豪华枕&#xff0c;舒爽透气呵护青春期娇嫩肌肤 良好的睡眠对青少年的生长发育至关重要&#xff0c;想要获得高质量睡眠&#xff0c;除了选择合适的床垫之外&#xff0c;一款合适的枕头同样是打造优质睡眠环境的重要一环。康姿百德集团有限公司深耕睡眠领域已…

electron模板【lectron-react-boilerplate】多窗口配置【HtmlWebpackPlugin】多页面配置

如果您正在使用electron-react-boilerplate进行快速的Electron应用程序开发,您可能会遇到想要在桌面应用程序中拥有多个原生窗口的情况。 MacOS窗口图像由OpenClipart-Vectors提供,来源Pixabay。 开始之前需要提及的事情! Electron有一个主进程和渲染进程的模式。可以有多个…

【博客718】时序数据库基石:LSM Tree(log-structured merge-tree)

时序数据库基石&#xff1a;LSM Tree(log-structured merge-tree) 1、为什么需要LSM Tree LSM被设计来提供比传统的B树更好的写操作吞吐量&#xff0c;通过消去随机的本地更新操作来达到这个目标&#xff0c;使得写入都是顺序写&#xff0c;而不是随机写。 那么为什么这是一个…