前言

模型转换思路通常为:

  • Pytorch -> ONNX -> TensorRT
  • Pytorch -> ONNX -> TVM
  • Pytorch -> 转换工具 -> caffe
  • Pytorch -> torchscript(C++版本Torch)
    由于我的模型存在caffe不包含的层, 本文使用第4中方法

1. pytorch模型转化为libtorch的torchscript模型 (.pth -> .pt)

首先, 在python中, 把模型转化成.pt文件

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。

Pytorch官方提供的C++API名为libtorch,详细查看:
- LIBRARY API
- USING THE PYTORCH C++ FRONTEND

pytorch模型, 使用C++调用 随笔 第1张

import torch

# An instance of your model.
from my_infer import BaseLine

model = BaseLine().model.cpu().eval()

# An example input you would normally provide to your model's forward() method.
example = torch.rand(1, 3, 256 , 128)

# Use torch.jit.trace to generate a torch.jit.ScriptModule via tracing.
traced_script_module = torch.jit.trace(model, example)
traced_script_module.save("demo/model.pt")

2. 使用libtorch调用torchscript模型

此处有一个大坑, opencv和torch可以单独使用, 但是同时使用的时候, cv::imread提示未定义的应用. 所以使用了opencv2的图片读取方式, 然后再转成cv::Mat.

#include <iostream>                                                                                                
#include "torch/script.h"
#include "torch/torch.h"
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include <vector>

int main()
{
    //加载pytorch模型
    std::shared_ptr<torch::jit::script::Module> module = torch::jit::load("/home/zhuoshi/ZSZT/Geoffrey/opencvTest/m
    assert(module != nullptr);

    // 创建一个Tensor
    //std::vector<torch::jit::IValue> inputs;
    //inputs.emplace_back(torch::ones({1, 3, 256, 128}));
    //测试前向
    //at::Tensor output = module->forward(inputs).toTensor();
    //std::cout << output;

    // 转换为int8类型
    //vector<int16_t> feature(2048);
    //for (int i = 0;i<128;i++)
    //{
    // 转化成Float
    //int temp = output[0][i].item().toInt();
    //    if (temp != 0){
    //        temp = 1;
    //    }
    //    feature[i] = temp;
    //}
    //std::cout << feature;

    //读取图片
    IplImage* pmg = cvLoadImage("/home/zhuoshi/ZSZT/Geoffrey/opencvTest/test.jpg");
    cv::Mat image(pmg, true);
    //cv::Mat imageRGB = cv::cvtColor(image, imageRGB, cv::COLOR_BGR2RGB);
    cv::cvtColor(image, image, CV_BGR2RGB);

    //IplImage转换成Tensor
    cv::Mat img_float;
    image.convertTo(img_float, CV_32F, 1.0 / 255);
    cv::resize(img_float, img_float, cv::Size(256, 128));
    torch::Tensor tensor_image = torch::from_blob(img_float.data, {1, 3, 256, 128}, torch::kFloat32);

    //前向
    std::vector<torch::jit::IValue> input;
    input.emplace_back(tensor_image);
    at::Tensor output_image = module->forward(input).toTensor();
    //std::cout << output_image;

    //Tensor 转 array
    std::vector<float> feature(2048);
    for (int i=0; i<2048; i++){
    //    feature[i] = output_image[i]
        std::cout << output_image[0][i].item().toFloat();
    }
    return 0;
}  

对应的CMakeLists.txt内容:

cmake_minimum_required(VERSION 2.8)                                                                                

project(opencv_example_project)
SET(CMAKE_C_COMPILER g++)
add_definitions(--std=c++11)

# 指定libTorch位置
set(Torch_DIR /home/zhuoshi/ZSZT/Geoffrey/opencvTest/libtorch/share/cmake/Torch)
find_package(Torch REQUIRED)

find_package(OpenCV REQUIRED)

message(STATUS "OpenCV library status:")
message(STATUS "    version: ${OpenCV_VERSION}")
message(STATUS "    libraries: ${OpenCV_LIBS}")
message(STATUS "    include path: ${OpenCV_INCLUDE_DIRS}")
message(STATUS "    torch lib : ${TORCH_LIBRARIES} ")

include_directories(${OpenCV_INCLUDE_DIRS}
                    /home/zhuoshi/ZSZT/Geoffrey/opencvTest/libtorch/include
                    /home/zhuoshi/ZSZT/Geoffrey/opencvTest/libtorch/include/torch/csrc/api/include/
                    )

add_executable(main main.cpp)
     
# Link your application with OpenCV libraries
target_link_libraries(main ${OpenCV_LIBS} ${TORCH_LIBRARIES} )

运行结果如图:
pytorch模型, 使用C++调用 随笔 第2张

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