The_be 2024-11-02 19:13 采纳率: 25%
浏览 119

C++调用YOLOv11的onnx模型


#include <onnxruntime_cxx_api.h>
#include <opencv2/opencv.hpp>
#include <fstream>
using namespace cv;
using namespace std;


int main(int argc, char** argv)
{
    std::cout << "OpenCV version: " << CV_VERSION << std::endl;
    std::cout << "ONNX Runtime version: " << Ort::GetVersionString() << std::endl;

    cv::Mat frame = cv::imread("E:/2.jpg", 1);
    std::string onnxpath = "E:/best.onnx";

    //step2:load labels
    std::vector<std::string> labels;
    std::ifstream inputFile("E:/classes.names");
    if (inputFile.is_open())
    {
        std::string classLine;
        while (std::getline(inputFile, classLine))
            labels.push_back(classLine);
        inputFile.close();
    }

    //step-3:load onnx model
    int ih = frame.rows;
    int iw = frame.cols;
    std::wstring modelPath = std::wstring(onnxpath.begin(), onnxpath.end());
    Ort::SessionOptions session_options = Ort::SessionOptions();;
    Ort::Env env = Ort::Env(ORT_LOGGING_LEVEL_WARNING, "yolov11");
    std::cout << "onnxruntime inference try to use GPU Device" << std::endl;
    Ort::Session session_(env, modelPath.c_str(), session_options);

    std::vector<std::string> input_node_names;
    std::vector<std::string> output_node_names;

    size_t numInputNodes = session_.GetInputCount();
    size_t numOutputNodes = session_.GetOutputCount();
    Ort::AllocatorWithDefaultOptions allocator;
    input_node_names.reserve(numInputNodes);

    int input_w = 0;
    int input_h = 0;
    for (int i = 0; i < numInputNodes; i++) {
        //onnx newest version-1.14
        auto input_name = session_.GetInputNameAllocated(i, allocator);
        input_node_names.push_back(input_name.get());

        //onnx old version-1.8
        //input_node_names.push_back(session_.GetInputName(i, allocator));

        Ort::TypeInfo input_type_info = session_.GetInputTypeInfo(i);
        auto input_tensor_info = input_type_info.GetTensorTypeAndShapeInfo();
        auto input_dims = input_tensor_info.GetShape();
        input_w = input_dims[3];
        input_h = input_dims[2];
        std::cout << "input format: NxCxHxW = " << input_dims[0] << "x" << input_dims[1] << "x" << input_dims[2] << "x" << input_dims[3] << std::endl;
    }

    //step-4:get output parameter
    int output_h = 0;
    int output_w = 0;
    Ort::TypeInfo output_type_info = session_.GetOutputTypeInfo(0);
    auto output_tensor_info = output_type_info.GetTensorTypeAndShapeInfo();
    auto output_dims = output_tensor_info.GetShape();
    output_h = output_dims[1];
    output_w = output_dims[2];
    std::cout << "output format : HxW = " << output_dims[1] << "x" << output_dims[2] << std::endl;
    for (int i = 0; i < numOutputNodes; i++)
    {
        //onnx newest version-1.14
        auto out_name = session_.GetOutputNameAllocated(i, allocator);
        output_node_names.push_back(out_name.get());

        //onnx old version-1.8
        //output_node_names.push_back(session_.GetOutputName(i, allocator));
    }
    std::cout << "input: " << input_node_names[0] << " output: " << output_node_names[0] << std::endl;

    //step-5:get infer result
    int64 start = cv::getTickCount();
    int w = frame.cols;
    int h = frame.rows;
    int _max = std::max(h, w);
    cv::Mat image = cv::Mat::zeros(cv::Size(_max, _max), CV_8UC3);
    cv::Rect roi(0, 0, w, h);
    frame.copyTo(image(roi));

    // fix bug, boxes consistence!
    float x_factor = image.cols / static_cast<float>(input_w);
    float y_factor = image.rows / static_cast<float>(input_h);

    cv::Mat blob = cv::dnn::blobFromImage(image, 1 / 255.0, cv::Size(input_w, input_h), cv::Scalar(0, 0, 0), true, false);
    size_t tpixels = input_h * input_w * 3;
    std::array<int64_t, 4> input_shape_info{ 1, 3, input_h, input_w };

    // set input data and inference
    auto allocator_info = Ort::MemoryInfo::CreateCpu(OrtDeviceAllocator, OrtMemTypeCPU);
    Ort::Value input_tensor_ = Ort::Value::CreateTensor<float>(allocator_info, blob.ptr<float>(), tpixels, input_shape_info.data(), input_shape_info.size());
    const std::array<const char*, 1> inputNames = { input_node_names[0].c_str() };
    const std::array<const char*, 1> outNames = { output_node_names[0].c_str() };
    std::vector<Ort::Value> ort_outputs;
    try {
        ort_outputs = session_.Run(Ort::RunOptions{ nullptr }, inputNames.data(), &input_tensor_, 1, outNames.data(), outNames.size());
    }
    catch (std::exception e) {
        std::cout << e.what() << std::endl;
    }

    // output data
    const float* pdata = ort_outputs[0].GetTensorMutableData<float>();
    cv::Mat dout(output_h, output_w, CV_32F, (float*)pdata);
    cv::Mat det_output = dout.t(); // 8400x84

    // post-process
    std::vector<cv::Rect> boxes;
    std::vector<int> classIds;
    std::vector<float> confidences;

    for (int i = 0; i < det_output.rows; i++) {
        cv::Mat classes_scores = det_output.row(i).colRange(4, 84);
        cv::Point classIdPoint;
        double score;
        minMaxLoc(classes_scores, 0, &score, 0, &classIdPoint);

        //between 0~1
        if (score > 0.25)
        {
            float cx = det_output.at<float>(i, 0);
            float cy = det_output.at<float>(i, 1);
            float ow = det_output.at<float>(i, 2);
            float oh = det_output.at<float>(i, 3);
            int x = static_cast<int>((cx - 0.5 * ow) * x_factor);
            int y = static_cast<int>((cy - 0.5 * oh) * y_factor);
            int width = static_cast<int>(ow * x_factor);
            int height = static_cast<int>(oh * y_factor);
            cv::Rect box;
            box.x = x;
            box.y = y;
            box.width = width;
            box.height = height;

            boxes.push_back(box);
            classIds.push_back(classIdPoint.x);
            confidences.push_back(score);
        }
    }

    // NMS
    std::vector<int> indexes;
    cv::dnn::NMSBoxes(boxes, confidences, 0.25, 0.45, indexes);
    for (size_t i = 0; i < indexes.size(); i++) {
        int index = indexes[i];
        int idx = classIds[index];
        cv::rectangle(frame, boxes[index], cv::Scalar(0, 0, 255), 2, 8);
        cv::rectangle(frame, cv::Point(boxes[index].tl().x, boxes[index].tl().y - 20),
            cv::Point(boxes[index].br().x, boxes[index].tl().y), cv::Scalar(0, 255, 255), -1);

        std::string classString = labels[idx] + ' ' + std::to_string(confidences[idx]).substr(0, 4);
        putText(frame, classString, cv::Point(boxes[index].tl().x, boxes[index].tl().y), cv::FONT_HERSHEY_PLAIN, 2.0, cv::Scalar(255, 0, 0), 2, 8);
        cv::imshow("YOLOv11 onnxrunning", frame);
    }


    //calculate FPS render it
    float t = (cv::getTickCount() - start) / static_cast<float>(cv::getTickFrequency());
    putText(frame, cv::format("FPS: %.2f", 1.0 / t), cv::Point(20, 40), cv::FONT_HERSHEY_PLAIN, 2.0, cv::Scalar(255, 0, 0), 2, 8);
    cv::imshow("YOLOv11 onnxrunning", frame);
    cv::imwrite("result.jpg", frame);
    cv::waitKey(0);

    session_options.release();
    session_.release();
    return 0;
}

