【YOLOv10】使用 TensorRT C++ API 调用GPU加速部署 YOLOv10 实现 500FPS 推理速度——快到飞起!

2024-07-06 1236阅读

  NVIDIA ® TensorRT ™ 是一款用于高性能深度学习推理的 SDK,包含深度学习推理优化器和运行时,可为推理应用程序提供低延迟和高吞吐量。YOLOv10是清华大学研究人员近期提出的一种实时目标检测方法,通过消除NMS、优化模型架构和引入创新模块等策略,在保持高精度的同时显著降低了计算开销,为实时目标检测领域带来了新的突破。

  在本文中,我们将演示如何使用NVIDIA TensorRT C++ API 部署YOLOv10目标检测模型,实现模型推理加速。下面看一下YOLOv10模型在TensorRT上的运行效果吧:

YOLOv10实现500FPS推理速度,快到离谱!!——使用 TensorRT C++ API 调用GPU加速部署YOLOv10实现快速预测

1. 前言

  TensorRT是NVIDIA官方推出的一个高性能深度学习推理加速引擎,它能够使深度学习模型在GPU上进行低延迟、高吞吐量的部署。TensorRT是基于CUDA和cuDNN的,专门为NVIDIA的GPU进行了优化。TensorRT支持TensorFlow、PyTorch、Caffe、MxNet等深度学习框架。对于MxNet和PyTorch,需要先将其模型转换为中间模型ONNX格式。总的来说,TensorRT是一个强大的深度学习推理加速引擎,通过优化和部署深度学习模型,能够在各种应用场景中实现快速、高效的推理性能。

【YOLOv10】使用 TensorRT C++ API 调用GPU加速部署 YOLOv10 实现 500FPS 推理速度——快到飞起!

  YOLOv10是清华大学研究人员近期提出的一种实时目标检测方法,该方法在Ultralytics Python包的基础上进行了多项创新和改进,主要有以下特点

  1. 消除非极大值抑制(NMS):YOLOv10通过引入一致的双重分配策略,在训练时使用一对多的标签分配来提供丰富的监督信号,在推理时使用一对一的匹配,从而消除了对NMS的依赖。这一改进在保持高精度的同时,减少了推理延迟和计算量。
  2. 全面优化的模型架构:YOLOv10从推理效率和准确性的角度出发,全面优化了模型的各个组成部分。这包括采用轻量级分类头、空间通道去耦下采样和等级引导块设计等,以减少计算冗余并提高模型性能。
  3. 引入大核卷积和部分自注意模块:为了提高性能,YOLOv10在不增加大量计算成本的前提下,引入了大核卷积和部分自注意模块。
  4. 多种模型尺寸可选:官方发布了从N到X各种型号的模型,以满足不同应用的需求。这些模型包括超小型版本YOLOv10-N(用于资源极其有限环境)、小型版本YOLOv10-S(兼顾速度和精度)、中型版本YOLOv10-M(通用)、平衡型版本YOLOv10-B(宽度增加,精度更高)、大型版本YOLOv10-L(精度更高,但计算资源增加)以及超大型版本YOLOv10-X(可实现最高的精度和性能)。

  通过广泛的实验验证,YOLOv10在多个模型尺度上实现了卓越的精度-延迟权衡。例如,在COCO数据集上,YOLOv10-S在相似精度下比其他实时目标检测方法更快,同时参数和浮点运算量也大幅减少。综上所述,YOLOv10通过消除NMS、优化模型架构和引入创新模块等策略,在保持高精度的同时显著降低了计算开销,为实时目标检测领域带来了新的突破。

【YOLOv10】使用 TensorRT C++ API 调用GPU加速部署 YOLOv10 实现 500FPS 推理速度——快到飞起!

