系统环境

  • Ubuntu 18.04
  • CUDA 10.1
  • cuDNN 7.6.5

获取LibTorch

官网下载LibTorch的GPU版本二进制包。注意版本。
image.png
我之前PyTorch用的是1.4版本,因此LibTorch保持同版本,修改下载地址如下:
https://download.pytorch.org/libtorch/cu101/libtorch-cxx11-abi-shared-with-deps-1.4.0.zip

百度云下载地址,有cpu后缀的是CPU版本的,没有的是GPU版本的。
链接: https://pan.baidu.com/s/1mSHh66CIzO6hzVE4-2Ytkw 密码: cb24

解压后即可使用。

CMakeLists.txt编写

  1. cmake_minimum_required(VERSION 3.7)
  2. project(deploy)
  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. set(Torch_DIR /home/luzhan/软件/libtorch_gpu/share/cmake/Torch)
  8. set(CUDA_TOOLKIT_ROOT_DIR /usr/local/cuda)
  9. # 自动查找包
  10. find_package(Torch REQUIRED)
  11. find_package(OpenCV 3.4.3 REQUIRED)
  12. # 添加源程序
  13. add_executable(deploy
  14. main.cpp
  15. )
  16. # 添加头文件
  17. include_directories(${OpenCV_INCLUDE_DIRS} ./include)
  18. # 加入库文件位置
  19. target_link_libraries(deploy
  20. ${OpenCV_LIBS}
  21. -pthread
  22. -lMVSDK
  23. /lib/libMVSDK.so
  24. )
  25. target_link_libraries(deploy
  26. ${TORCH_LIBRARIES}
  27. )

主程序代码

  1. /**
  2. * @author starrysky
  3. * @date 2020/08/16
  4. * @version 1.0
  5. * @details LibTorch调用PyTorch已经训练好的模型, 对传入的OpenCV的灰度图进行分类
  6. */
  7. #include <torch/script.h>
  8. #include <torch/torch.h>
  9. #include <vector>
  10. #include <opencv2/opencv.hpp>
  11. #include "opencv2/imgcodecs.hpp"
  12. #include "opencv2/imgproc.hpp"
  13. #include <iostream>
  14. #include <opencv2/tracking.hpp>
  15. class DigitalRecognition {
  16. private:
  17. torch::jit::script::Module module;
  18. torch::Device device;
  19. const int IMAGE_COLS = 28;
  20. const int IMAGE_ROWS = 28;
  21. public:
  22. /**
  23. * 默认使用CPU,可通过标志位开启使用GPU
  24. * @param use_cuda 是否使用GPU
  25. * @param model_path 模型文件路径
  26. */
  27. explicit DigitalRecognition(bool use_cuda = false,
  28. const std::string &model_path = "../model/model.pt") : device(torch::kCPU) {
  29. if ((use_cuda) && (torch::cuda::is_available())) {
  30. std::cout << "CUDA is available! Training on GPU." << std::endl;
  31. device = torch::kCUDA;
  32. }
  33. module = torch::jit::load(model_path, device);
  34. }
  35. /**
  36. * 单张图片分类器
  37. * @param img 图片,cv::Mat类型
  38. * @return 分类结果
  39. */
  40. int matToDigital(cv::Mat &img) {
  41. // 正则化
  42. img.convertTo(img, CV_32FC1, 1.0f / 255.0f);
  43. // 模型用的是 28*28 的单通道灰度图
  44. cv::resize(img, img, cv::Size(IMAGE_COLS, IMAGE_ROWS));
  45. // 将 OpenCV 的 Mat 转换为 Tensor, 注意两者的数据格式
  46. // OpenCV: H*W*C 高度, 宽度, 通道数
  47. auto input_tensor = torch::from_blob(img.data, {1, IMAGE_COLS, IMAGE_ROWS, 1});
  48. // Tensor: N*C*H*W 数量, 通道数, 高度, 宽度
  49. // 数字表示顺序
  50. input_tensor = input_tensor.permute({0, 3, 1, 2}).to(device);
  51. // 添加数据
  52. std::vector<torch::jit::IValue> inputs;
  53. inputs.emplace_back(input_tensor);
  54. // 模型计算
  55. at::Tensor output = module.forward(inputs).toTensor();
  56. std::cout << output.slice(/*dim=*/1, /*start=*/0, /*end=*/7) << '\n';
  57. // 输出分类的结果
  58. int ans = output.argmax(1).item().toInt();
  59. std::cout << "当前机器人编号: " << ans << std::endl;
  60. return ans;
  61. }
  62. };
  63. int main() {
  64. DigitalRecognition digitalRecognition;
  65. cv::Mat img = cv::imread("../image/1.jpg", CV_8UC1);
  66. digitalRecognition.matToDigital(img);
  67. return 0;
  68. }