Search code examples
c++opencvonnxonnxruntimemodelmetadata

What is the best way to read metadata from onnx model from C++?


I have model in onnx format that contains attribute "list_classes". I run it with opencv dnn. I need to read this list using C++.

  • I tried opencv dnn library, but it seems like there is no instruments for that.
  • I tried onnxruntime, but I can't even create a session. I'm not very familiar with its syntax so maybe I did something wrong.Here is test program:
#include <onnxruntime_cxx_api.h>
#include <iostream>

int main()
{
    auto model_path = L"model.onnx";
    std::unique_ptr<Ort::Env> ort_env;
    Ort::SessionOptions session_options;
    Ort::Session session(*ort_env, model_path, session_options);

    return 0;
}

This code throws error message


Solution

  • I kind of figured it out

    #include <iostream>
    #include "onnxruntime_cxx_api.h"
    
    std::vector<std::string> split(std::string str, std::string delimiter) {
        size_t pos = 0;
        std::string token;
        while ((pos = str.find(delimiter)) != std::string::npos) {
            token = str.substr(0, pos);
            output.push_back(token);
            str.erase(0, pos + delimiter.length());
        }
        output.push_back(str);
        return output;
    }
    
    int main() {
        std::string model_path = "path/to/model.onnx";
        std::wstring widestr = std::wstring(model_path.begin(), model_path.end());
        const wchar_t* widecstr = widestr.c_str();
        Ort::Env env;
        Ort::SessionOptions ort_session_options;
        Ort::Session session = Ort::Session(env, widecstr, ort_session_options);
        Ort::AllocatorWithDefaultOptions ort_alloc;
    
        std::cout << "CLASS NAMES: " << std::endl;
        Ort::ModelMetadata model_metadata = session.GetModelMetadata();
        Ort::AllocatedStringPtr search = model_metadata.LookupCustomMetadataMapAllocated("classes", ort_alloc);
        std::vector<std::string> classNames;
        if (search != nullptr) {
            const std::array<const char*, 1> list_classes = { search.get() };
            classNames = split(std::string(list_classes[0]), ",");
            for (int i = 0; i < classNames.size(); i++)
                std::cout << "\t" << i << " | " << classNames[i] << std::endl;
        }
    
        return 0;
    }
    

    The output looks like this:

    CLASS NAMES:
        0 | class_1
        1 | class_2
        2 | class_3