如何使用c++使用onnx和opencv制作超分辨率图像?

问题描述 投票:0回答:1

我的超分辨率 ios/macos 应用程序有

animesr.onnx
,所以我需要将 python 代码转换为 C++ 代码。这些是我的Python代码:

session = onnxruntime.InferenceSession('animesr.onnx')

img = cv2.imread('imgs/naruto.jpg')
ori_h, ori_w, _ = img.shape
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img = cv2.resize(img, (512,512))
img = (np.array(img) / 255.0).astype(np.float32)
img = np.transpose(img, (2, 0, 1))
img = np.expand_dims(img, 0)

input_name = session.get_inputs()[0].name
output_name = session.get_outputs()[0].name

input_feed = {input_name: img}
output = session.run([output_name], input_feed)

output = output[0].clip(0, 1) * 255
output = output.astype(np.uint8)
output = np.squeeze(output)
output = np.transpose(output, (1, 2, 0))
output = cv2.cvtColor(output, cv2.COLOR_RGB2BGR)
output = cv2.resize(output, (ori_w*4, ori_h*4))
cv2.imwrite('naruto_animesr.jpg', output)

工作正常,结果是这样的(左是之前,右是之后) naruto_sr

这是我的 C++ 代码:

Ort::Session session(env, ORT_TSTR(modelPath), sessionOptions);

cv::Mat inputImage = cv::imread(imagePath, cv::IMREAD_COLOR);
// cv::Mat blob = cv::dnn::blobFromImage(inputImage, 1.0/255, cv::Size(512,512), cv::Scalar(), true);
cv::Mat resizedImage;
cv::resize(inputImage, resizedImage, cv::Size(512,512));
cv::Mat floatImage;
resizedImage.convertTo(floatImage, CV_32FC3, 1.0/255.0);

Ort::MemoryInfo memoryInfo = Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault);
std::vector<int64_t> inputShape = {1, 3, 512, 512};
  
Ort::Value inputTensor = Ort::Value::CreateTensor<float>(memoryInfo, (float*) floatImage.data, 3*512*512, inputShape.data(), inputShape.size());

std::vector<const char*> inputNames = {"input"};
std::vector<const char*> outputNames = {"output"};

std::vector<Ort::Value> outputTensor = session.Run(Ort::RunOptions{}, inputNames.data(), &inputTensor, 1, outputNames.data(), outputNames.size());

Ort::TensorTypeAndShapeInfo outputInfo = outputTensor[0].GetTensorTypeAndShapeInfo();
int channels = outputInfo.GetShape()[1]; // 3
int height = outputInfo.GetShape()[2]; // 2048
int width = outputInfo.GetShape()[3]; // 2048
  
const float* outputData = outputTensor[0].GetTensorMutableData<float>();
  
cv::Mat outputImage(height, width, CV_32FC(channels), const_cast<float*>(outputData));
cv::Mat uint8Image;
outputImage.convertTo(uint8Image, CV_8UC3, 255);
cv::Mat bgrOutput;
cv::cvtColor(uint8Image, bgrOutput, cv::COLOR_RGB2BGR);
cv::imwrite(outputPath, bgrOutput);

这就是结果 naruto_fail1 这是 cv::ddn::blobFromImage() 的结果 naruto_fail2

两者都是糟糕的结果,与我的Python结果不同。

我认为问题出在运行模型之前将图像作为输入进行预处理并将输出处理为CV图像,我不擅长矩阵运算,如变换、转置、重塑等。

你能帮我提供正确的opencv c++处理图像代码吗?

python c++ opencv machine-learning deep-learning
1个回答
0
投票

我已经审查了您的 C++ 代码。问题在于您的代码没有利用 cv::split 来分离张量数据的输入图像的通道。有必要分割通道并使用足够大的缓冲区来将数据重新排列为以下格式:[r0, r1, r2, ..., rn], [g0, g1, g2, ..., gn ], [b0, b1, b2, ..., bn]。此外,对于输出张量数据,您应该应用相反的过程并使用 cv::merge 将通道重新组装回 RGB 图像。

© www.soinside.com 2019 - 2024. All rights reserved.