码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • 【QT开发(8)】QT 中使用tensorrt


    在之前的文章《【TensorRT(2)】研究美团tech的yolov6的TensorRT部署》说明了tensorRT 的使用流程。今天尝试将其并入QT 项目中。

    文章目录

    • 项目地址
    • 参考资料:
    • 该分支主要做的工作
    • Task 1:读取视频文件,然后通过 dds 发送的事情
    • Task 2.1:将 yolov6 作为deeplib 库。
    • # Task 2.2:接收 dds 信息,用 deeplib 库推理图片。
    • 演示gif 动画

    项目地址

    库地址:https://gitee.com/hiyanyx/qt5.14-cpp_dds_-project/tree/dds_-tensorRT-yolov6/

    参考资料:

    1、代码参考:https://gitee.com/xiaoyuerCV/tensorrt-yolov6/,已经下载到了目录 ./reference/YOLOv6-Trt8

    2、pytorch 权重下载:美团yolov6,已经下载到了目录 ./reference/YOLOv6-main-meituan/deployONNX

    原理:下载 pytorch 的权重,yolov6s.pt,转换成 onnx。然后,把onnx 复制到 ./reference/YOLOv6-Trt8。然后trt 里面的c代码会自动把onnx 序列化为 yolov6s.engine 文件。

    3、行人视频:reference/YOLOv6-Trt8/xingren.mp4

    该分支主要做的工作

    1、在 ./src/main/example.cpp 中实现了读取视频文件,然后通过 dds 发送的事情。

    2、将 ./reference/YOLOv6-Trt8 作为 库 引入到 c++ 代码工程中,库名字为 deeplib,位置:./deps/deeplib。 具体工作为修改cmakelist文件,生成动态库 deeplib.so,增加deeplib.h 作为yolo检测器的接口(实现了Inferclass这个对象进行检测)。

    Task 1:读取视频文件,然后通过 dds 发送的事情

    1、在之前的文章【QT开发(6)】0926-QT 中加入 fastDDS 通信库的程序使用说明中说明了dds 的使用方法。

    2、我们基于上次的项目,修改 examples.hpp, 在 class Example 增加一个对象成员 cv::VideoCapture video_capture;。 特别说明以下,关于对象成员的初始化可以查看我的博客【C++学习(8)】类对象作为成员变量 和 【C++学习(10)】将一个类作为另一个类的成员: 类对象和类指针; std::unique_ptr 智能管理类指针。成员对象的初始化还是有很多知识点,作为基础知识大家需要学习。

    3、修改 examples.cpp对 video_capture 的一些属性进行修改。

    video_capture.open("/var/files/yanyixiong/qt5.14-cpp_-empty_-project/deps/deeplib/xingren.mp4");
    // 视频mp4解码
      int codec = cv::VideoWriter::fourcc('D', 'I', 'V', 'X');
    //获得
      double fps = video_capture.get(cv::CAP_PROP_FPS);
    // 宽度
      int width = video_capture.get(cv::CAP_PROP_FRAME_WIDTH);
    //高度
      int height = video_capture.get(cv::CAP_PROP_FRAME_HEIGHT);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    4、然后在50ms定时器中设置发送dds 信息。如果不明白我说的这个定时器是什么东西,请查看博文【QT开发(6)】0926-QT 中加入 fastDDS 通信库的程序使用说明

    我把那篇的截图放一下:
    在这里插入图片描述

    void Example::timer_WorkingStatus_callback()
    {
      // Test Env
      std::vector<unsigned char> vec_data;
      cv::Mat frame_pub;
      video_capture.read(frame_pub);
    
      if (!frame_pub.data ) {
                  debug::log("fail to imread");
                  return ;
          }
      else
          {
                  //cv::imshow("source image", img1);
                  //cv::waitKey(1);
                  //cv::resize(frame_pub, frame_pub, cv::Size(),0.1, 0.1);
                  debug::log("success to imread");
          }
    
      cv::imencode(".jpg", frame_pub, vec_data);
      auto_msg::msg::FrameData msg1;
      msg1.time_stamp() = get_time_ms();
      msg1.data() = vec_data;
      //msg1.data.insert(msg1.data.end(), vec_data.begin(), vec_data.end());
      simulation_raw_images_pub_->publish(msg1);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    5、至此,dds 发送视频就完成了。接下来,我们需要接受dds 信息,并用 yolov6 推理。

    Task 2.1:将 yolov6 作为deeplib 库。

    将 ./reference/YOLOv6-Trt8 作为 库 引入到 c++ 代码工程中,库名字为 deeplib,位置:./deps/deeplib。 具体工作为修改cmakelist文件,生成动态库 deeplib.so,增加deeplib.h 作为yolo检测器的接口(实现了Inferclass这个对象进行检测)。

    1、 ./deps/deeplib 修改cmakelists,增加库

    ADD_LIBRARY(deeplib SHARED ${SOURCES_FILES})
    target_include_directories(deeplib PUBLIC ${SOURCES_PATH})
    target_link_libraries(deeplib cuda tensorrt opencv)
    
    • 1
    • 2
    • 3

    2、写deeplib.h 接口程序
    写一个对象 Inferclass,包含,构造函数,析构函数,推理接口inferIOmain,以及复制构造函数。
    包含 私有成员类指针 Yolov6Detector,这个是在https://gitee.com/xiaoyuerCV/tensorrt-yolov6/里面已经实现的

    class Inferclass {
    public:
      Inferclass(std::string model_path = "/var/files/yanyixiong/qt5.14-cpp_-empty_-project/deps/deeplib/yolov6s.onnx");
    	Inferclass(const Inferclass &S);
    	void inferIOmain(cv::Mat input_image);
    	~Inferclass();
    
    private:
        std::string model_path ;
        std::unique_ptr<Yolov6Detector> yolov6_detector;
    
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在 构造函数 中完成对 Yolov6Detector 对象的初始化。

    Inferclass::Inferclass(std::string model_path):model_path(model_path)
    {
        std::cout << "Start" << std::endl;
    // 导入onnx 地址
      this->yolov6_detector.reset(new Yolov6Detector(model_path));
      if (!this->yolov6_detector->Init()) {
        std::cout << "Failed to initialize Yolov6 detector!";
      }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    析构函数 ,因为我们使用的是std::unique_ptr 类指针,不需要手动new和delete 指针。需要注意的是,如果我们是使用普通指针,一定到在 析构函数里面把 这个类指针释放,否则是内存泄漏!

    Inferclass::~Inferclass()
    {
        std::cout << "End" << std::endl;
    	//-----------------代码-------------------------------
    	if(NULL != pA)//此处需要初始化时设置指针为空。
    	{
    	  delete pA;
    	  pA = new A;
    	}  else {
    	  pA = new A;
    	}
    	//-----------------代码-------------------------------
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    推理接口 inferIOmain函数:

    void Inferclass::inferIOmain(cv::Mat input_image) {
      //cv::Mat input_image;
    // 建立目标列表
        std::vector objects;
    // 检测图像 
       this->yolov6_detector->Detect(input_image, &objects);
        //画图
        DrawObjects(input_image, objects);
    // 展示图片
        cv::imshow("YOLOv6 Object detection", input_image);
        cv::waitKey(1);
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    3、我们有了 deeplib.h 和cmakelist文件,这就是一个库了,可以被其他项目使用。这是个基础的工作,如果你不懂怎么在主项目里面引入库,可以看之前的git仓库学习cmake practice。

    # Task 2.2:接收 dds 信息,用 deeplib 库推理图片。

    在之前的文章【QT开发(6)】0926-QT 中加入 fastDDS 通信库的程序使用说明中,引入deeplib 库。

    1、修改 cmakelists,增加头文件

    # ===== 设置 include 目录路径 =====
    target_include_directories ( emptyApp PUBLIC
        # === 第三方库 ===
        # 在此处添加更多 第三方库
        # 具体写法,请查阅各个 库文档
        ${CMAKE_CURRENT_SOURCE_DIR}/deeplib/src
        )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    2、修改 cmakelists,增加 cmaklist 子目录

    #---------------------------------------------------#
    #             子目录 CMakeLists.txt
    #---------------------------------------------------#
    #-- 子 CMakeLists.txt 执行的 中间产物,将分别放在 
    #      build/src  build/libhello  目录中。
    add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/deps/deeplib EXCLUDE_FROM_ALL)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    3、修改 cmakelists,增加一个 target_link_libraries

        target_link_libraries( emptyApp 
    			    deeplib)
    
    • 1
    • 2

    4、至此,修改完了 cmakelists。然后在 Examples.h 中增加成员类。

    在博客【C++学习(10)】将一个类作为另一个类的成员: 类对象和类指针; std::unique_ptr 智能管理类指针,我们谈到,如果是在 一个 class 中增加另一个 类成员,首先,要将A类的对象作为B类的成员,你必须在B类声明前声明A类。其次,就是像声明一个成员变量一样,在B类中添加一个成员,如A m_a; 最后,初始化m_a。因为这个成员是一个类对象,因此需要调用构造函数才能初始化。因为这个对象m_a在B类中,m_a对象的构造必然是在B类对象构造之前进行,因此不能在B类构造函数中进行,又因为m_a不是全局对象,也不能在函数外部。如何解决这个问题呢?这就是C++提出的成员初始化列表,用来解决这类问题的。

    因此,我们增加一个 类成员

    class Example : public rclcpp::Node
    {
     public:
      Example(std::string model_path);
      ~Example();
      int Init();
      int Start();
      int Stop();
      Inferclass InferPr;
    ...
    ...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    然后在 Examples.cpp 中class Examples 成员初始化列表 初始化。

    Example::Example(std::string model_path) : rclcpp::Node("example"),InferPr(model_path)
    {
      running_ = false;
      workingStatus_timer_ = nullptr;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    完成了初始化,就可以使用这个 InferPr 成员,在50ms 定时器中用它进行推理

    void Example::timer_WorkingStatus_callback()
    {
      auto_msg::msg::FrameData stitch_img = stitch_img_.Get();
        if ( running_ == true && stitch_img.time_stamp()>0) {
          cv::Mat frame = cv::imdecode(stitch_img.data(), CV_LOAD_IMAGE_COLOR);
          InferPr.inferIOmain(frame);
        }
        else
        {
            std::cout << "Timer trick 50ms, waiting" << std::endl;
        }
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    4、至此,完成了工作

    演示gif 动画

    ScreenToGif 很好用呀,推荐。
    在这里插入图片描述

    正文结束

  • 相关阅读:
    uniapp 实现富文本编辑器【小程序端】
    基于信通院 Serverless 工具链模型的实践:Serverless Devs
    软考网络工程师IPSEC VPN配置考点总结
    Kubernetes 进阶训练营 网络
    ELK日志分析平台(一)—elasticsearch的安装和配置
    C# 超好用的自定义异形窗体
    开启深度学习之门—《深度学习》
    03 Spring_DI 依赖注入
    借助Rich库实现Pandas DataFrame颜值升级
    CryptoCTF easy
  • 原文地址:https://blog.csdn.net/djfjkj52/article/details/133856952
    • 最新文章
    • 攻防演习之三天拿下官网站群
      数据安全治理学习——前期安全规划和安全管理体系建设
      企业安全 | 企业内一次钓鱼演练准备过程
      内网渗透测试 | Kerberos协议及其部分攻击手法
      0day的产生 | 不懂代码的"代码审计"
      安装scrcpy-client模块av模块异常,环境问题解决方案
      leetcode hot100【LeetCode 279. 完全平方数】java实现
      OpenWrt下安装Mosquitto
      AnatoMask论文汇总
      【AI日记】24.11.01 LangChain、openai api和github copilot
    • 热门文章
    • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
      奉劝各位学弟学妹们,该打造你的技术影响力了!
      五年了,我在 CSDN 的两个一百万。
      Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
      面试官都震惊,你这网络基础可以啊!
      你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
      心情不好的时候,用 Python 画棵樱花树送给自己吧
      通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
      13 万字 C 语言从入门到精通保姆级教程2021 年版
      10行代码集2000张美女图,Python爬虫120例,再上征途
    Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
    正则表达式工具 cron表达式工具 密码生成工具

    京公网安备 11010502049817号