YOLOv8对象检测ONNXRUNTIME部署C++源码演示

描述

 

ONNXRUNTIME1.13

    ONNXRUNTIME是主流的深度学习部署框架之一,支持ONNX格式模型在CPU、GPU、ARM等不同硬件平台上加速推理,支持C++、Python、Java、C#、JS等不同语言SDK。C++版本安装包下载如下:

python

不同版本的ONNXRUNTIME安装文件下载地址

  框架主页

推理流程与API接口

常用组件与推理流程支持:

python

Python SDK API支持:

python

C++ SDK API支持:

python

YOLOv8对象检测 + ONNXRUNTIME深度学习 C++源码如下:

 

#include 
#include 
#include 

using namespace cv;
using namespace std;

int main(int argc, char** argv) {
    std::vector labels = readClassNames();
    cv::Mat frame = cv::imread("D:/python/my_yolov8_train_demo/zidane.jpg");
    int ih = frame.rows;
    int iw = frame.cols;

    // 创建InferSession, 查询支持硬件设备
    // GPU Mode, 0 - gpu device id
    std::string onnxpath = "D:/python/my_yolov8_train_demo/yolov8n.onnx";
    std::wstring modelPath = std::wstring(onnxpath.begin(), onnxpath.end());
    Ort::SessionOptions session_options;
    Ort::Env env = Ort::Env(ORT_LOGGING_LEVEL_ERROR, "yolov8-onnx");

    session_options.SetGraphOptimizationLevel(ORT_ENABLE_BASIC);
    std::cout << "onnxruntime inference try to use GPU Device" << std::endl;
    OrtSessionOptionsAppendExecutionProvider_CUDA(session_options, 0);
    Ort::Session session_(env, modelPath.c_str(), session_options);

    std::vector input_node_names;
    std::vector 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++) {
        auto input_name = session_.GetInputNameAllocated(i, allocator);
        input_node_names.push_back(input_name.get());
        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;
    }

    // 获取输出信息
    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]; // 84
    output_w = output_dims[2]; // 8400
    std::cout << "output format : HxW = " << output_dims[1] << "x" << output_dims[2] << std::endl;
    for (int i = 0; i < numOutputNodes; i++) {
        auto out_name = session_.GetOutputNameAllocated(i, allocator);
        output_node_names.push_back(out_name.get());
    }
    std::cout << "input: " << input_node_names[0] << " output: " << output_node_names[0] << std::endl;

    // format frame
    int64 start = cv::getTickCount();
    int w = frame.cols;
    int h = frame.rows;
    int _max = std::max(h, w);
    cv::Mat image = 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(input_w);
    float y_factor = image.rows / static_cast(input_h);

    cv::Mat blob = cv::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 input_shape_info{ 1, 3, input_h, input_w };

    // set input data and inference
    auto allocator_info = Ort::CreateCpu(OrtDeviceAllocator, OrtMemTypeCPU);
    Ort::Value input_tensor_ = Ort::CreateTensor(allocator_info, blob.ptr(), tpixels, input_shape_info.data(), input_shape_info.size());
    const std::array inputNames = { input_node_names[0].c_str() };
    const std::array outNames = { output_node_names[0].c_str() };
    std::vector 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();
    cv::Mat dout(output_h, output_w, CV_32F, (float*)pdata);
    cv::Mat det_output = dout.t(); // 8400x84

    // post-process
    std::vector boxes;
    std::vector classIds;
    std::vector 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);

        // 置信度 0~1之间
        if (score > 0.25)
        {
            float cx = det_output.at(i, 0);
            float cy = det_output.at(i, 1);
            float ow = det_output.at(i, 2);
            float oh = det_output.at(i, 3);
            int x = static_cast((cx - 0.5 * ow) * x_factor);
            int y = static_cast((cy - 0.5 * oh) * y_factor);
            int width = static_cast(ow * x_factor);
            int height = static_cast(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 indexes;
    cv::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);
        putText(frame, labels[idx], 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("YOLOv8+ONNXRUNTIME 对象检测演示", frame);
    }

    // 计算FPS render it
    float t = (cv::getTickCount() - start) / static_cast(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("YOLOv8+ONNXRUNTIME 对象检测演示", frame);
    cv::waitKey(0);

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

 

 

  审核编辑:汤梓红

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分