<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
前天由於某些原因需要利用C++呼叫PyTorch,於是接觸到了LibTorch,配了兩天最終有了一定的效果,於是記錄一下。
去PyTorch官網下載LibTorch包,選擇對應的版本,這裡我選擇Stable(1.6.0),Windows,LibTorch,C++/JAVA,10.2,然後我選擇release版本下載,如下圖
下載完後先不用管它,之後再用
我先建立了一個python檔案,載入resnet50預訓練模型,用來生成模型檔案,程式碼如下
import torch import torchvision.models as models from PIL import Image import numpy as np from torchvision import transforms model_resnet = models.resnet50(pretrained=True).cuda() # model_resnet.load_state_dict(torch.load("resnet_Epoch_4_Top1_99.75845336914062.pkl")) model_resnet.eval() # 自己選擇任意一張圖片,並將它的路徑寫在open方法裡,用來讀取影象,我這裡路徑就是‘111.jpg'了 image = Image.open("111.jpg").convert('RGB') tf = transforms.Compose([ transforms.Resize((224, 224)), transforms.ToTensor(), # transforms.Normalize(mean=[0.5]*3, std=[0.5]*3) ]) img = tf(image) img = img.unsqueeze(dim=0) print(img.shape) input = torch.rand(1, 3, 224, 224).cuda() traced_script_module_resnet = torch.jit.trace(model_resnet, input) output = traced_script_module_resnet(img.cuda()) print(output.shape) pred = torch.argmax(output, dim=1) print(pred) traced_script_module_resnet.save("model_resnet_jit_cuda.pt")
最後可以生成一個model_resnet_jit_cuda.pt檔案,產生的輸出如下所示
第一行是我們讀取影象的shape,我們讀取圖片之後經過各種resize,增加維度,把圖片資料的shape修改成模型接受的格式,可以看到預測的結果是921,之後我們將用到生成的model_resnet_jit_cuda.pt檔案。
我在這個python檔案路徑下建立了這個vs工程Project1
建立完成之後我們開啟Project1資料夾,裡面內容如下
現在建立VS工程先告一段落,開始進行工程環境設定。把之前下載的LibTorch,解壓到當前目錄,解壓後會出現一個libtorch的資料夾,資料夾目錄裡的內容為
這裡將我框選的資料夾路徑設定到工程屬性當中,開啟剛才新建的VS工程,選擇專案為relaese的×64版本
然後點選專案->Project1屬性,彈出屬性頁
在屬性頁同樣注意是release的×64平臺,點選VC++目錄,在包含目錄下載入我之前框出來的include資料夾路徑,在庫目錄下載入框出來的lib資料夾路徑,同時,我們也要用到opencv,所以也需要在包含目錄下載入opencv的include資料夾與opencv2資料夾,在庫目錄下載入opencvbuildx64vc14lib,如下圖
然後在屬性頁的連結器->輸入,新增附加依賴項,首先先把opencv的依賴項新增了
opencv_world440.lib,(如果一直用的Debug模式,就新增opencv_world440d.lib),然後將libtorch/lib裡所有字尾為.lib的檔案全新增進來,開啟這個資料夾
全都寫進去,再點選確定,如下圖所示
然後點選連結器->命令列,加上/INCLUDE:?warp_size@cuda@at@@YAHXZ 這一句,加上這一句是因為我們要用cuda版本的,如果是cpu版本可以不加。
最後點選C/C++ ->常規的SDL檢查,設定為否
點選C/C++ ->語言的符合模式,設定為否
到此我們的設定就全部結束了!最後!複製libtorch/lib資料夾下所有檔案,貼上到工程資料夾Project1/×64/release資料夾裡(點選此處的Project1資料夾可以發現裡面也有一個×64/release,之前我也糾結是放在哪,然後我都試了一下,發現這個裡面是可以不放的)
然後我執行VS工程下一個空的main檔案,沒有報錯,設定大致是沒問題的,最後新增完整程式碼,如下
#include <torch/script.h> // One-stop header. #include <opencv2/opencv.hpp> #include <iostream> #include <memory> //https://pytorch.org/tutorials/advanced/cpp_export.html std::string image_path = "../../111.jpg"; int main(int argc, const char* argv[]) { // Deserialize the ScriptModule from a file using torch::jit::load(). //std::shared_ptr<torch::jit::script::Module> module = torch::jit::load("../../model_resnet_jit.pt"); using torch::jit::script::Module; Module module = torch::jit::load("../../model_resnet_jit_cuda.pt"); module.to(at::kCUDA); //assert(module != nullptr); //std::cout << "okn"; //輸入影象 auto image = cv::imread(image_path, cv::ImreadModes::IMREAD_COLOR); cv::cvtColor(image, image, cv::COLOR_BGR2RGB); cv::Mat image_transfomed; cv::resize(image, image_transfomed, cv::Size(224, 224)); // 轉換為Tensor torch::Tensor tensor_image = torch::from_blob(image_transfomed.data, { image_transfomed.rows, image_transfomed.cols,3 }, torch::kByte); tensor_image = tensor_image.permute({ 2,0,1 }); tensor_image = tensor_image.toType(torch::kFloat); tensor_image = tensor_image.div(255); tensor_image = tensor_image.unsqueeze(0); tensor_image = tensor_image.to(at::kCUDA); // 網路前向計算 at::Tensor output = module.forward({ tensor_image }).toTensor(); //std::cout << "output:" << output << std::endl; auto prediction = output.argmax(1); std::cout << "prediction:" << prediction << std::endl; int maxk = 3; auto top3 = std::get<1>(output.topk(maxk, 1, true, true)); std::cout << "top3: " << top3 << 'n'; std::vector<int> res; for (auto i = 0; i < maxk; i++) { res.push_back(top3[0][i].item().toInt()); } for (auto i : res) { std::cout << i << " "; } std::cout << "n"; system("pause"); }
得到最終輸出為921,可以看到和之前的python檔案下輸出一致,這裡還輸出了它的top前三,分別是921,787,490。
注意到,我的這兩個輸出相同的前提條件是:
1、確定載入的是由對應python檔案生成的模型!
2、輸入的圖片是同一張!並且在python下和C++下進行了同樣的轉換,這裡我在python下,將它進行了RGB模型的轉換,resize(224, 224),並且將它的每一個元素值除以255.0,轉換到0~1之間(ToTensor()方法),最後維度轉換為1, 3, 224, 224,在C++中同樣需要將BGR模型轉化為RGB模型,進行影象縮放至224,224,並且將畫素值除以255,將型別轉化為float型別,最後維度同樣轉換為1,3,224,224,再進行網路前向計算。
以上為個人經驗,希望能給大家一個參考,也希望大家多多支援it145.com。
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45