博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Libtorch部署模型
阅读量:4136 次
发布时间:2019-05-25

本文共 4678 字,大约阅读时间需要 15 分钟。

Libtorch部署显著性目标检测网络BASNet

是Pytorch官方提供的C++ API,使用方法可以说是很大程度上还原了Pytorch。

一、环境配置

  • GitHub地址:
  • VS2017+CUDA 10.1+cuDNN 7.6.5+OpenCV 3.4.11
  • Pytorch 1.5.0+torchvision 0.6.0
  • Libtorch 1.5.0 (release):提取码:865k

Libtorch下载的版本一定要和Pytorch版本对应,我这里提供的是release版本的Libtorch

注:
1.原作者GitHub上推荐的是用Pytorch 0.4.0来跑,但是Libtorch是从Pytorch 1.0开始支持的,所以尽量升级为1.x的来运行
2.!!!Pytorch,Libtorch,CUDA,cuDNN版本一定要一一对应
3.训练模型生成.pth的Pytorch版本也最好和转换为torchscript的.pt文件最好也一致,不要用0.4.0的训练用1.7.0的转换

二、torchscript生成.pt文件

转换之前修改BASNet.py文件(注意这个时候应该已经是训练完了,不要在训练前修改)344行 return F.sigmoid(dout), F.sigmoid(d1), F.sigmoid(d2), F.sigmoid(d3), F.sigmoid(d4), F.sigmoid(d5), F.sigmoid(d6), F.sigmoid(db)只return第一个值。不更改的话C++那边forward的时候会报错。似乎也能用tuple来接收多个值,这里我就没有研究了。

import torchfrom model import BASNet	#model文件夹下的BASNet.py文件model_dir = r"./saved_models/basnet_bsi/basnet_best.pth"model = BASNet(3,1)			# channels, classesmodel.load_state_dict(torch.load(model_dir))if torch.cuda.is_available():	model.cuda()model.eval()example = torch.rand(1,3,256,256).cuda() 		# input exampletraced_script_module = torch.jit.trace(model,example)traced_script_module.save(r"./basnet.pt")

.cuda()很重要,挂载到CUDA上,在C++那边既可以用CPU计算,也可以用GPU计算。反之则只能用CPU计算。

参考:

三、Libtorch部署

Libtorch配置有两种方式,一种是CMake,一种是VS手动配置。这里我选择的是VS手动配置

下载好的Libtorch文件列表如下:
在这里插入图片描述

1.添加环境变量

在这里插入图片描述

2.VS配置环境

(1)创建一个空项目

(2)添加各种路径

i.项目—》属性—》C/C++—》常规—》附加包含目录

D:\Libraries\libtorch\includeD:\Libraries\libtorch\include\torch\csrc\api\include

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

在这里插入图片描述

ii.项目—》属性—》链接器—》常规—》附加库目录

在这里插入图片描述
iii.项目—》属性—》链接器—》输入—》附加依赖项
在这里插入图片描述
不放心的话,可以把libtorch\lib目录下的所有lib文件都写进去:

asmjit.libc10.libc10_cuda.libcaffe2_detectron_ops_gpu.libcaffe2_module_test_dynamic.libcaffe2_nvrtc.libclog.libcpuinfo.libfbgemm.liblibprotobuf.liblibprotobuf-lite.liblibprotoc.libmkldnn.libtorch.libtorch_cuda.libtorch_cpu.lib

iv.项目—》属性—》C/C++目录—》常规—》SDL检查 :否

在这里插入图片描述
v.项目—》属性—》C/C++目录—》语言—》符合模式 :否
在这里插入图片描述
vi.新建项目—》属性—》连接器—》命令行—》其他选项:
添加**/INCLUDE:?warp_size@cuda@at@@YAHXZ**
在这里插入图片描述
测试

#include "torch/torch.h"#include "torch/script.h"int main(){
torch::Tensor output = torch::randn({
3,2 }); std::cout << output; return 0;}

输出:

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

四、BASNet demo