2. 项目开发环境

  下面简单介绍一下项目的开发环境,开发者可以根据自己的设备情况进行配置:

  • 系统平台:Windows 11
  • 开发平台:Visual Studio 2022
  • CUDA:11.4
  • CUDNN:8.2.4
  • TensorRT:8.6
  • OpenCV:4.8.0

      此处代码开发平台使用的是C++,因此在项目配置时,需要配置第三方依赖库,分别是CUDA\CUDNN、TensorRT和OpenCV三个依赖库,其配置方式此处不做详述。

    3. 模型获取

    3.1 源码下载

      YOLOv10 模型需要源码进行下载,首先克隆GitHub上的源码,输入以下指令:

    git clone https://github.com/THU-MIG/yolov10.git
    cd yolov10
    

    3.2 配置环境

      接下来安装模型下载以及转换环境,此处使用Anaconda进行程序集管理,输入以下指令创建一个yolov10环境:

    conda create -n yolov10 python=3.9
    conda activate yolov10
    pip install -r requirements.txt
    pip install -e .
    

    3.3 下载模型

      首先导出目标识别模型,此处以官方预训练模型为例,首先下载预训练模型文件,然后调用yolo导出ONBNX格式的模型文件,最后使用 OpenVINO™ 的模型转换命令将模型转为IR格式,依次输入以下指令即可:

    wget https://github.com/jameslahm/yolov10/releases/download/v1.0/yolov10s.pt
    yolo export model=yolov10s.pt format=onnx opset=13 simplify
    

    4. engine模型转换

      首先定义ONNX模型转换Engine格式的代码,如下所示:

    #include "opencv2/opencv.hpp"
    #include 
    #include 
    #include "cuda.h"
    #include "NvInfer.h"
    #include "NvOnnxParser.h"
    class Logger : public nvinfer1::ILogger
    {
        void log(Severity severity, const char* msg) noexcept override
        {
            if (severity 
        // 将路径作为参数传递给函数
        std::string path(onnxFile);
        std::string::size_type iPos = (path.find_last_of('\\') + 1) == 0 ? path.find_last_of('/') + 1 : path.find_last_of('\\') + 1;
        std::string modelPath = path.substr(0, iPos);//获取文件路径
        std::string modelName = path.substr(iPos, path.length() - iPos);//获取带后缀的文件名
        std::string modelName_ = modelName.substr(0, modelName.rfind("."));//获取不带后缀的文件名名
        std::string engineFile = modelPath + modelName_ + ".engine";
        // 构建器,获取cuda内核目录以获取最快的实现
        // 用于创建config、network、engine的其他对象的核心类
        nvinfer1::IBuilder* builder = nvinfer1::createInferBuilder(logger);  // 构建器,获取cuda内核目录以获取最快的实现,用于创建config、network、engine的其他对象的核心类
        const auto explicitBatch = 1U 
            std::cout setMaxWorkspaceSize(1024 * 1024 * memorySize);  // 设置最大工作空间大小。
        config->setFlag(nvinfer1::BuilderFlag::kFP16);  // 设置模型输出精度
        nvinfer1::ICudaEngine* engine = builder->buildEngineWithConfig(*network, *config);  // 创建推理引擎
        // 将推理文件保存到本地
        std::cout 
            std::cerr destroy();
        engine->destroy();
        network->destroy();
        parser->destroy();
        std::cout 
    	cv::Mat mat;
        int rh = img-rows;
        int rw = img-cols;
        int rc = img->channels();
    	cv::cvtColor(*img, mat, cv::COLOR_BGR2RGB);
        int maxImageLength = rw > rh ? rw : rh;
        cv::Mat maxImage = cv::Mat::zeros(maxImageLength, maxImageLength,CV_8UC3);
        maxImage = maxImage * 255;
        cv::Rect roi (0, 0, rw, rh);
        mat.copyTo(cv::Mat(maxImage, roi));
    	cv::Mat resizeImg;
        cv::resize(maxImage, resizeImg, cv::Size(length, length), 0.0f, 0.0f, cv::INTER_LINEAR);
    	*factor = (float)((float)maxImageLength / (float)length);
        resizeImg.convertTo(resizeImg, CV_32FC3, 1 / 255.0);
        rh = resizeImg.rows;
        rw = resizeImg.cols;
        rc = resizeImg.channels();
        for (int i = 0; i  
    

      在调用时也相对简单,将相关变量传入即可,代码如下所示:

    Mat frame = new frame();
    std::vector inputData(640 * 640 * 3);
    float factor = 0;
    preProcess(&frame, 640, &factor, inputData);
    

    5.2 结果后处理

      首先此处定义了一个结果类:

    struct DetResult {
        cv::Rect bbox;
        float conf;
        int lable;
        DetResult(cv::Rect bbox,float conf,int lable):bbox(bbox),conf(conf),lable(lable){}
    };
    

      然后定义模型的结果处理方式,代码如下所示:

    std::vector postProcess(float* result, float factor, int outputLength) {
        std::vector positionBoxes;
        std::vector  classIds;
        std::vector  confidences;
        // Preprocessing output results
        for (int i = 0; i  0.2)
            {
                float cx = result[s + 0];
                float cy = result[s + 1];
                float dx = result[s + 2];
                float dy = result[s + 3];
                int x = (int)((cx)* factor);
                int y = (int)((cy)* factor);
                int width = (int)((dx - cx) * factor);
                int height = (int)((dy - cy) * factor);
                cv::Rect box(x, y, width, height);
                positionBoxes.push_back(box);
                classIds.push_back((int)result[s + 5]);
                confidences.push_back((float)result[s + 4]);
            }
        }
        std::vector re;
        for (int i = 0; i  
    

      最后为了让结果可视化,定义了结果绘制方法,代码如下所示:

    void drawBbox(cv::Mat& img, std::vector& res) {
        for (size_t j = 0; j  
    

      上述方式调用依旧十分容易,使用代码如下所示:

    std::vector output_data(300 * 6);
    std::vector result = postProcess(output_data.data(), factor, 300);
    drawBbox(frame, result);
    

    6. 模型推理实现

    6.1 模型读取与创建推理通道

      首先读取上文中转换的Engine模型,并创建推理通道,用于后文的模型推理,实现代码如下所示:

    std::shared_ptr creatContext(std::string modelPath) {
        // 以二进制方式读取问价
        std::ifstream filePtr(modelPath, std::ios::binary);
        if (!filePtr.good()) {
            std::cerr createExecutionContext());
    }
    

    6.2 Yolov10 推理代码

      下面结合一个视频推理,编写TensorRT推理YOLOv10的流程,代码如下所示:

    #include "opencv2/opencv.hpp"
    #include 
    #include 
    #include "cuda.h"
    #include "NvInfer.h"
    #include "NvOnnxParser.h"
    class Logger : public nvinfer1::ILogger
    {
        void log(Severity severity, const char* msg) noexcept override
        {
            // suppress info-level messages
            if (severity 
        const char* videoPath = "E:\\Text_dataset\\car_test.mov";
        const char* enginePath = "E:\\Text_Model\\yolov10s.engine";
        std::shared_ptr
            std::cerr 
            cv::Mat frame;
            if (!capture.read(frame)) {
                break;
            }
            float factor = 0;
        	preProcess(&frame, 640, &factor, inputData);
            cudaMemcpyAsync(inputSrcDevice, inputData.data(), 3 * 640 * 640 * sizeof(float), 
                cudaMemcpyHostToDevice, stream);
            void* bindings[] = { inputSrcDevice, outputSrcDevice };
        	context-enqueueV2((void**)bindings, stream, nullptr);
            cudaMemcpyAsync(output_data.data(), outputSrcDevice, 300 * 6 * sizeof(float),
                cudaMemcpyDeviceToHost, stream);
            cudaStreamSynchronize(stream);
            std::vector
VPS购买请点击我

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

目录[+]