在C++部署Pytorch(Libtorch)模型的方法总结(Win10+VS2017)

it2023-10-11  72

目录

1、准备工作(1)下载准备(2)TorchScript(.pt文件)准备 2、配置步骤(1)CMake配置(2)手动在VS配置 3、踩坑汇总

1、准备工作

(1)下载准备

下载安装VS2017安装配置OpenCV 可参考博客:VS2017配置opencv教程(超详细!!!) ,讲的非常详细。安装配置CMake(对于CMake配置法) 可参考博客:Windows下CMake安装教程下载Libtorch 下载地址:https://pytorch.org/,根据自己的系统情况来选择下载版本。 注意: (1)有debug和release两个版本,根据需要下载,debug版本的libtorch之后只能在debug下运行,release亦然。 (2)下载的Libtorch需和生成.pt文件的pytorch版本一致,否则会无法读取.pt文件。 下载并解压后,文件夹将有如下组成: 其中,include文件夹下是libtorch库的头文件; lib文件夹下是libtorch库的静态库(lib)和动态链接库(dll); share文件夹下有之后cmake配置时要find的.cmake文件,用于在cmake时让项目链接到libtorch库;

(2)TorchScript(.pt文件)准备

实际上,从Pytorch得到的网络模型接口的到C++就是通过Torch脚本(.pt文件)实现的。因此,需要先在Python中用Pytorch生成Torch脚本。

有两种将PyTorch模型转换为Torch脚本的方法。 第一种称为跟踪,一种机制,通过使用示例输入对模型的结构进行一次评估,并记录这些输入在模型中的流动,从而捕获模型的结构。这适用于有限使用控制流的模型。 第二种方法是在模型中添加显式批注,以告知Torch Script编译器可以根据Torch Script语言施加的约束直接解析和编译模型代码。

关于如何得到Torch脚本这里就不过多叙述了,想了解的可以参考以下资料: 在C++ 中加载 TorchScript 模型 官方TorchScript文档 这里放两个我用于测试的代码,第一个用于只用libtorch库的简单测试,输入为随机的向量。最终在工作目录中生成resnet18.pt文件。

import torch from torchvision.models import resnet18 model =resnet18() example = torch.rand(1, 3, 224, 224) traced_script_module = torch.jit.trace(model, example) traced_script_module.save("resnet18.pt")

第二个是用于libtorch+OpenCV库测试,之后需要在C++中用OpenCV读取输入图像。采用torchvision.models中的Resnet50网络模型,实现图像的分类,分类结果说明参考:ImageNet图像库1000个类别名称(中文注释不断更新)。最终生成resnet50.pt于工作目录中。

import torch import torchvision.models as models from PIL import Image import numpy as np image = Image.open("E:/HM_DL/torch_test/torch_py/test1.jpg") image = image.resize((224, 224),Image.ANTIALIAS) image = np.asarray(image) image = image / 255 image = torch.Tensor(image).unsqueeze_(dim=0) image = image.permute((0, 3, 1, 2)).float() model = models.resnet50(pretrained=True) model = model.eval() resnet = torch.jit.trace(model, torch.rand(1,3,224,224)) # output=resnet(torch.ones(1,3,224,224)) output = resnet(image) max_index = torch.max(output, 1)[1].item() print(max_index) # ImageNet1000类的类别序 resnet.save('resnet50.pt')

最终,通过将脚本模块序列化为文件,得到模型的.pt文件,这个文件就将作为C++的输入,用于实现在C++中部署Pytorch。

2、配置步骤

利用VS在C++中部署Pytorch模型的配置方法大致有两种:基于CMake自动配置,手动在VS中配置。

(1)CMake配置

以我自己为例,首先在E:\torch_test下创建名为Example的文件夹,然后在该文件夹下分别创建C++测试代码(example-app.cpp)和CMakeLists.txt,以及一个名为build的文件夹。 example-app.cpp示例: 配合第一个Python程序,测试libtorch库是否可用。

#include <torch/script.h> // One-stop header. #include <iostream> #include <memory> int main() { // Deserialize the ScriptModule from a file using torch::jit::load(). //std::shared_ptr<torch::jit::script::Module> module = // torch::jit::load("E:/HM_DL/torch_test/traced_resnet_model.pt"); using torch::jit::script::Module; Module module = torch::jit::load("E:/HM_DL/torch_test/traced_resnet_model.pt"); std::cout << "ok\n"; // Create a vector of inputs. std::vector<torch::jit::IValue> inputs; inputs.push_back(torch::ones({1, 3, 224, 224})); // Execute the model and turn its output into a tensor. at::Tensor output = module.forward(inputs).toTensor(); std::cout << output.slice(/*dim=*/1, /*start=*/0, /*end=*/5) << '\n'; while (1) ; }

配合第二个Python程序,同时测试libtorch库和OpenCV库。

