pytorch 配置opencv_Windows下将PyTorch模型转成Libtorch并使用C++进行读取

Abstract

这是我在19年年初在上海卫宁健康AI Lab实习所做的一个小工作,主要是将一个模型从Pytorch模型下转换成C++可执行进而可以部署在服务器上。当时做的时候参考资料找不到行之有效的解决方案。摸索了很长时间最终完成,这里写出来在Windows上的整个过程。

Linux下没有尝试。

本机环境:

OS: Windows 10 专业版, GPU: GTX 960m

软件版本:CUDA 8.0 + 对应Cudnn、Python 3.7.1、pytorch 1.0.1、Visual Studio 2017、CMake 3.14、OpenCV 4.0.1。

1. LibTorch项目构建

  • 在官网下载libtorch,并解压到自己指定的目录下。
PyTorch​pytorch.org
57d53165e0a22e20f4a49c62e7687656.png
  • 先写一个C++的文件,内容可以是非常简单的。比如 example-app.cpp
#include<iostream>
void main(){
	cout<<”test”;
	return 1;
}
  • 新建一个CMakeLists.txt,内容:
cmake_minimum_required(VERSION 3.12 FATAL_ERROR)
project(demo)
find_package(OpenCV REQUIRED)
find_package(Torch REQUIRED)
add_executable(demo example-app.cpp)
target_link_libraries(demo ${TORCH_LIBRARIES})
set_property(TARGET demo PROPERTY CXX_STANDARD 11)

(注:这里的倒数第三行有example-app.cpp要和对应的cpp文件名一样)

  • 将cpp文件、CMakeLists.txt、libtorch文件夹放在一起,新建一个空文件夹,名为build。文件的组织形式如图1所示。

897d859b526a9b2302762f5955fc8e50.png
图1. Libtorch文件组织形式
  • 进入build文件夹中,管理员身份执行cmd命令,输入以下命令:
cmake -DCMAKE_PREFIX_PATH=..  -DCMAKE_BUILD_TYPE=Release -G "Visual Studio 15 Win64" -DTorch_DIR=F:NewTestlibtorchsharecmakeTorch DOpenCV_DIR=F:opencvopencvbuild

命令中,DTorch_DIR和DOpenCV_DIR要根据自己的电脑更改为对应电脑上libtorch和opencv存放的地方。然后回车,执行。

如果执行成功的话会输出以下的信息,如图2所示:

309abcb5e238436107a951863456d471.png
图2. 构建过程中CMD输出信息

(注:记得将opencv,libtorch,cmake的文件存放路径添加到windows操作系统的环境变量PATH里。)

执行完后,build文件里会生成许多文件。

这步做完,这整个的build文件夹里的文件就是生成好的c++文件,用vs打开demo.sln就可以引入#include<torch/torch.h>了

  • 删掉ALL_BUILD和ZERO_CHECK。编写完成时点击本地windows调试器即可运行,demo.sln文件和build文件夹外的cpp文件会同时更新。

2. 生成Libtorch模型

  • 利用网上提供的教程,比如 这篇 就可以,用torch.jit.trace将模型转换成libtorch可用的样式。在这里,不能用公司的模型,于是我在网上找了一个图片分类模型把转换成了model.pt用来做讲解。
  • 转换完成之后,点开build文件夹下的demo.sln(注意这时候网络输入图片dog.png和model.pt都要放在对应文件夹中),编写如下的代码:
#include <torch/script.h>
#include <torch/torch.h> 
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
#include <string>
#include <vector>

/* main */
int main() {
	std::shared_ptr<torch::jit::script::Module> module = torch::jit::load("model.pt");
	assert(module != nullptr);
	std::cout << "load model okn";

	std::vector<torch::jit::IValue> inputs;
	inputs.push_back(torch::rand({ 64, 3, 224, 224 }));

	double t = (double)cv::getTickCount();
	module->forward(inputs).toTensor();
	t = (double)cv::getTickCount() - t;
	inputs.pop_back();

	//load image with opencv and transform
	cv::Mat image;
	image = cv::imread("dog.png", 1);
	cv::cvtColor(image, image, cv::COLOR_BGR2RGB);
	cv::Mat img_float;
	image.convertTo(img_float, CV_32F, 1.0 / 255);
	cv::resize(img_float, img_float, cv::Size(224, 224));
	//std::cout << img_float.at<cv::Vec3f>(56,34)[1] << std::endl;
	auto img_tensor = torch::CPU(torch::kFloat32).tensorFromBlob(img_float.data, { 1, 224, 224, 3 });
	img_tensor = img_tensor.permute({ 0,3,1,2 });
	img_tensor[0][0] = img_tensor[0][0].sub_(0.485).div_(0.229);
	img_tensor[0][1] = img_tensor[0][1].sub_(0.456).div_(0.224);
	img_tensor[0][2] = img_tensor[0][2].sub_(0.406).div_(0.225);
	auto img_var = torch::autograd::make_variable(img_tensor, false);
	inputs.push_back(img_var);

	// Execute the model and turn its output into a tensor.
	torch::Tensor out_tensor = module->forward(inputs).toTensor();
	std::cout << out_tensor.slice(/*dim=*/1, /*start=*/0, /*end=*/10) << 'n';

	system("pause");
	return 0;
}

输入的图片是图3。

2839697389cc4e8d3c964c72182e4955.png
图3. 示例图片dog.png

此时,整个build文件下的组织形式是:

7137cde7c5e4eae35368aef81ed2b9fc.png
图4. 文件组织形式

然后在VS 2017里面点击Release x64 在本地运行调试器,就会产生如下的结果,如图5所示。输出出来了10个值,模型的运行成功了。

8df58356a83a5d735d5bd89e284e48c7.png
图5. 文件运行结果

(注:因为是在网上随便找的模型和图片做测试,所以这个分类结果不正确。但是从侧面说明了这样的方法可以让程序顺利运行下来。在后来将公司里的模型迁移至Libtorch上时,运行结果没有出现这样的数值错误。)

3. 可能会遇到的Bug

  • 出现Torch.dll, caffe.dll和另一个dll的缺失,无法运行程序。

2acb8fe32dc076b42c4c5f08f78af891.png
图7. Bug说明

这里其实三个动态链接库是没有缺失的,只不过系统没有找到对应位置。

解决方法:找到具体dll所在的地方,把目录添加进Windows的环境变量PATH里。

  • Cmake torch运行到CUDA这一步之后无法运行下去

解决方法:重新调整libtorch,检查路径有无问题。

  • 没有为 xxx.dll/ pdb 加载的符号文件

解决办法:1.检查自己的程序语句是否有问题,关键是检查,举例:检查imread(“xx.jpg”) 的图片引入路径。

2.手动添加符号文件:

Visual studio 工具栏里: 调试(D) --->选项(O)--->

165c197b650ffa23656322d7def67642.png
图8. 配置符号服务器

安装如上图,勾选 Microsoft符号服务器。

完成之后,在程序第一次执行,会花费一定时间去从服务器上加载符号文件,会比较慢,加载完成后,程序会继续执行。

4. 结尾

谢谢! 在解决整套流程的时候我也遇到了许多的问题,感谢他们无私的帮助。

如有问题,我的邮箱 lizheng1@stu.hznu.edu.cn 欢迎交流!

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值