你好,感谢你查看我的问题,上述代码是我在CSDN找的一个C++调用yolov11导出的onnx格式代码,我在其中替换了我的图片、模型、类别文件路径,在vs2022运行,opencv版本是4.10,onnxruntime版本是1.20。在我运行之后它产生错误信息

这是报错内容,我也不懂第一次尝试,恳请大家能够帮助。

  • 写回答

2条回答

  • 香格里辣 2024-11-02 19:14
    关注

    以下回复参考:皆我百晓生券券喵儿等免费微信小程序作答:

    从你提供的错误信息来看,问题似乎出在模型的输入和输出节点名称的获取上。错误提示信息表示输入或输出节点名称为空,这可能是在获取节点名称时出现了问题。此外,你也提到在运行时遇到了其他错误,但你没有提供具体的错误信息,所以我只能根据现有的信息进行分析。

    首先,我建议你检查以下几点:

    1. 确保你的模型路径(onnxpath)是正确的,并且模型文件确实存在于该路径下。
    2. 确保你的类别文件路径(用于加载标签)是正确的,并且文件存在且可访问。
    3. 检查你的模型是否正确导出为ONNX格式,并且支持YOLOv11的输入和输出格式。

    关于代码中的问题,我注意到你在获取输入和输出节点名称时使用了以下代码:

    //onnx newest version-1.14
    auto input_name = session_.GetInputNameAllocated(i, allocator);
    input_node_names.push_back(input_name.get());
    // ...类似地获取输出节点名称
    

    这段代码使用了GetInputNameAllocatedGetOutputNameAllocated函数来获取节点名称。这些函数在新版本的ONNX Runtime中可能已经被弃用或更改了。你可以尝试使用其他方法来获取节点名称,例如使用GetInputInfoGetOutputInfo函数来获取输入和输出的信息,然后从中提取名称。

    另外,确保你的ONNX模型具有正确的输入和输出节点名称,并且在代码中正确设置了这些名称。你也可以尝试打印模型的输入和输出信息,以检查它们是否正确。

    最后,请确保你的ONNX模型和YOLOv11的版本是兼容的,因为不同版本的模型和框架可能会有一些差异。如果可能的话,尝试使用与YOLOv11版本匹配的ONNX模型。

    如果你能提供更多的错误信息或详细的代码调试过程,我可以更具体地帮助你解决问题。

    评论

报告相同问题?

问题事件

  • 创建了问题 11月2日