#include <torch/script.h> #include <torch/torch.h> #include <iostream> #include <opencv2/core/core.hpp> #include <opencv2/highgui.hpp> #include <opencv2/opencv.hpp> #include <vector> void TorchTest() { torch::jit::script::Module module = torch::jit::load("E:/HM_DL/torch_test/torch_py/resnet.pt"); std::cout << "Load model successful!" << std::endl; std::vector<torch::jit::IValue> inputs; inputs.push_back(torch::zeros({1, 3, 224, 224})); at::Tensor output = module.forward(inputs).toTensor(); auto max_result = output.max(1, true); auto max_index = std::get<1>(max_result).item<float>(); std::cout << max_index << std::endl; } void Classfier(cv::Mat &image) { torch::Tensor img_tensor = torch::from_blob( image.data, {1, image.rows, image.cols, 3}, torch::kByte); img_tensor = img_tensor.permute({0, 3, 1, 2}); img_tensor = img_tensor.toType(torch::kFloat); img_tensor = img_tensor.div(255); torch::jit::script::Module module = torch::jit::load("E:/HM_DL/torch_test/torch_py/resnet.pt"); torch::Tensor output = module.forward({img_tensor}).toTensor(); auto max_result = output.max(1, true); auto max_index = std::get<1>(max_result).item<float>(); std::cout << max_index << std::endl; } int main() { // TorchTest(); cv::Mat image = cv::imread("E:/HM_DL/torch_test/torch_py/test1.jpg"); cv::resize(image, image, cv::Size(224, 224)); cv::imshow("image", image); cv::waitKey(0); std::cout << image.rows << " " << image.cols << " " << image.channels() << std::endl; Classfier(image); return 0; }

CMakeLists.txt示例:

cmake_minimum_required(VERSION 3.12 FATAL_ERROR) project(example-app) find_package(Torch REQUIRED) find_package(OpenCV REQUIRED) if(NOT Torch_FOUND) message(FATAL_ERROR "Pytorch Not Found!") endif(NOT Torch_FOUND) message(STATUS "Pytorch status:") message(STATUS " libraries: ${TORCH_LIBRARIES}") message(STATUS "OpenCV library status:") message(STATUS " version: ${OpenCV_VERSION}") message(STATUS " libraries: ${OpenCV_LIBS}") message(STATUS " include path: ${OpenCV_INCLUDE_DIRS}") add_executable(example-app example-app.cpp) target_link_libraries(example-app ${TORCH_LIBRARIES} ${OpenCV_LIBS}) set_property(TARGET example-app PROPERTY CXX_STANDARD 11)

然后打开cmd终端,进入build文件夹,输入:

cmake -DCMAKE_PREFIX_PATH=D:\Opencv\opencv\build\x64\vc14\lib;D:\Code_Lib\libtorch -G "Visual Studio 15 Win64" ..

其中,-DCMAKE_PREFIX_PATH后要写你下载的libtorch库的绝对路径和opencv库下\build\x64\vc14\lib的绝对路径。"Visual Studio 15 Win64"表示用VS2017 x64编译。另外注意,一定不要忘了最后的..,这表示采用上一级目录下的cmake文件,否则会报错说build下没找到cmake文件。

运行成功的话会生成解决方案,选择合适的编译方式,生成可执行文件,然后运行。如有报错,参考我的C++部署Pytorch(Libtorch)出现问题、错误汇总

(2)手动在VS配置

除了采用CMake的方式,也可以直接在一个已建项目里通过配置环境属性来将项目连接到libtorch库。 下面以一个新建空项目为例,展示一下具体步骤。

首先用VS新建一个空项目。在解决方案资源管理器》源文件下添加一个新的cpp文件,将上述的测试代码复制进去。接下来开始配置属性,进入属性管理器》Debug | x64 》,右键点击Microsoft.Cpp.x64.user,选择“添加新项目属性表” 名称按自己喜好和功能来定,保存在合适的目录下。这样可以为libtorch和opencv建立专门的属性表,方便之后管理和使用。右键建立的属性表,选择属性。开始配置libtorch属性表。在 C/C++=>附加包含目录 中添加libtorch库的包含头文件路径: D:\Code_Lib\libtorch\include D:\Code_Lib\libtorch\include\torch\csrc\api\include

前者对应#include <torch/script.h>,后者对应#include <torch/torch.h>。

在 链接器=>常规=>附加库目录 中添加libtorch库的lib库路径: D:\Code_Lib\libtorch\lib 在 链接器=>输入=>附加依赖项 中添加需要的lib文件,如果不放心,可以把libtorch\lib目录下的所有lib文件都写进去。 举例: asmjit.lib c10.lib c10_cuda.lib caffe2_detectron_ops_gpu.lib caffe2_module_test_dynamic.lib caffe2_nvrtc.lib clog.lib cpuinfo.lib dnnl.lib fbgemm.lib libprotobuf.lib libprotobuf-lite.lib libprotoc.lib mkldnn.lib torch.lib torch_cuda.lib torch_cpu.lib OpenCV的配置参考VS2017配置opencv教程(超详细!!!)回到解决方案资源管理器,右键点击建立的项目,进入“属性”。 在 调试=>环境 里添加libtorch动态库的路径 PATH=D:\Code_Lib\libtorch\lib;%PATH%

11. 将 C/C++ => 语言 => 符合模式,改为否;C/C++ => 常规=> SDL检查,改为否。

至此,在C++中部署Libtorch完成。可以通过运行测试程序进行测试。

3、踩坑汇总

如果过程中有踩坑的可以参考我的踩坑总结: C++部署Pytorch(Libtorch)出现问题、错误汇总

最新回复(0)