4

I'm trying to extract data like input layers, output layers and their shapes from an onnx model. I know there is python interface to do this. I want to do something similar to this code but in c++. I have also pasted the code from the link. I have tried it in python and it has worked for me. I want to know if there are c++ API's to do the same.

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()

Also I'm new to c++, please help me with the same.

1 Answer 1

8

ONNX format is essentially a protobuf, so it can be opened in any language protoc compiler supports.

In case of C++

  1. Take onnx proto file (onnx repo)
  2. Compile it with protoc --cpp_out=. onnx.proto3 command. It will generate onnx.proto3.pb.cc and onnx.proto3.pb.h files
  3. 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());

  std::cout << "graph outputs:\n";
  print_io_info(graph.output());
  return 0;
}
Sign up to request clarification or add additional context in comments.

2 Comments

can you please add the compile and link command as well, Thanks!
g++ *.cc -lprotobuf -pthread -o output

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.