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

新闻资讯   2023-07-19 15:48   94   0  

点击上方蓝字关注我们

微信公众号:OpenCV开发者联盟

关注获取更多计算机视觉与深度学习知识

ONNXRUNTIME1.13

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


不同版本的ONNXRUNTIME安装文件下载地址:
https://github.com/microsoft/onnxruntime/tags
框架主页:
https://onnxruntime.ai/

推理流程与API接口

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


Python SDK API支持:


C++ SDK API支持:


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

#include <onnxruntime_cxx_api.h>
#include <opencv2/opencv.hpp>
#include <fstream>

using namespace cv;
using namespace std;

int main(int argc, char** argv) {
    std::vector<std::string> 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<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++) {
        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::Mat::zeros(cv::Size(_max, _max), CV_8UC3);
    cv::Rect roi(00, 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(000), truefalse);
    size_t tpixels = input_h * input_w * 3;
    std::array<int64_t, 4> input_shape_info{ 13, 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(484);
        cv::Point classIdPoint;
        double score;
        minMaxLoc(classes_scores, 0, &score, 0, &classIdPoint);

        // 置信度 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.250.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(00255), 28);
        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(0255255), -1);
        putText(frame, labels[idx], cv::Point(boxes[index].tl().x, boxes[index].tl().y), cv::FONT_HERSHEY_PLAIN, 2.0, cv::Scalar(25500), 28);
        cv::imshow("YOLOv8+ONNXRUNTIME 对象检测演示", frame);
    }

    // 计算FPS render it
    float t = (cv::getTickCount() - start) / static_cast<float>(cv::getTickFrequency());
    putText(frame, cv::format("FPS: %.2f"1.0 / t), cv::Point(2040), cv::FONT_HERSHEY_PLAIN, 2.0, cv::Scalar(25500), 28);
    cv::imshow("YOLOv8+ONNXRUNTIME 对象检测演示", frame);
    cv::waitKey(0);

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


ONNXRUNTIME推理演示

YOLOv8 对象检测 C++ 


YOLOv8实例分割模型 C++ 推理:


UNet语义分割模型 C++ 推理:

Mask-RCNN实例分割模型 C++ 推理:

YOLOv8姿态评估模型 C++ 推理:


人脸关键点检测模型 C++ 推理:


人脸关键点检测模型 Python SDK 推理:


学会用C++部署YOLOv5与YOLOv8对象检测,实例分割,姿态评估模型,TorchVision框架下支持的Faster-RCNN,RetinaNet对象检测、MaskRCNN实例分割、Deeplabv3 语义分割模型等主流深度学习模型导出ONNX与C++推理部署,轻松解决Torchvision框架下模型训练到部署落地难题。


整个视频课程通过案例代码实战驱动,手把手系统化教学,帮助大家掌握ONNXRUNTIME API2 C++开发的各种技巧,学会图像分类、对象检测、语义分割、实例分割、pytorch自定义模型部署等ONNXRUNTIME  C++版本的模型推理与解析技巧,课程思维导图如下:

课程源码、测试图像与视频、模型等资料均可下载,负责答疑解惑

现在报名,享受系统自动拼团优惠
原价:199,
优惠价格:149


文章引用微信公众号"OpenCV学堂",如有侵权,请联系管理员删除!

博客评论
还没有人评论,赶紧抢个沙发~
发表评论
说明:请文明发言,共建和谐网络,您的个人信息不会被公开显示。