Win10 + VS2019 + Qt5 + OpenCV + Libtorch (PyTorch) C++ cmake 基本配置 + 踩坑记录

最近想用 Qt 写一个界面在 C++ 下调用 Pytorch 模型,整个环境配置下来遇到了不少问题,因此记录一下。

1. 下载安装相关文件

由于我的开发环境是 Win10,因此需要下载的东西挺多的,IDE 用的 Visual Studio 2019,在 这里 下载社区版,安装的时候可以选择需要的编译器,我装的是 MSVC v142,vs2019 里要装一个 cmake,单独的 cmake 可下可不下。

VS 中的 cmake.exe 在 D:\Microsoft Visual Studio\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin 路径下。

使用 cmake 安装包安装的会多一个 cmake-gui.exe 可视化程序可以用。

然后下载 Qt5,在 清华源 里可以直接下载,在页面右边的获取下载链接的应用软件里。

在这里插入图片描述
这里选择 MSVC 2017,虽然 VS 是 2019,但不影响。如果要用 MinGW 重新编译 OpenCV 的就要装 MinGW。这里 可以看他们的区别。

安装好之后把 Qt 的 bin 文件夹加入环境变量,我的路径是 E:\Qt\5.14.2\msvc2017_64\bin

接着下载 OpenCV,Windows 平台的安装包解压后有 buildsources 两个文件夹。build 文件夹下的就是已经用 VS 编译好的,可以直接用。sources 就是源文件,可以自己按需要编译。

我没有重新编译,直接用原生提供的,网上有说在 Qt 中用 OpenCV 要自己重新编译,但我目前使用发现没什么问题。
这里给出两个如何自行编译的链接。如果需要就重新编译一下。

Pytorch 有专门的 C++ 库,叫 Libtorch,在 官网 上就可以下载到。这里我选择的是 cpu 版本的,cuda 版本的还需要额外的配置,先把简单的搞定。

Python 和 C++ 的 Pytorch 版本最好一样,免得读取模型出问题,我这里统一用了 1.6 版本。

在这里插入图片描述
下载完成,解压后,可以把 libtorch/lib 文件夹也添加到环境变量里。

这是我添加的几个环境变量。

在这里插入图片描述
如果出现找不到 dll 的错误,大概率是环境变量没配置好,还有一个更粗暴的方法就是把缺的 dll 文件放到 exe 文件夹下。

在这里插入图片描述

2. 转换 Pytorch 模型

这一步需要将 Pytorch 模型转换成 Torch Script,这东西具体是个啥可以看 官方文档

转换模型可以有两种方法,第一种是 tracing,使用一个示例输入来获取模型结构。
第二种是在模型中添加显式 annotations,以告知 Torch Script 编译器可以根据 Torch Script 语言施加的约束直接解析和编译模型代码。

2.1 通过 Tracing 转换

import torch
import torchvision

# 模型实例
model = torchvision.models.resnet18()

# 设置一个示例输入
example = torch.rand(1, 3, 224, 224)

# 使用 torch.jit.trace 生成 torch.jit.ScriptModule
traced_script_module = torch.jit.trace(model, example)

# 保存转换后的模型
traced_script_module.save("traced_resnet_model.pt")

2.2 通过 Annotation 转换

如果模型有特定的控制流,例如控制流依赖于输入:

import torch

class MyModule(torch.nn.Module):
    def __init__(self, N, M):
        super(MyModule, self).__init__()
        self.weight = torch.nn.Parameter(torch.rand(N, M))

    def forward(self, input):
        if input.sum() > 0:
          output = self.weight.mv(input)
        else:
          output = self.weight + input
        return output

# 然后通过 `torch.jit.script` 将模块转换为 ScriptModule。
my_module = MyModule(10,20)
sm = torch.jit.script(my_module)

# 保存模型
my_module.save("my_module_model.pt")

3. 新建项目

