C++模型部署:qt+yolov5/6+onnxruntime+opencv

作者平时主要是写 c++ 库的,界面方面了解不多,也没有发现“美”的眼镜,界面有点丑,大家多包涵。请添加图片描述本次介绍的项目主要是通过 cmake 构建一个 基于 c++ 语言的,以 qt 为框架的,包含 opencv 第三方库在内的,跨平台的,使用 ONNX RUNTIME 进行前向推理的 yolov5/6 演示平台。文章力求简单,不追求过多的细节,让同学们对整个流程有一个全面的认识,废话不多说,下面我们就开始一步步的进行介绍。

推理框架

各种支持 C++ 的前向推理库都有自己的一些优点与缺点。X86架构下常用的框架:OpenCV DNN,OpenVINO,OpenVINO,ONNX RUNTIME与TensorRT 也是。下面对他们进行简要的对比,混合使用方式较复杂,暂不考虑(例如:使用其他模块为 DNN 加速等)。

OpenCV DNN

OpenCV 中的深度学习模块(DNN)只提供了推理功能,不涉及模型的训练,即模型训练好了,进行预测,支持多种深度学习框架,比如TensorFlow,Caffe,Torch和Darknet。

优点:

1.代码量及编译运行开销远小于其他深度学习模型框架;
2.DNN 模块提供了内建的 CPU 和 GPU 加速(不常用),OpenCV 内置,无需依赖第三方库;
3.一般不限制平台与 CPU ,通用性强。

缺点:

一般情况下 OpenCV DNN 速度最慢。

OpenVino

OpenVINO是英特尔推出的一款全面的工具套件,用于快速部署应用和解决方案,支持计算机视觉的CNN网络结构超过200余种。

优点

1.Linux、Windows、macOS 三大平台全覆盖;
2.对英特尔CPU有相应的优化(毕竟自家出品);
3.支持部分英特尔的独立显卡,同时支持英特尔核芯显卡的第 6 代至第 12 代智能英特尔 酷睿处理器,详细信息点击

缺点

原则上只支持英特尔的CPU与显卡推理加速。

ONNX Runtime

ONNX Runtime 是一个微软公司的开源项目,旨在加速跨各种框架、操作系统和硬件平台的机器学习。

优点

1.Linux、Windows、macOS 三大平台全覆盖;
2.英特尔、amd CPU都可使用;
3.同时支持 CPU 和 GPU 加速。

缺点

1.个人感觉在 linux 下比在 windows 下速度慢(研究领域有限,对是否为设计问题保持怀疑);
2.一般情况下,速度同样较慢,对比 OpenCV DNN 加速效果提升不明显。

TensorRT

英伟达官方出品,TensorRT 以 NVIDIA 的并行编程模型 CUDA (所以暂时显卡还是只建议购买 N 卡,TPU 等不属于本文介绍范畴)为基础构建而成,使用英伟达显卡时的“唯一选择”。

优点

1.对英伟达显卡进行最有效利用。

缺点

1.需要英伟达GPU硬件的支持;
2.代码量较多,使用较复杂。

一般情况下CPU推理速度(可用条件下):

OpenVino > ONNX Runtime > OpenCV DNN

使用显卡的情况下(速度无比较意义):

英特尔显卡使用 OpenVino ,英伟达显卡使用 TensorRT 。

由于用来演示的笔记本是 amd cpu ,所以本次便使用 ONNX Runtime 给大家进行相应的介绍。

模型

yolov5/6 之前也有过相应的介绍,文章就不再赘述了,需要了解的同学可在公众号中进行搜索。因为使用 ONNX Runtime 进行推理,所以对于模型来说,最简单的方式就是将其转化为 .onnx ,这一步的操作一般都会包含在 yolov5/6 开源项目中,按照相应的介绍就可以很方面的完成。

OpenCV

OpenCV(开源的计算机视觉库)是基于BSD协议,因此它可免费用于学术和商业用途。其提供C++,C,Python和Java接口,支持Windows,Linux,Mac OS,iOS和Android。
opencv 提供的功能基本可以覆盖科研中的大部分场景,所以我们这次使用 opencv 来介绍一下如何使用第三方库。
本次使用cmake来设置依赖,详细的介绍在后面的文章中说明。

QT

Qt 是一个跨平台的 C++ 框架(C++库),目前最新的版本是 Qt6.4。其中推荐 Qt5.15 或 Qt6.2,这两个版本是 LTS 版本(即长期支持版本),Bug较少,相对稳定。

Qt 除了支持界面设计(GUI编程),还封装了与网络编程、多线程、数据库连接、视频音频等相关的功能。

在这里插入图片描述
一般情况下,如何我的项目中如果使用到 QT ,那么我就会以 QT 为框架,进行整个项目的搭建。这次我们就基于 qt6.2.4 来介绍一下整个项目的搭建。因为 qt 最开始支持的是 qmake ,可能很多同学听到的都是这个构建方式。但是现在 qt 已经支持 cmake 了,为了不增加多余的学习成本,我们这次使用 cmake 来进行相应的介绍。

CMake

CMake 允许开发者编写一种平台无关的 CMakeList.txt 文件来定制整个编译流程,然后再根据目标用户的平台进一步生成所需的本地化 Makefile 和工程文件(Cmake 并不直接建构出最终的软件,而是产生标准的建构档),如 Unix 的 Makefile 或 Windows 的 Visual Studio 工程,然后再依一般的建构方式使用。在这里插入图片描述

CMake 使用方法

