使用C++解析ONNX模型。使用C++从ONNX模型中提取层、输入和输出形状

2 人关注

我想从一个onnx模型中提取输入层、输出层和它们的形状等数据。我知道有python接口可以做到这一点。我想做的是类似于这样的事情 code 但在C++中。我也粘贴了链接中的代码。我已经在Python中试过了,它对我来说是有效的。我想知道是否有C++的API来做同样的事情。

import onnx
model = onnx.load(r"model.onnx")
# The model is represented as a protobuf structure and it can be accessed
# using the standard python-for-protobuf methods
# iterate through inputs of the graph
for input in model.graph.input:
    print (input.name, end=": ")
    # get type of input tensor
    tensor_type = input.type.tensor_type
    # check if it has a shape:
    if (tensor_type.HasField("shape")):
        # iterate through dimensions of the shape:
        for d in tensor_type.shape.dim:
            # the dimension may have a definite (integer) value or a symbolic identifier or neither:
            if (d.HasField("dim_value")):
                print (d.dim_value, end=", ")  # known dimension
            elif (d.HasField("dim_param")):
                print (d.dim_param, end=", ")  # unknown dimension with symbolic name
            else:
                print ("?", end=", ")  # unknown dimension with no name
    else:
        print ("unknown rank", end="")
    print()

另外,我是C++的新手,请帮助我解决这个问题。

python
c++
onnx
onnxruntime
Hitesh Kumar
Hitesh Kumar
发布于 2021-04-28
1 个回答
binarman
binarman
发布于 2021-04-29
已采纳
0 人赞同

ONNX格式本质上是一种 protobuf 因此,它可以用protoc编译器支持的任何语言打开。

在C++的情况下

  • Take onnx proto file ( onnx repo )
  • Compile it with protoc --cpp_out=. onnx.proto3 command. It will generate onnx.proto3.pb.cc and onnx.proto3.pb.h files
  • Link protobuf library (maybe protobuf-lite), generated cpp file and following code:
  • #include <fstream>
    #include <cassert>
    #include "onnx.proto3.pb.h"
    void print_dim(const ::onnx::TensorShapeProto_Dimension &dim)
      switch (dim.value_case())
      case onnx::TensorShapeProto_Dimension::ValueCase::kDimParam:
        std::cout << dim.dim_param();
        break;
      case onnx::TensorShapeProto_Dimension::ValueCase::kDimValue:
        std::cout << dim.dim_value();
        break;
      default:
        assert(false && "should never happen");
    void print_io_info(const ::google::protobuf::RepeatedPtrField< ::onnx::ValueInfoProto > &info)
      for (auto input_data: info)
        auto shape = input_data.type().tensor_type().shape();
        std::cout << "  " << input_data.name() << ":";
        std::cout << "[";
        if (shape.dim_size() != 0)
          int size = shape.dim_size();
          for (int i = 0; i < size - 1; ++i)
            print_dim(shape.dim(i));
            std::cout << ", ";
          print_dim(shape.dim(size - 1));
        std::cout << "]\n";
    int main(int argc, char **argv)
      std::ifstream input("mobilenet.onnx", std::ios::ate | std::ios::binary); // open file and move current position in file to the end
      std::streamsize size = input.tellg(); // get current position in file
      input.seekg(0, std::ios::beg); // move to start of file
      std::vector<char> buffer(size);
      input.read(buffer.data(), size); // read raw data
      onnx::ModelProto model;
      model.ParseFromArray(buffer.data(), size); // parse protobuf
      auto graph = model.graph();
      std::cout << "graph inputs:\n";
      print_io_info(graph.input());