如何在C++中使用DirectML提供程序加载图像作为onnx模型的输入[duplicate]

k0pti3hp  于 2023-03-20  发布在  其他
关注(0)|答案(1)|浏览(263)

此问题在此处已有答案

How to use ONNX model in C++ code on Linux?(1个答案)
3天前关闭。
这篇文章是编辑和提交审查2天前。
我一直在尝试了解如何使用Visual Studio在C++中加载onnx模型并向其提供输入,看看如何以及什么是onnx模型的输出,但我没有找到任何方法或如何将输入加载到onnx模型
这是最新的代码:

#include<GLFW/glfw3.h>
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

#include <iostream>
#include <onnxruntime_cxx_api.h>
#include<dml_provider_factory.h>
#include <vector>

std::vector<float> load_image_and_preprocess(std::string& filename, int& x, int& y) 
{
    std::cout << x<<y<<filename<<std::endl;
    x = 0;
    y = 0;
    std::vector<float> ret;
    int n;
    unsigned char* data = stbi_load(filename.c_str(), &x, &y, &n, 3);
    ret.resize(x * y * 3);
    float* rptr = &ret[0 * x * y], * gptr = &ret[1 * x * y], * bptr = &ret[2 * x * y];
    for (int i = 0; i < x * y; i++) {
        *rptr++ = (float(data[3 * i + 0]) / 255 - 0.485) / 0.229;
        *gptr++ = (float(data[3 * i + 1]) / 255 - 0.456) / 0.224;
        *bptr++ = (float(data[3 * i + 2]) / 255 - 0.406) / 0.225;
    }
    stbi_image_free(data);
    return ret;
}

 
int main()
{ 
    const std::string model_s = "C:/Downloads/resnet18-v1-7.tar/resnet18-v1-7/resnet18-v1-7.onnx";
    std::basic_string<ORTCHAR_T> model = std::basic_string<ORTCHAR_T>(model_s.begin(), model_s.end());
    std::cout << model.c_str();
    // onnxruntime setup
    Ort::Env env(ORT_LOGGING_LEVEL_WARNING, "batch-model-explorer");
    Ort::SessionOptions session_options;
    OrtSessionOptionsAppendExecutionProvider_DML(session_options, 0);
    Ort::Session session = Ort::Session(env, model.c_str(), session_options);

    std::cout << "number of model input:" << session.GetInputCount() << std::endl;
    std::cout << "number of model Output:" << session.GetOutputCount() << std::endl;

    Ort::AllocatorWithDefaultOptions allocator;

    auto val = session.GetInputTypeInfo(0).GetTensorTypeAndShapeInfo().GetShape().size();
    auto val1 = session.GetOutputTypeInfo(0).GetTensorTypeAndShapeInfo().GetShape().size();
    std::cout << "number of model input:" << val << std::endl;
    std::cout << "number of model Output:" << val1 << std::endl;

    auto input_names = session.GetInputNameAllocated(0, allocator);
    auto output_names = session.GetOutputNameAllocated(0, allocator);
    std::cout << "Val:" << input_names << std::endl;
    std::cout << "Val:" << output_names << std::endl;

    std::vector<std::vector<int64_t>> input_node_dims(1);
    int i = 0;
    input_node_dims[0] = session.GetInputTypeInfo(0).GetTensorTypeAndShapeInfo().GetShape();

    for (int j = 0; j < input_node_dims[i].size(); j++)
        printf("Input %d : dim %d=%jd\n", i, j, input_node_dims[i][j]);
    
    int x = 0, y = 0;
    std::string sVal = "C:/Desktop/Image.png";
    std::vector<float> vecVal = load_image_and_preprocess(sVal, x, y);
    std::cout << vecVal.size() << std::endl;
    for (int j = 0; j < vecVal.size(); j++)
        std::cout << vecVal[j] << std::endl;
    
    constexpr size_t input_tensor_size = 224 * 224 * 3;
    auto memory_info = Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault);
    
    auto input_tensor = Ort::Value::CreateTensor<float>(memory_info, vecVal.data(), input_tensor_size,input_node_dims.data(), 4);
    return 0;
}

请帮助我了解如何加载和提供输入到onnx模型

nkoocmlb

nkoocmlb1#

该模型随附的文档对输入预期非常明确:

输入

所有预先训练的模型都期望输入图像以相同的方式归一化,即形状的3通道RGB图像的小批量(N x 3 x H x W),其中N是批量大小,H和W期望至少为224。使用jpeg图像进行推断。

预处理

图像必须加载到[0,1]的范围内,然后使用均值= [0.485,0.456,0.406]和标准差= [0.229,0.224,0.225]进行归一化。
你可以使用stbi_image从磁盘加载你的文件:

#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

std::vector<float> load_image_and_preprocess(const std::string& filename, int& x, int& y) {
  std::vector<float> ret;
  int n;
  unsigned char *data = stbi_load(filename.c_str(), &x, &y, &n, 3);
  ret.resize(x * y * 3);
  float *rptr = &ret[0 * x * y], *gptr = &ret[1 * x * y], *bptr = &ret[2 * x * y];
  for (int i = 0; i < x * y; i++) {
    *rptr++ = (float(data[3 * i + 0])/255 - 0.485) / 0.229;
    *gptr++ = (float(data[3 * i + 1])/255 - 0.456) / 0.224;
    *bptr++ = (float(data[3 * i + 2])/255 - 0.406) / 0.225;
  }
  stbi_image_free(data);
  return ret;
}

这段代码按照您的模型所期望的那样分离了红色、绿色和蓝色通道。这会产生一个预处理的vector<float>,您可以将其传递给Ort::Value::CreateTensor。从那里开始,您可能应该从squeezenet example中复制

相关问题