1. 开发环境

  • Ubuntu 18.04
  • gcc 7.5.0
  • OpenCV 3.4.3

    2. 获取LibTorch

    PyTorch官网获取。选取C++11版本,否则单独可以正常使用,但是和OpenCV联合编译会报错。

图片.png

如果官网下载不顺,可以使用下面我已经上传的压缩包。

libtorch-cxx11-abi-shared-with-deps-1.4.0+cpu.zip

解压即可。注意文件路径在CMake中会会使用到。
图片.png

3. 编写CMakeLists.txt文件

  1. cmake_minimum_required(VERSION 3.7)
  2. project(cplus_test)
  3. set(CMAKE_CXX_STANDARD 11)
  4. # 指定文件夹位置
  5. set(OPENCV_DIR /home/luzhan/软件/opencv-3.4.3)
  6. set(Torch_DIR /home/luzhan/软件/LibTorch_CPU/share/cmake/Torch)
  7. # 自动查找包
  8. find_package(Torch REQUIRED)
  9. find_package(OpenCV 3.4.3 REQUIRED)
  10. # 添加源程序
  11. add_executable(cplus_test
  12. main.cpp)
  13. # 添加头文件
  14. include_directories(${OpenCV_INCLUDE_DIRS} ./include)
  15. # 加入库文件位置
  16. target_link_libraries(cplus_test ${OpenCV_LIBS} ${TORCH_LIBRARIES})

4. C++部分编写

  1. #include <torch/script.h>
  2. #include <torch/torch.h>
  3. #include <opencv2/opencv.hpp>
  4. #include <iostream>
  5. using namespace cv;
  6. using namespace std;
  7. int main() {
  8. // 加载模型
  9. torch::jit::script::Module module = torch::jit::load("../model.pt");
  10. // 制造假数据测试
  11. std::vector<torch::jit::IValue> inputs;
  12. inputs.push_back(torch::ones({1, 1, 28, 28}));
  13. // 模型计算并输出
  14. at::Tensor output = module.forward(inputs).toTensor();
  15. std::cout << output.slice(/*dim=*/1, /*start=*/0, /*end=*/5) << '\n';
  16. return 0;
  17. }

输出结果

  1. 1.0754 -1.3711
  2. [ CPUFloatType{1,2} ]

5. 和OpenCV一起使用

  1. #include <torch/script.h>
  2. #include <torch/torch.h>
  3. #include <opencv2/opencv.hpp>
  4. #include <iostream>
  5. using namespace cv;
  6. using namespace std;
  7. int main() {
  8. torch::jit::script::Module module = torch::jit::load("../model.pt");
  9. cv::Mat img;
  10. img = cv::imread("../1.jpg", CV_8UC1);
  11. // 正则化
  12. img.convertTo(img, CV_32FC1, 1.0f / 255.0f);
  13. // 模型用的是 28*28 的单通道灰度图
  14. cv::resize(img, img, Size(28, 28));
  15. // 将 OpenCV 的 Mat 转换为 Tensor, 注意两者的数据格式
  16. // OpenCV: H*W*C 高度, 宽度, 通道数
  17. auto input_tensor = torch::from_blob(img.data, {1, img.cols, img.rows, 1});
  18. // Tensor: N*C*H*W 数量, 通道数, 高度, 宽度
  19. input_tensor = input_tensor.permute({0, 3, 1, 2});
  20. // 添加数据
  21. std::vector<torch::jit::IValue> inputs;
  22. inputs.push_back(input_tensor);
  23. // 模型计算
  24. at::Tensor output = module.forward(inputs).toTensor();
  25. std::cout << output.slice(/*dim=*/1, /*start=*/0, /*end=*/5) << '\n';
  26. // 输出分类的结果
  27. int ans = output.argmax(1).item().toInt();
  28. cout << ans;
  29. return 0;
  30. }

输出结果,最后的数字即为分类的结果,和数据集的标签对应。

  1. -3.3254 2.4606
  2. [ CPUFloatType{1,2} ]
  3. 1

6. 参考链接

https://pytorch.org/cppdocs/installing.html#minimal-example
https://www.jianshu.com/p/1034b23c703a
https://zhuanlan.zhihu.com/p/66832878
https://oldpan.me/archives/pytorch-c-libtorch-inference

7. 完整工程文件

Cplus_test.zip