新建项目时我用的不是 vs2019,而是 Qt Creator,因为 Libtorch 给的是 cmake 的构建方式,使用 Qt 新建 cmake 项目时会建立所有需要的东西。

新建一个 widget 应用。

在这里插入图片描述
这里选择 cmake。

在这里插入图片描述
项目建立完成后可以选择直接用 Qt Creator 写,也可以用 vs2019 打开 cmake 文件继续修改项目。我是改用了 vs2019,毕竟宇宙第一 ide

4. 配置 cmake

使用 Qt 创建项目后 cmake 文件里已经添加了部分必要的命令,这里只需要进行简单的修改。

下面贴出我的 cmake 文件,其中有些路径需要替换成自己的

cmake_minimum_required(VERSION 3.5)

project(SegTool LANGUAGES CXX)

set(CMAKE_INCLUDE_CURRENT_DIR ON)

set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

set(Qt5_DIR E:/Qt/5.14.2/msvc2017_64/lib/cmake/Qt5)
set(Qt5Widgets_DIR E:/Qt/5.14.2/msvc2017_64/lib/cmake/Qt5Widgets)
set(Qt5Gui_DIR E:/Qt/5.14.2/msvc2017_64/lib/cmake/Qt5Gui)
set(Qt5Core_DIR E:/Qt/5.14.2/msvc2017_64/lib/cmake/Qt5Core)
find_package(Qt5 COMPONENTS Widgets Core Gui REQUIRED)

set(OpenCV_DIR "D:/Lib/opencv/build/x64/vc15/lib")
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})

set(Torch_DIR "D:/Lib/libtorch-debug-cpu-1.6/share/cmake/Torch")
find_package(Torch REQUIRED)
include_directories(${TORCH_INCLUDE_DIRS})

qt5_wrap_ui(UI_HEADERS mainwindow.ui)  # 通过 ui 文件生成对应的头文件

add_executable(${PROJECT_NAME}
    main.cpp
    mainwindow.cpp
    mainwindow.h
    ${UI_HEADERS}
)

target_link_libraries(${PROJECT_NAME} Qt5::Widgets)
target_link_libraries(${PROJECT_NAME} ${TORCH_LIBRARIES} ${OpenCV_LIBS})
set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 11)

这里我设置了 Qt 路径,因为如果用 Python 的可能 Anaconda 里也有,但是用 Anaconda 里的会有问题。

在 vs2019 中打开 CMakeSettings.json 可以看到其他配置信息,把 显示高级变量 勾选上可以看到所有 cmake 变量,可以看看设置都对不对。CMakeLists.txt 里定义的变量会覆盖 json 文件里的。

在这里插入图片描述
配置完成后 Ctrl + S 就可以看到 cmake 完成了。

在这里插入图片描述

5. 测试

接下来用一段 C++ 代码来测试是否成功,修改 mainwindow.cpp 文件(根据你创建时的类命名的)。

代码里的模型和图片路径替换成你的就行了。

#include "mainwindow.h"
#include "./ui_mainwindow.h"

#include <iostream>
#include <opencv2/opencv.hpp>

#undef slots
#include <torch/torch.h>
#include <torch/script.h>
#define slots Q_SLOTS

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    torch::jit::script::Module module;
    module = torch::jit::load("model.pt");  // 模型路径
    std::cout << "Succeed in loading model" << std::endl;

    cv::Mat image = cv::imread("C:/Users/lan/Desktop/2.jpg", 1);  // 图片路径
    cv::namedWindow("My Image");
    cv::imshow("My Image", image);
}

MainWindow::~MainWindow()
{
    delete ui;
}

代码中有一段 #undef,不加会发生语法错误,不知道为什么,反正加上就对了。

然后就可以编译、生成了,编译的时候会出现很多警告,应该是 #undef 导致的,可以忽略。

在这里插入图片描述
这是全部完成后我的文件夹里的文件

在这里插入图片描述

这是运行结果

在这里插入图片描述
成功!

所有的准备操作到这里就结束了,后面就可以开始写 qt 界面了。

评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值