使用CV::imread() 读取图片时,如何保证python中torch模型输出的数据和libtorch输出的数据一模一样?
请大家关注,相互交流哈~
网上各种教程,全不说关键所在。吐血三天整出了代码核心!!!
怀着鸡冻的心情写下这个博客,做个记录。
网上有出多使用这种torch.ones(1,3,64,64)来生成一个张量作为模型的输入数据,比较python和c++平台的输出结果是否一致。
这个也是有必要的,但这只是第一步。因为我们一般输入的数据不可能都是这样生成,往往都是读取图片,然后经过一系列处理才送进
module。在这个过程就会出现各种问题。这就是博主今天要总结的东西:
trance_module = torch.jit.load( os.path.join(PATH,"scriptmodule1.pt") )
output2 = traced_script_module(torch.ones(1,3,64,64).to((device))) #image
保证python和C++两个平台数据的一致性有两个关键:
-
图片数据的预处理必须一致 如果输入数据都不一样,那还搞啥子! 所以,大家可以看到我的图片,读取图片得到 img
之后,我没有使用torch的transform来做处理。这是因为c++的libtorch在读取自己的数据集时我不会使用transform库(这里就是我的缺陷了,弄了很久还是不会跟python一样,调用torch自带的transform库来处理图片,有人知道的欢迎留言告诉我一样,谢谢啦~)
大家看图1中代码,我使用的是最原始的方法,整体处以255.0(线性归一化)。
之所这样是因为c++也能这样处理,而不用费力使用tranform。
-
cv::imread(“img”)。之后,有个关键:
这里的核心就在与 torch::from_blob( ),这个函数!!!不小心的话你会遇到跟博主一样的问题,折腾了所有方案就是搞不定,困恼好几天!!明明所以操作和处理一致,就是得不到一致的输出,而且,c++ libtorch的输出还特别大,都是 1.0e18级别的。 这里的关键就是(看代码):torch::kByte。
具体原因还来得及了解,欢迎大家交流~
torch::Tensor imgtransform;
imgtransform = torch::from_blob(img.data,{1,img.rows, img.cols,3 }, torch::kByte); //
imgtransform = imgtransform.permute({ 0,3,1,2 });
imgtransform = imgtransform.to(torch::kFloat);
imgtransform = imgtransform.div(255.0);
上图就是图1了,这个博客网站我还不是很熟,不知道为什么不能加图标题,不过在做libtorch的朋友,一定很熟悉这个界面哈哈哈哈~
直接上全部代码:
python的。
imgPath = "E:/00_ComponentData/rule/test/01_Crankshaft"
img = cv.imread( os.path.join(imgPath,"063.jpg") ) # ,cv.COLOR_BAYER_BG2RGB
img = cv.cvtColor(img, cv.COLOR_BGR2RGB)
img = cv.resize(img,(64,64))
img = torch.from_numpy(img)
img = img.permute(2,0,1)
img = img.to(torch.float)
img = img.div(255.0)
image = torch.unsqueeze(img,0).to(device)
print((img_input.shape),' --- ',image.shape)
inputs = (torch.rand(1, 3, 224, 224).to(device))
trance_module = torch.jit.load( os.path.join(PATH,"scriptmodule1.pt") )
output2 = trance_module (inputs).to((device)))
print(output2)
C++的代码:
// vc_torch_test02.cpp: 定义应用程序的入口点。
//
//#include "vc_torch_test02.h"
#include <iostream>
#include<string>
#include<memory>
#include<stdlib.h>
#include<assert.h>
//#include"torchNet.h"
#include <torch/torch.h>
#include <torch/script.h>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/core.hpp>
#include<opencv2/opencv.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace std;
using namespace cv;
using namespace torch;
//
int main()
{
cout << "Hello World!\n";
torch::Tensor img_tensor = torch::rand({ 3,64, 64 });
cout << img_tensor[1][0][0] << endl;
cv::Mat img = cv::imread("E:/00_ComponentData/rule/test/01_Crankshaft/063.jpg");
if (img.empty() || !img.data)
std::cout << "read image fail" << std::endl;
cv::cvtColor(img, img, cv::COLOR_BGR2RGB);
cv::resize(img, img, cv::Size(64, 64),0,0);
cv::imshow("ds", img);
//cv::waitKey(2000);
string modelpath = "D:/Python/00-work/01-torch-test/trained_models/";
string modelname = "scriptmodule1.pt";
torch::jit::Module model = torch::jit::load(modelpath + modelname);
model.eval();
model.to(at::kCUDA);
//cv::normalize(img, img, 1, 1.0);
torch::Tensor imgtransform;
imgtransform = torch::from_blob(img.data,{1,img.rows, img.cols,3 }, torch::kByte); //
imgtransform = imgtransform.permute({ 0,3,1,2 });
imgtransform = imgtransform.to(torch::kFloat);
imgtransform = imgtransform.div(255.0);
//imgtransform = imgtransform.unsqueeze(0); //
//imgtransform = imgtransform.norm(0.5);
imgtransform = imgtransform.to(torch::kCUDA);
auto output = model.forward({ imgtransform }).toTensor();
cout << output.slice(/*dim*/1, /*start*/0, /*end*/6) << endl;
cv::waitKey(2000);
return 0;
}