signed

QiShunwang

“诚信为本、客户至上”

Pytorch C++ windows部署教程

2021/4/26 20:26:50   来源:

Pytorch C++ windows部署教程

  • 0 所需环境
  • 1 将PyTorch模型转换为Torch Script
  • 2 C++调用pytorch模型
  • 3 配置opencv
  • 4 编译
  • 参考文献

0 所需环境

软件:

  1. VS 2017 或 VS 2019

  2. Cmake :安装过程中选择添加环境变量
    (Cmake安装:https://cmake.org/download/)
    部署包:

  3. Libtorch
    Libtorch是pytorch官方的部署工具包,已经预编译好了,不需要我们去编译
    我们在官网下载适合于Windows的libtorch,可以直接下载稳定版并解压到任意位置。libtorch有CPU版本的和GPU版本的(经网友测试和CPU使用教程类似),这里以CPU版本为例进行介绍:
    (下载地址:https://pytorch.org/ )
    在这里插入图片描述

  4. opencv 包
    官网下载或者服务器下载(opencv4.3.0版本),实验室下载opencv为预编译版本,不需要额外编译。

1) 下载opencv-4.3.0-vc14-vc15.exe

  1. 提取模型到任意位置
    在这里插入图片描述

1 将PyTorch模型转换为Torch Script

在训练端(windows和linux通用,pytorch环境)要通过tracing来将PyTorch模型转换为Torch脚本,必须将模型的实例以及样本输入传递给torch.jit.trace函数.这将生成一个torch.jit.ScriptModule对象,并在模块的forward方法中嵌入模型评估的跟踪。下文中以图像分割为案例。
具体步骤:
0. 训练模型并保存 .pt 参数文件

  1. 运行下列代码:
2.	import torch  
3.	from unet import UNet  
4.	   
5.	#载入模型和训练参数
6.	model = UNet(n_channels=1, n_classes=1).cuda()  
7.	model=torch.load('./checkpoints/fcn_model_30.pt').cpu()  
8.	
9.	#使用eval测试模式,不然会导致存在batchnorm模型无法使用
10.	model.eval()  
11.	   
#一个模型forward函数的随机输入(保证输入大小与训练时输入大小一致)
12.	example = torch.rand(1,1,512,512) 
13.	   
14.	#  通过 tracing使用 torch.jit.trace 生成  torch.jit.ScriptModule.  
15.	traced_script_module = torch.jit.trace(model, example)  
16.	output = traced_script_module(torch.ones(1,3,512,512))  
17.	traced_script_module.save("./checkpoints/ torch_script_eval.pt")  
18.	   
19.	# 测试输出
20.	print(output)  
  1. 运行结果生成ScriptModule模型torch_script_eval.pt

2 C++调用pytorch模型

  1. 构建测试文件夹test

  2. 在test文件夹中编写c++测试test.cpp代码:其中主要包括图像预处理与调用模型,图像预处理应该与训练时保持一致

1.	#include <torch/script.h> // One-stop header.  
2.	  
3.	#include<opencv2/opencv.hpp>  
4.	  
5.	#include <vector>  
6.	#include <iostream>  
7.	#include <memory>  
8.	  
9.	using namespace cv;  
10.	  
11.	int main(int argc, const char* argv[]) {  
12.	  if (argc != 3) {  
13.	    std::cerr << "usage: example-app <path-to-exported-script-module> <path-to-image>\n";  
14.	    return -1;  
15.	  }  
16.	  
17.	  Mat src = imread(argv[2]);  
18.	  
19.	  int img_size = 512;  
20.	  
21.	  resize(src, src, Size(img_size, img_size));  // resize 图像  
22.	  //cvtColor(src, src, COLOR_BGR2GRAY);  // bgr -> gray  
23.	  //cvtColor(src, src, COLOR_BGR2RGB);  // bgr -> gray  
24.	  Mat float_image;  
25.	  auto img_tensor = torch::from_blob(src.data, { 512,512,1 }, torch::kByte);  
26.	  img_tensor = img_tensor.permute({ 2,0,1 });//(h,w,c) to (c, h, w)  
27.	  img_tensor = img_tensor.toType(torch::kFloat);  
28.	  img_tensor = img_tensor.unsqueeze(0);//(c,h,w) to (b, c,h,w)  
29.	  
30.	  
31.	  torch::jit::script::Module module;  
32.	  try {  
33.	    // Deserialize the ScriptModule from a file using torch::jit::load().  
34.	    module = torch::jit::load(argv[1]);  
35.	  }  
36.	  catch (const c10::Error& e) {  
37.	      std::cerr << "error loading the model\n";  
38.	      return -1;  
39.	  }  
40.	  
41.	  at::Tensor output = module.forward({ img_tensor }).toTensor();  
42.	  output = torch::sigmoid(output);  
43.	  output = output.squeeze(0).detach().permute({ 1,2,0 }).squeeze();//(b,c,h,w) to (c,h,w) to (h,w,c) to(h,w)  
44.	  output = output.gt(0.5);//大于0.5的为1  
45.	  output.unsqueeze(-1);  
46.	  output = output.mul(255).clamp(0, 255).to(torch::kU8);//转化为0-255像素  
47.	  Mat result(output.size(0), output.size(1), CV_8UC1);  
48.	  memcpy((void*)result.data, output.data_ptr(), sizeof(torch::kU8) * output.numel());  
49.	  imwrite("result.jpg", result);  
50.	  
51.	  std::cout << "ok\n";  
52.	} 

3.在test文件夹中编写CMakeLists.txt文件

1.	cmake_minimum_required(VERSION 3.0 FATAL_ERROR)  
2.	project(test)  
3.	  
4.	find_package(Torch REQUIRED)  
5.	  
6.	add_executable(test test.cpp)  
7.	target_link_libraries(test "${TORCH_LIBRARIES}")  
8.	set_property(TARGET test PROPERTY CXX_STANDARD 14)  
  1. 键盘输入win+R,输入cmd,点击确定,进入windows终端

在这里插入图片描述
4. 进入test所在文件夹,终端输入命令

cmake -DCMAKE_PREFIX_PATH=H:/arrange/libtorch(libtorch文件夹位置) -DCMAKE_BUILD_TYPE=Release -G "Visual Studio 15 2017 Win64"(如果是VS2015的话,"Visual Studio 14 2015 Win64"

如果顺利,应可以看到如下输出:
在这里插入图片描述
Cmake之后的test文件夹为:
在这里插入图片描述
5. 点击test.vcxproj,右键test并设为启动项目
在这里插入图片描述

3 配置opencv

我们发现与opencv相关的代码下有红线,这是因为我们没有配置opencv

1.右键test并点击属性

在这里插入图片描述
2.配置属性->VC++目录->常规->包含目录,添加三个路径:
Path\to\Opencv\build\include
Path\to\Opencv\build\include\opencv2,如图操作,确认。

在这里插入图片描述
3.VC++目录->常规->库目录中加入D:\Path\Opencv\build\x64\vc15\lib(以自己的安装目录为主)

在这里插入图片描述
5.与opencv相关的代码,红色的下划线消失
在这里插入图片描述

4 编译

  1. 点击本地windows调试器
    编译成功但是出现下述错误,找不到c10.dll。
    在这里插入图片描述
  2. 编译之后test文件夹中出现Release文件夹,进入之后如下:

在这里插入图片描述
3. 打开path\to\libtorch\lib,将所有的dll文件复制到Release文件夹
在这里插入图片描述
4. 打开path\to\opencv\build\x64\vc15\bin,将所有dll文件复制到Release文件夹
在这里插入图片描述
5. 复制测试图像和模型到Release文件夹
在这里插入图片描述
6. 打开windows终端到release文件夹 输入

test.exe torch_script_eval.pt(模型名) 12.jpg  (图像名)
test.exe torch_script_eval.pt 12.jpg

顺利编译的话,输出为:

在这里插入图片描述
Release文件夹中生成result.jpg, 结果如下:
在这里插入图片描述
至此,部署成功
只要复制Release文件夹,可以在不同电脑上进行测试。

参考文献

1.pytorch官方部署说明:https://pytorch.org/tutorials/advanced/cpp_export.html
2. Win10+VS2017+PyTorch(libtorch) C++ 基本应用
https://blog.csdn.net/gulingfengze/article/details/92013360
3. opencv 配置博客:https://blog.csdn.net/qq321772514/article/details/90514538