#include "torch/torch.h"#include "torch/script.h"#include 
#include
using std::cout;using std::endl;using std::string;using torch::jit::script::Module;const string image_path = "C:/Developer/BASNet test/0003.jpg";const string module_path = "C:/Developer/BASNet test/basnet.pt";int main(int argc, char **argv){
cout << "CUDA是否可用:" << (torch::cuda::is_available() ? "√" : "×") << endl; cout << "cudnn是否可用:" << (torch::cuda::cudnn_is_available() ? "√" : "×") << endl; // load module Module module; try {
module = torch::jit::load(module_path); module.to(torch::kCUDA); } catch (const c10::Error& e) {
std::cerr << "Error\n"; } // 读入图像为cv::Mat,做resize cv::Mat image = cv::imread(image_path, cv::ImreadModes::IMREAD_COLOR); int img_h = image.rows; // 原始图像的高 int img_w = image.cols; // 原始图像的宽 cv::cvtColor(image, image, cv::COLOR_BGR2RGB); // BGR->RGB cv::Mat image_transfomed; cv::resize(image, image_transfomed, cv::Size(256, 256)); // Mat转Tensor torch::Tensor tensor_image = torch::from_blob(image_transfomed.data, {
image_transfomed.rows, image_transfomed.cols, 3 }, torch::kByte); //{ 256,256,3 } tensor_image = tensor_image.toType(torch::kFloat); // 为了下一步归一化除255,将无符号整型转为float型 tensor_image = tensor_image.div(255.0); // 归一化 tensor_image = tensor_image.permute({
2,0,1 }).unsqueeze(0); // opencv读取的图像矩阵存储形式:H x W x C, 但是Pytorch中Tensor的存储为:N x C x H x W, 因此需要进行变换 tensor_image = tensor_image.to(torch::kCUDA); // perdict at::Tensor output = module.forward({
tensor_image }).toTensor(); // output.size = { 1,1,256,256 } at::Tensor predict(output); predict = predict.squeeze(0); // 降维 predict = predict.mul(255).clamp(0, 255).to(torch::kU8); // 反归一化并转换为无符号整型 predict = predict.to(torch::kCPU); // kCUDA报错 // Tensor转Mat cv::Mat result(image_transfomed.rows, image_transfomed.cols, CV_8UC1, predict.data_ptr()); // (1) CV_8UC1√ CV_8UC3× (2) 必须是256×256,若是直接resize为原图大小则出错 cv::resize(result, result, cv::Size(img_w, img_h)); // 还原为原尺寸 cv::imshow("result", result); cv::imwrite("../prediction.png", result); cv::waitKey(0); return 0;}

输入:

在这里插入图片描述
输出:
在这里插入图片描述
done!!!

可能会遇到的问题:at::Scalar不明确

原因:使用Libtorch构建C++推理程序中,因为使用 opencv的Scalar类型,导致和Libtorch命名空间的Scalar冲突。
修改 libtorch/include/ATen/detail/CUDAHooksInterface.h的第26行:

namespace at{
using c10:Allocator; // 添加命名空间

修改libtorch/include/ATen/core/TensorBody.h的第35行

namespace at{
using c10::Scalar; //添加命名空间

参考:

萌新一个,因为项目需要用C++,只有在没有Pytorch基础的情况下强上Libtorch,顺带也学习了一下Pytorch。Libtorch这部分的资料比较少,踩了很多坑,在此记录一下。

参考链接

[1]

[2]
[3]
[4]
[5]
[6]

转载地址:http://ucavi.baihongyu.com/

你可能感兴趣的文章
【JavaScript 教程】浏览器—History 对象
查看>>
JavaScript深入理解之闭包
查看>>
这才是学习Vite2的正确姿势!
查看>>
7 个适用于所有前端开发人员的很棒API,你需要了解一下
查看>>
25个构建Web项目的HTML建议,你需要了解一下!
查看>>
【web素材】02-10款大气的购物商城网站模板
查看>>
6种方式实现JavaScript数组扁平化(flat)方法的总结
查看>>
如何实现a===1 && a===2 && a===3返回true?
查看>>
49个在工作中常用且容易遗忘的CSS样式清单整理
查看>>
20种在学习编程的同时也可以在线赚钱的方法
查看>>
隐藏搜索框:CSS 动画正反向序列
查看>>
12 个JavaScript 特性技巧你可能从未使用过
查看>>
127个超级实用的JavaScript 代码片段,你千万要收藏好(上)
查看>>
【视频教程】Javascript ES6 教程27—ES6 构建一个Promise
查看>>
【5分钟代码练习】01—导航栏鼠标悬停效果的实现
查看>>
127个超级实用的JavaScript 代码片段,你千万要收藏好(中)
查看>>
8种ES6中扩展运算符的用法
查看>>
【视频教程】Javascript ES6 教程28—ES6 Promise 实例应用
查看>>
127个超级实用的JavaScript 代码片段,你千万要收藏好(下)
查看>>
【web素材】03-24款后台管理系统网站模板
查看>>