在ubuntu下将Pytorch模型部署到c++(二)(模型转换与调用)

模型转换

pytorch模型部署到c++需要转化为libtorch可读取的torchscript格式,或者更通用的onnx格式

转换torchscript格式

pytorch模型转换中用到trace方法运行一次网络并将模型中的参数与网络结构融合
注意当网络输出是list时trace中加入strict=False避免warning

  	net = PoseEstimationWithMobileNet() # 调用定义好的网络
    checkpoint = "./checkpoint_iter_370000.pth"
    net.load(checkpoint)
    net.eval()

    forward_input = torch.rand(1, 3, 256, 394) # 模型的输入Tensor大小

    # trace_model = torch.jit.trace(net, forward_input, strict=False)  
    trace_model = torch.jit.trace(net, forward_input)  
    trace_model.save('./pose.pt')

转换onnx格式

	net = PoseEstimationWithMobileNet()
    checkpoint = "./checkpoint_iter_370000.pth"
    net.load(checkpoint)
    net.eval()

    forward_input = torch.rand(1, 3, 256, 394) # 模型的输入Tensor大小
    trace_model = torch.jit.trace(net, forward_input)
    # save onnx
    input_names = ["input"]
    output_names = ["output"]
    torch.onnx.export(net, forward_input, "pose.onnx", verbose=False, input_names=input_names,
                      output_names=output_names)

模型调用

利用opencv 载入并调用onnx格式模型

本文中利用opencv载入onnx
注意opencv的ReadNetFromTorch函数用来读取torch模型而不是pytorch,所以不能直接读取.pt文件
cv::dnn::Net inputNet = cv::dnn::readNet("pose.onnx");
调用模型
cv::Mat input = cv::imread(inputFile, cv::IMREAD_COLOR);
inputNet.setInput(input);

利用libtorch载入并调用pt格式模型

由于本项目中输入图片的预处理和输出图片的前向传播过程都使用opencv函数编写,格式也都是opencv的Mat格式,所以在Libtorch载入网络过程前后都需要进行libtorch中Tensor格式和opencv中Mat的互相转换.
这里提一下Tensor和Mat在获取高维矩阵结构时的不同

cv::Mat inputBlob = ...
int size0 = inputBlob.size[0]; //1 
int size1 = inputBlob.size[1]; //3
int size2 = inputBlob.size[2]; //256
int size3 = inputBlob.size[3]; //394
torch::Tensor img_tensor = ...
std::cout << "size:"<< img_tensor.sizes() << std::endl;	

模型载入

torch::jit::script::Module module;
	module = torch::jit::load("/pose.pt" ); 

Mat to Tensor 类型转换

网上找到的代码大多为三维三通道图像通过torch::from_blob函数生成四维单通道Tensor,输入的维度信息大概如下

//opencv format H*W*C
 auto input_tensor = torch::from_blob(frame.data, {1, frame_h, frame_w, kCHANNELS});

然而本项目中需要处理图像经过预处理后生成的四维单通道Mat,经过多次数据输出对比,如下的代码可以成功转换数据格式并且不影响数据存放顺序

// torch::Tensor img_tensor = torch::from_blob(inputBlob.data, {inputBlob.size[0], inputBlob.size[1], inputBlob.size[2], inputBlob.size[3]},torch::kFloat32);
torch::Tensor img_tensor = torch::from_blob(inputBlob.data, {1,3,256,394},torch::kFloat32); //输入四维 和上一行代码等效 即按输入Mat维度顺序传入函数 不需要下一行的维度转换
	// img_tensor = img_tensor.permute({0,3,1,2});
  // img_tensor = img_tensor.div(255);  预处理时经过归一化处理 这里删掉

References :
https://zhuanlan.zhihu.com/p/92090874

模型调用

auto Output = module.forward({img_tensor}).toTensorList();

Tensor to Mat 类型转换

// netOutput = netOutput.squeeze().detach().permute({1, 2, 0}); 需要4维Mat所以不进行squeeze操作
// netOutput = netOutput.mul(255).clamp(0, 255).to(torch::kU8);网络需要Float结构不转ku8
int size[4];//创建Tensor结构大小的size数组 
for(int i=0;i<sizeof(netOutput.sizes())/sizeof(int);i++)
	size[i] = netOutput.sizes()[i] ;
