在C+中部署python(libtoch)模型的方法总结+,PytorchLibtorch,Win10VS2017

 

 

目录

 

1、准备工作

(1)下载准备

 

D:\Code_Lib\libtorch\include
D:\Code_Lib\libtorch\include\torch\csrc\api\include

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

 

D:\Code_Lib\libtorch\lib

 

asmjit.lib
c10.lib
c10_cuda.lib
caffe2_detectron_ops_gpu.lib
caffe2_module_test_dynamic.lib
caffe2_nvrtc.lib
clog.lib
cpuinfo.lib
dnnl.lib
fbgemm.lib
libprotobuf.lib
libprotobuf-lite.lib
libprotoc.lib
mkldnn.lib
torch.lib
torch_cuda.lib
torch_cpu.lib

 

PATH=D:\Code_Lib\libtorch\lib;%PATH%

在这里插入图片描述
11. 将 C/C++ => 语言 => 符合模式,改为否;C/C++ => 常规=> SDL检查,改为否。

至此,在C++中部署Libtorch完成。可以通过运行测试程序进行测试。

3、踩坑汇总

如果过程中有踩坑的可以参考我的踩坑总结:
C++部署Pytorch(Libtorch)出现问题、错误汇总

 

转载自 https://www.pythonf.cn/read/152618

  • 下载安装VS2017
  • 安装配置OpenCV
    可参考博客: VS2017配置opencv教程(超详细!!!)
    ,讲的非常详细。
  • 安装配置CMake(对于CMake配置法)
    可参考博客: Windows下CMake安装教程
  • 下载Libtorch
    下载地址: https://pytorch.org/ ,根据自己的系统情况来选择下载版本。
    注意:
    (1)有debug和release两个版本,根据需要下载,debug版本的libtorch之后只能在debug下运行,release亦然。
    (2)下载的Libtorch需和生成.pt文件的pytorch版本一致,否则会无法读取.pt文件。
    下载并解压后,文件夹将有如下组成:
    在这里插入图片描述
    其中,include文件夹下是libtorch库的头文件;
    lib文件夹下是libtorch库的静态库(lib)和动态链接库(dll);
    share文件夹下有之后cmake配置时要find的.cmake文件,用于在cmake时让项目链接到libtorch库;
  • (2)TorchScript(.pt文件)准备

    实际上,从Pytorch得到的网络模型接口的到C++就是通过Torch脚本(.pt文件)实现的。因此,需要先在Python中用Pytorch生成Torch脚本。

    有两种将PyTorch模型转换为Torch脚本的方法。
    第一种称为 跟踪 ,一种机制,通过使用示例输入对模型的结构进行一次评估,并记录这些输入在模型中的流动,从而捕获模型的结构。这适用于有限使用控制流的模型。
    第二种方法是在模型中添加 显式批注 ,以告知Torch Script编译器可以根据Torch Script语言施加的约束直接解析和编译模型代码。

    关于如何得到Torch脚本这里就不过多叙述了,想了解的可以参考以下资料:
    在C++ 中加载 TorchScript 模型
    官方TorchScript文档
    这里放两个我用于测试的代码,第一个用于只用libtorch库的简单测试,输入为随机的向量。最终在工作目录中生成resnet18.pt文件。

    import torch
    from torchvision.models import resnet18
    model =resnet18()
    example = torch.rand(1, 3, 224, 224)
    traced_script_module = torch.jit.trace(model, example)
    
    traced_script_module.save("resnet18.pt")
    
    

    第二个是用于libtorch+OpenCV库测试,之后需要在C++中用OpenCV读取输入图像。采用torchvision.models中的Resnet50网络模型,实现图像的分类,分类结果说明参考: ImageNet图像库1000个类别名称(中文注释不断更新) 。最终生成resnet50.pt于工作目录中。

    import torch
    import torchvision.models as models
    from PIL import Image
    import numpy as np
    
    image = Image.open("E:/HM_DL/torch_test/torch_py/test1.jpg") 
    image = image.resize((224, 224),Image.ANTIALIAS)
    image = np.asarray(image)
    image = image / 255
    image = torch.Tensor(image).unsqueeze_(dim=0)
    image = image.permute((0, 3, 1, 2)).float()
    
    model = models.resnet50(pretrained=True)
    model = model.eval()
    resnet = torch.jit.trace(model, torch.rand(1,3,224,224))
    # output=resnet(torch.ones(1,3,224,224))
    output = resnet(image)
    max_index = torch.max(output, 1)[1].item()
    print(max_index) # ImageNet1000类的类别序
    
    resnet.save('resnet50.pt')
    

    最终,通过将脚本模块序列化为文件,得到模型的.pt文件,这个文件就将作为C++的输入,用于实现在C++中部署Pytorch。

    2、配置步骤

    利用VS在C++中部署Pytorch模型的配置方法大致有两种: 基于CMake自动配置 , 手动在VS中配置 

    (1)CMake配置

    以我自己为例,首先在E:\torch_test下创建名为Example的文件夹,然后在该文件夹下分别创建C++测试代码(example-app.cpp)和CMakeLists.txt,以及一个名为build的文件夹。
    在这里插入图片描述
    example-app.cpp示例:
    配合第一个Python程序,测试libtorch库是否可用。

    #include <torch/script.h>  // One-stop header.
    #include <iostream>
    #include <memory>
    
    int main() {
      // Deserialize the ScriptModule from a file using torch::jit::load().
      //std::shared_ptr<torch::jit::script::Module> module =
      //          torch::jit::load("E:/HM_DL/torch_test/traced_resnet_model.pt");
    
      using torch::jit::script::Module;
      Module module =
          torch::jit::load("E:/HM_DL/torch_test/traced_resnet_model.pt");
    
      std::cout << "ok\n";
      // Create a vector of inputs.
      std::vector<torch::jit::IValue> inputs;
      inputs.push_back(torch::ones({1, 3, 224, 224}));
    
      // Execute the model and turn its output into a tensor.
      at::Tensor output = module.forward(inputs).toTensor();
    
      std::cout << output.slice(/*dim=*/1, /*start=*/0, /*end=*/5) << '\n';
      while (1)
        ;
    }
    

    配合第二个Python程序,同时测试libtorch库和OpenCV库。

    #include <torch/script.h>
    #include <torch/torch.h>
    #include <iostream>
    #include <opencv2/core/core.hpp>
    #include <opencv2/highgui.hpp>
    #include <opencv2/opencv.hpp>
    #include <vector>
    
    void TorchTest() {
      torch::jit::script::Module module =
          torch::jit::load("E:/HM_DL/torch_test/torch_py/resnet.pt");
    
      std::cout << "Load model successful!" << std::endl;
      std::vector<torch::jit::IValue> inputs;
      inputs.push_back(torch::zeros({1, 3, 224, 224}));
      at::Tensor output = module.forward(inputs).toTensor();
      auto max_result = output.max(1, true);
      auto max_index = std::get<1>(max_result).item<float>();
      std::cout << max_index << std::endl;
    }
    
    void Classfier(cv::Mat &image) {
      torch::Tensor img_tensor = torch::from_blob(
          image.data, {1, image.rows, image.cols, 3}, torch::kByte);
      img_tensor = img_tensor.permute({0, 3, 1, 2});
      img_tensor = img_tensor.toType(torch::kFloat);
      img_tensor = img_tensor.div(255);
      torch::jit::script::Module module =
          torch::jit::load("E:/HM_DL/torch_test/torch_py/resnet.pt");
      torch::Tensor output = module.forward({img_tensor}).toTensor();
      auto max_result = output.max(1, true);
      auto max_index = std::get<1>(max_result).item<float>();
      std::cout << max_index << std::endl;
    }
    
    int main() {
      //    TorchTest();
      cv::Mat image = cv::imread("E:/HM_DL/torch_test/torch_py/test1.jpg");
      cv::resize(image, image, cv::Size(224, 224));
      cv::imshow("image", image);
      cv::waitKey(0);
      std::cout << image.rows << " " << image.cols << " " << image.channels()
                << std::endl;
      Classfier(image);
      return 0;
    }
    

    CMakeLists.txt示例:

    cmake_minimum_required(VERSION 3.12 FATAL_ERROR)
    project(example-app)
    
    find_package(Torch REQUIRED)
    find_package(OpenCV REQUIRED)
    
    if(NOT Torch_FOUND)
        message(FATAL_ERROR "Pytorch Not Found!")
    endif(NOT Torch_FOUND)
    
    message(STATUS "Pytorch status:")
    message(STATUS "    libraries: ${TORCH_LIBRARIES}")
    
    message(STATUS "OpenCV library status:")
    message(STATUS "    version: ${OpenCV_VERSION}")
    message(STATUS "    libraries: ${OpenCV_LIBS}")
    message(STATUS "    include path: ${OpenCV_INCLUDE_DIRS}")
    
    
    add_executable(example-app example-app.cpp)
    target_link_libraries(example-app ${TORCH_LIBRARIES} ${OpenCV_LIBS})
    set_property(TARGET example-app PROPERTY CXX_STANDARD 11)
    

    然后打开cmd终端,进入build文件夹,输入:

    cmake -DCMAKE_PREFIX_PATH=D:\Opencv\opencv\build\x64\vc14\lib;D:\Code_Lib\libtorch -G "Visual Studio 15 Win64" ..
    

    其中,-DCMAKE_PREFIX_PATH后要写你下载的libtorch库的绝对路径和opencv库下\build\x64\vc14\lib的绝对路径。"Visual Studio 15 Win64"表示用VS2017 x64编译。另外注意,一定不要忘了最后的 .. ,这表示采用上一级目录下的cmake文件,否则会报错说build下没找到cmake文件。

    运行成功的话会生成解决方案,选择合适的编译方式,生成可执行文件,然后运行。如有报错,参考我的 C++部署Pytorch(Libtorch)出现问题、错误汇总

    (2)手动在VS配置

    除了采用CMake的方式,也可以直接在一个已建项目里通过配置环境属性来将项目连接到libtorch库。
    下面以一个新建空项目为例,展示一下具体步骤。

  • 首先用VS新建一个空项目。
  • 在解决方案资源管理器》源文件下添加一个新的cpp文件,将上述的测试代码复制进去。
  • 接下来开始配置属性,进入属性管理器》Debug | x64 》,右键点击Microsoft.Cpp.x64.user,选择“添加新项目属性表”
    在这里插入图片描述
    名称按自己喜好和功能来定,保存在合适的目录下。这样可以为libtorch和opencv建立专门的属性表,方便之后管理和使用。
  • 右键建立的属性表,选择属性。开始配置libtorch属性表。
  • 在 C/C++=>附加包含目录 中添加libtorch库的包含头文件路径:
  • 在 链接器=>常规=>附加库目录 中添加libtorch库的lib库路径:
  • 在 链接器=>输入=>附加依赖项 中添加需要的lib文件,如果不放心,可以把libtorch\lib目录下的所有lib文件都写进去。
    举例:
  • OpenCV的配置参考 VS2017配置opencv教程(超详细!!!)
  • 回到解决方案资源管理器,右键点击建立的项目,进入“属性”。
    在这里插入图片描述
  • 在 调试=>环境 里添加libtorch动态库的路径
PATH=D:\Code_Lib\libtorch\lib;%PATH%

在这里插入图片描述
11. 将 C/C++ => 语言 => 符合模式,改为否;C/C++ => 常规=> SDL检查,改为否。

至此,在C++中部署Libtorch完成。可以通过运行测试程序进行测试。

3、踩坑汇总

如果过程中有踩坑的可以参考我的踩坑总结:
C++部署Pytorch(Libtorch)出现问题、错误汇总

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值