模型训练 用 python 来构建模型并用数据集进行训练(略).
需要注意的是,用于训练的 python 版本的 pytorch 需要和 CPP 版本的 libtorch 版本一致!这里统一用 Stable (1.7.0)
版本.
模型保存 用 TorchScript 将训练好的模型保存为 *.pt
文件,以便通过 CPP 调用.
1 2 3 4 5 6 7 import torchfrom torchvision.models import resnet18model = resnet18() example = torch.rand(1 , 3 , 224 , 224 ) traced_script_module = torch.jit.trace(model, example) traced_script_module.save("./model/model1_resnet18.pt" )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import torchimport torchvision.models as modelsfrom PIL import Imageimport numpy as npimage = Image.open ("./images/demo.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(image) max_index = torch.max (output, 1 )[1 ].item() print (max_index) resnet.save("./model/model2_resnet50.pt" )
VS2017+libtorch 在 官网 选择 Stable (1.7.0)
+Windows
+LibTorch
+C++ / Java
+10.2
, 下载Release
版本和 Debug
版本.
Windows binaries do not support Java. Support is only available for Linux and MacOS. Download here for C++ (Release version):https://download.pytorch.org/libtorch/cu102/libtorch-win-shared-with-deps-1.7.0.zip Download here for C++ (Debug version):https://download.pytorch.org/libtorch/cu102/libtorch-win-shared-with-deps-debug-1.7.0.zip
配置 下载好 libtorch-win-shared-with-deps-1.7.0.zip
和libtorch-win-shared-with-deps-debug-1.7.0.zip
两个文件之后,分别解压到 release
和debug
两个文件夹下. 这里先仅使用 Debug
版本.
libtorch-win-shared-with-deps-debug-1.7.0.zip
压缩包解压后得到如下文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - debug - libtorch - bin - cmake - include - ... - lib - *.lib - * .pdb - *.dll - share - test - build-hash - release - ...
LIB 在 解决方案资源管理器
右击项目名 ->属性
-> 链接器
-> 常规
-> 附加库目录
: 将 lib 文件夹路径添加到这里: …libtorch\lib 在解决方案资源管理器
右击项目名 ->属性
-> 链接器
-> 输入
-> 附加依赖项
: 将 lib 文件名添加到这里:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 asmjit.lib clog.lib libprotobuf-lited.lib c10.lib cpuinfo.lib libprotocd.lib c10_cuda.lib dnnl.lib mkldnn.lib c10d.lib fbgemm.lib torch.lib caffe2_detectron_ops_gpu.lib gloo.lib torch_cpu.lib caffe2_module_test_dynamic.lib gloo_cuda.lib torch_cuda.lib caffe2_nvrtc.lib libprotobufd.lib
INCLUDE 在 解决方案资源管理器
右击项目名 ->属性
->C/C++
-> 常规
-> 附加包含目录
: 将 include 文件夹路径添加到这里: …libtorch\include …libtorch\include\torch\csrc\api\include
解决提醒 std 冲突问题 在解决方案资源管理器
右击项目名 ->属性
->C/C++
-> 常规
->SDL 检查
-> 否(/sdl-)
在 解决方案资源管理器
右击项目名 ->属性
->C/C++
-> 语言
-> 符合模式
-> 否
dll 将 libtorch\lib 文件夹下的所有 dll 文件都复制到解决方案生成的可执行文件 *.exe
文件所在路径. 此外,如果是 debug 模式,运行时会报错:找不到 vcruntime140_1d.dll
. 其实系统里一定有vcruntime140_1.dll
文件,但是没有用于调试版本的 dll 文件,可以去 <www.dll-files.com> 网站下载 : https://www.dll-files.com/vcruntime140_1d.dll.html
dll 文件可以直接放在 exe 文件相同路径下,也可以专门放在一个文件夹下,然后将这个文件夹添加到可搜索环境下: 在 解决方案资源管理器
右击项目名 ->属性
-> 调试
-> 环境
->PATH=.\dll;%PATH%
.
测试 测试 libtorch 1 2 3 4 5 6 7 #include <iostream> #include <torch/script.h> int main () { torch::Tensor t1 = torch::tensor ({ 10 ,1 ,2 }); std::cout << t1[0 ] << std::endl; system ("pause" ); }
1 2 3 4 5 6 7 8 9 10 11 12 #include <iostream> #include <torch/script.h> int main () { auto t1 = torch::tensor ({ 1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 }).reshape ({ 3 ,3 }); auto t2 = torch::tensor ({ 1 ,0 ,2 ,6 ,1 ,1 ,5 ,3 ,2 }).reshape ({ 3 ,3 }); auto t3 = t1.mul (t2); std::cout << t3 << std::endl; system ("pause" ); }
模型导入测试 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #include <torch/script.h> #include <iostream> #include <memory> int main () { using torch::jit::script::Module; Module module = torch::jit::load ("./model/model1_resnet18.pt" ); std::cout << "model load success" << std::endl; std::vector<torch::jit::IValue> inputs; inputs.push_back (torch::ones ({ 1 , 3 , 224 , 224 })); at::Tensor output = module .forward(inputs).toTensor (); std::cout << output.slice (1 , 0 , 5 ) << std::endl; return 0 ; }
模型预测测试 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 #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 ("./model/model2_resnet50.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 ("./model/model2_resnet50.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 ("./images/demo.jpg" ); cv::resize (image, image, cv::Size (224 , 224 )); cv::imshow ("image" , image); cv::waitKey (100 ); std::cout << image.rows << " " << image.cols << " " << image.channels () << std::endl; Classfier (image); return 0 ; }
Reference