CMake的所有的语句都写在一个叫:CMakeLists.txt的文件中(cmake会根据该文件中的配置完成最终的编译,构建,打包,测试等一系列任务)。当CMakeLists.txt文件确定后,可以用cmake命令对相关的变量值进行配置。配置完成之后,应用cmake命令生成相应的makefile(在Unix like系统下)或者 project文件(指定用window下的相应编程工具编译时)。

平台框架搭建

前面有介绍到,既然我们以 qt 为框架进行平台的搭建。那么我们第一步就是创建一个能运行的 qt 项目。
在这里插入图片描述这里注意不要选错,我们本次使用 cmake 构建。
在这里插入图片描述到这里,点击 “Finish”, qt 项目就创建完成
在这里插入图片描述在 windows 平台下,为了避免兼容性问题,建议使用 vs ,编译器为默认的 msvc 。后续的操作也使用 vs 进行演示。
整个项目结构如下图所示:
在这里插入图片描述至此,qt 框架搭建完成,运行一下看看(因为我有 qt 的开发环境,所以环境变量之前已经设置好了)。
在这里插入图片描述然后我们在 CMakeLists.txt 中加入第三方库(OpenCV ,onnx runtime)的依赖。

OpenCV 依赖

find_package(OpenCV REQUIRED)
target_link_libraries(${PROJECT_NAME} PRIVATE ${OpenCV_LIBS})

需要在环境变量中进行相应的设置

onnx runtime 依赖(不同平台有微小区别)

if(UNIX)
    set(ONNXRUNTIME_DIR "/home/wobushimaomao/公共的/MyCode/CC++Code/onnxruntime-linux-x64-1.11.1")
    target_link_libraries(${PROJECT_NAME} PRIVATE "${ONNXRUNTIME_DIR}/lib/libonnxruntime.so")
elseif(WIN32)
    set(ONNXRUNTIME_DIR "D:/MyCode/CC++Code/onnxruntime-win-x64-1.11.1")
    target_link_libraries(${PROJECT_NAME} PRIVATE "${ONNXRUNTIME_DIR}/lib/onnxruntime.lib")
endif()
target_include_directories(${PROJECT_NAME} PRIVATE "${ONNXRUNTIME_DIR}/include")

windows平台有时会出现一些莫名其妙的问题,所以不常用的库我一般都是显式的设置,而不是加入环境变量。

再进行一些小的修改,得到最终的 CMakeLists.txt :

cmake_minimum_required(VERSION 3.5)

project(yolo_ort_cxx VERSION 0.1 LANGUAGES CXX)

set(CMAKE_INCLUDE_CURRENT_DIR ON)  # 自动将 CMAKE_CURRENT_SOURCE_DIR 和 CMAKE_CURRENT_BINARY_DIR 添加到每个目录的包含路径中

set(CMAKE_AUTOUIC ON)  # 自动翻译信号与槽
set(CMAKE_AUTOMOC ON)  # 自动翻译资源文件为cpp文件
set(CMAKE_AUTORCC ON)  # 自动翻译界面文件为cpp文件

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets)

file(GLOB_RECURSE PROJECT_SOURCES ./src/*)

if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
    qt_add_executable(${PROJECT_NAME}
        MANUAL_FINALIZATION
        ${PROJECT_SOURCES}
    )
endif()

target_link_libraries(${PROJECT_NAME} PRIVATE Qt${QT_VERSION_MAJOR}::Widgets)

# OpenCV
find_package(OpenCV REQUIRED)
# target_include_directories(${PROJECT_NAME} PRIVATE ${OpenCV_INCLUDE_DIRS})  # 一般不需要
target_link_libraries(${PROJECT_NAME} PRIVATE ${OpenCV_LIBS})

# ONNXRUNTIME
if(UNIX)
    set(ONNXRUNTIME_DIR "/home/wobushimaomao/公共的/MyCode/CC++Code/onnxruntime-linux-x64-1.11.1")
    target_link_libraries(${PROJECT_NAME} PRIVATE "${ONNXRUNTIME_DIR}/lib/libonnxruntime.so")
elseif(WIN32)
    set(ONNXRUNTIME_DIR "D:/MyCode/CC++Code/onnxruntime-win-x64-1.11.1")
    target_link_libraries(${PROJECT_NAME} PRIVATE "${ONNXRUNTIME_DIR}/lib/onnxruntime.lib")
else()
    message(STATUS "未知的平台类型!")
endif()
target_include_directories(${PROJECT_NAME} PRIVATE "${ONNXRUNTIME_DIR}/include")

set_target_properties(${PROJECT_NAME} PROPERTIES
    MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com
    MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
    MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
    MACOSX_BUNDLE TRUE
    # WIN32_EXECUTABLE TRUE # 打开时,可能出现windows下的vs不打印部分输出
)

# 屏蔽qDebug()调试信息
# add_compile_definitions(QT_NO_DEBUG_OUTPUT)

if(QT_VERSION_MAJOR EQUAL 6)
    qt_finalize_executable(${PROJECT_NAME})
endif()

add_subdirectory(src)

然后我们就可以按照自己的需求设置界面,并在合适的位置插入代码。最终的效果如下:
请添加图片描述至此,我们便完成了整个演示平台的介绍。

总结

文章的主要目的是基于 c++ 语言,搭建一个 yolov5/6 的前向推理演示平台。力求简单,不追求过多的细节,让同学们对整个设计有一个全面的理解。文中未介绍之处,如有需要大家可以善用搜索引擎或在公众号中搜索。

作者水平有限,如有问题或错误,欢迎评论区指正。

猜你喜欢

转载自blog.csdn.net/weixin_41006390/article/details/125645415