最近做东西想要早windows下用C++调用训练好的网络模型,达到高速pridict。PyTorch火的一塌糊涂,兼容性也不错,发现有个C++ 的lib,好挺好用,不过windows就是各种坑,记录一下,以供参考。
PyTorchLib下载
https://pytorch.org/get-started/locally/
!!!务必根据自己的硬件配置选择版本!!!
VS属性表配置
下载后只要解压即可。打开vs -> 新建工程 -> 打开属性管理器(在哪就不用我说了吧)
- 与Opencv配置类似,对包含路径 / 库目录等进行配置
Attention!!包含目录有两个
- 链接器 -> 输入, 添加对应lib
这里有个小trick, 可以利用
dir *.lib
命令进行快速搜索
- dll配置
有时候调用dll文件是直接拷贝过来,如果文件很多就很麻烦,可以通过添加依赖项目的环境变量。PATH=D:\........\libtorch\lib;%PATH%
模型调用(直接上代码!)
实际调用过程的问题可以参考我的另一篇C++ windows调用ubuntu训练的PyTorch模型
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <torch/torch.h>
#include <torch/script.h>
// 有人说调用的顺序有关系,我这好像没啥用~~
int main()
{
torch::DeviceType device_type;
if (torch::cuda::is_available()) {
std::cout << "CUDA available! Predicting on GPU." << std::endl;
device_type = torch::kCUDA;
}
else {
std::cout << "Predicting on CPU." << std::endl;
device_type = torch::kCPU;
}
torch::Device device(device_type);
//Init model
std::string model_pb = "D:/......./resnet.pt";
auto module = torch::jit::load(model_pb);
module.to(at::kCUDA);
cv::Mat image=cv::imread("........./xxx.jpg") ;
cv::cvtColor(image, image, cv::COLOR_BGR2RGB);
cv::resize(image, image, cv::Size(100, 150));
// convert to tensort
torch::Tensor img_tensor = ToTensor(image).to(at::kCUDA); //ToTensor是自定义函数,下面有
torch::Tensor output = module.forward({ image }).toTensor();
auto max_result = output.max(1, true);
auto max_index = std::get<1>(max_result).item<float>(); //找出最大值的索引
return max_index;
}
相关报错
1. TORCH::CUDA::IS_AVAILABLE()返回为FALSE
在链接器中 -> 命令行 -> 其他选项, 添加
/INCLUDE:?warp_size@cuda@at@@YAHXZ
,根本不知道这是啥东西,反正有效ㄟ( ▔, ▔ )ㄏ
2. ToTensor(image).to(at::kCUDA)报错
再GPU上运行模型需注意,image数据和模型必须都在GPU上,不能在CPU上,容易报错。
3.批量输入报错
上面只写了个单个输入数据(1,3,100,150),很多时候要批量输入,单个输入费时费力,几经周折终于弄懂了,
torch::cat
一下就行了(其实跟python是一样的~~)
img_tensor = torch::cat({ img_tensor, img_tensor }, 0);
4.cv::Mat转Tensor
torch::Tensor toTensor(cv::Mat& image)
{
torch::Tensor img_tensor = torch::from_blob(image.data, { image.rows, image.cols, 3 }, torch::kByte);
img_tensor = img_tensor.permute({ 2, 0, 1 }).toType(torch::kFloat).div(255);
img_tensor = torch::data::transforms::Normalize<torch::Tensor>({ 0.485, 0.456, 0.406 }, { 0.229, 0.224, 0.225 })(img_tensor);
img_tensor = img_tensor.unsqueeze(0);
return img_tensor;
}
网友评论