cv::Mat netOutputBlob(4,size,CV_32FC1,Output.data_ptr());	
//注意需要的数据类型,这里选择CV_32FC1格式

References :
https://blog.csdn.net/u011341856/article/details/102922246 高维Mat的创建

Mat、Tensor数据格式总结

cv::Mat
 数值                     类型                          
CV_8U                 8位无符号整数                          
CV_8S                 8 位符号整数                         
CV_16U                16 位无符号整数                       
CV_16S                16 位符号整数                        
CV_32S                32 位符号整数                  
CV_32F                32 位浮点数                       
CV_64F                64 位浮点数                      

在这里插入图片描述

Mat_<uchar>---------CV_8U
Mat<char>-----------CV_8S
Mat_<short>---------CV_16S
Mat_<ushort>--------CV_16U
Mat_<int>-----------CV_32S
Mat_<float>----------CV_32F
Mat_<double>--------CV_64F

在这里插入图片描述
References :
https://blog.csdn.net/qq_39790992/article/details/81280249
https://blog.csdn.net/weixin_40647819/article/details/80380836

c++输出txt

由于数据类型经过多次转换,数据的存储顺序可能发生变化,导致处理后的现象不正确,并且vscode调试功能并不方便,所以采用了较为直接的方法将转换前后数据输出txt进行对比

#include<iostream>
#include <fstream>
std::ofstream out("out.txt");//定义输出
out<<netOutput<<std::endl;
out.close();//关闭文件

References :
https://www.cnblogs.com/zhengfa-af/p/8157235.html

Tensor 数据遍历

Tensor和Mat数据遍历格式不同,输出代码也有所不同
Tensor可以直接输出

test<<netOutput<<std::endl;//tensor输出txt
Mat 数据遍历
 for(int i=0;i<netOutputBlob.size[1];i++) //mat遍历输出保存txt
	{for(int j=0;j<netOutputBlob.size[2];j++)
		{for(int k=0;k<netOutputBlob.size[3];k++)
			in<<netOutputBlob.ptr<float>(0,i,j)[k]<<std::endl;// 输出类型要根据Mat数据类型改变 比如float int 参考前文的Mat数据类型总结
 		}
}

References :
https://blog.csdn.net/u011518700/article/details/50835077

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
PyTorch模型转换为Tensorscript并部署于C平台需要以下步骤: 首先,要将PyTorch模型转换为Tensorscript模型。Tensorscript是一个用于高性能推理的图形执行模型,而PyTorch是一个用于深度学习训练和推理的框架。在转换过程中,我们需要使用TorchScript API。这个API允许将PyTorch模型转换为可序列化的脚本模型转换过程中,我们需要确保模型中使用的所有操作和模块都被支持并转换为Tensorscript的等效操作。有些高级功能和操作可能无法直接转换,需要对其进行手动的调整和替换。 完成模型转换后,我们可以开始部署这个Tensorscript模型到C平台。在部署之前,我们需要将Tensorscript模型保存为一个文件,以便在C平台中使用。可以使用TorchScript提供的函数将模型保存到硬盘上。 接下来,我们需要在C平台上使用一个能够加载并执行Tensorscript模型的库。一个常用的库是libTorch,它是PyTorchC++前端库,可以加载和执行Tensorscript模型。 在C平台上部署之前,我们需要确保我们的环境已经准备好了libTorch的依赖项,并且有正确的库和头文件路径。 部署的代码可以使用C或C++编写,并且需要加载Tensorscript模型,并将输入数据传递给模型进行推理。部署过程还需要处理模型的输出结果,并根据需求将结果展示、保存或传递给其他程序进行进一步的处理。 总结起来,将PyTorch模型转换为Tensorscript并部署到C平台需要将模型转换为Tensorscript模型,保存为文件,准备和安装libTorch的依赖项,并在C平台上编写代码来加载和执行Tensorscript模型

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值