The_be 2024-11-02 21:25 采纳率: 25%
浏览 183

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。在我运行之后它产生错误信息

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

OpenCV version: 4.10.0
ONNX Runtime version: 1.20.0
onnxruntime inference try to use GPU Device
input format: NxCxHxW = 1x3x640x640
output format : HxW = 9x8400
input: images output: output0
OpenCV(4.10.0) Error: Assertion failed (0 <= _colRange.start && _colRange.start <= _colRange.end && _colRange.end <= m.cols) in cv::Mat::Mat, file C:\GHA-OCV-1_work\ci-gha-workflow\ci-gha-workflow\opencv\modules\core\src\matrix.cpp, line 776
OpenCV: terminate handler is called! The last OpenCV error is:
OpenCV(4.10.0) Error: Assertion failed (0 <= _colRange.start && _colRange.start <= _colRange.end && _colRange.end <= m.cols) in cv::Mat::Mat, file C:\GHA-OCV-1_work\ci-gha-workflow\ci-gha-workflow\opencv\modules\core\src\matrix.cpp, line 776

img

  • 写回答

1条回答 默认 最新

  • 香格里辣 2024-11-02 21:26
    关注

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

    根据你提供的错误信息,问题似乎出在尝试从cv::Mat对象中获取数据时,尤其是当尝试创建一个新的cv::Mat对象时。错误信息指出一个断言失败,该断言检查某些参数的有效性,例如矩阵的范围和维度是否正确。这可能是由于输入到函数的矩阵参数(例如输入图像)与期望的尺寸或格式不匹配造成的。以下是一些可能的解决方案:

    1. 检查输入图像尺寸和格式是否正确:确保输入图像的大小和格式与模型输入相匹配。根据你的代码,模型输入大小为HxW=640x640,并且可能是BGR格式。如果输入图像的尺寸或格式不正确,可能会出现此错误。确保你读取图像时使用正确的参数,如cv::imread("E:/2.jpg", CV_LOAD_IMAGE_COLOR)以确保以正确的格式加载图像。
    2. 检查模型的输出维度:在你的代码中,你从模型的输出创建了一个cv::Mat对象det_output。确保模型的输出维度与你的代码中的预期维度相匹配。如果输出维度不正确,可能会导致错误。检查模型的输出配置并确保它们与你的代码中的预期匹配。
    3. 确保ONNX模型与OpenCV版本兼容:虽然你使用的OpenCV版本是4.10和ONNX Runtime版本是1.20,但有时可能会出现版本不兼容的问题。确保你使用的ONNX模型与你的OpenCV和ONNX Runtime版本兼容。

    尝试检查这些可能的问题点并进行相应的修复。如果这些建议无法解决你的问题,可能需要进一步检查你的代码逻辑,尤其是涉及矩阵操作和模型输出的部分。如果你还有其他问题或需要进一步的帮助,请提供更多关于错误的详细信息或相关代码段,我将尽力协助你解决问题。

    评论

报告相同问题?

问题事件

  • 创建了问题 11月2日