Openvino2024.3版部署YOLO (C++)

news2024/9/23 9:37:17

在网上很少看到有2024版的openvino,老版本的接口很多也都不在了,此篇写出来也算是为了防止自己忘记。

openvino下载

下载英特尔发行版 OpenVINO 工具套件 (intel.com)

下载好后解压出来,放C盘D盘都一样,我放在D盘了,这个文件夹名字有点长,自己修改成openvino_2024

打开你pycharm或者命令打开你的虚拟环境,安装下载

pip install openvino-genai==2024.3.0

cmd,进入虚拟环境->D盘openvino_2024文件夹中,运行setupvars.bat,再把下面的都运行,可能需要先更新一下你的pip

python -m pip install --upgrade pip
pip install onnx
pip install tensorflow
pip install mxnet
pip install network
如果下载速度太慢,可以加个清华源 -i https://pypi.tuna.tsinghua.edu.cn/simple

添加电脑环境变量

将openvino_2024中的路径加进去,我的是在D盘

D:\openvino_2024\runtime\bin\intel64\Debug
D:\openvino_2024\runtime\bin\intel64\Release
D:\openvino_2024\runtime\3rdparty\tbb\bin

到这一步openvino的环境算是全部装好了,前提是上面的安装都没有报错,验证的话先使用pycharm进行转换,pt->onnx->xml/bin

利用YOLO代码中的export.py将pt转成onnx

python export.py --weights yolov5s.pt --img 640 --batch 1

由于2024版的openvino已经取消了mo_onnx.py模型转换工具,所以需要我们自己转,脚本写在下方了

from openvino.runtime import Core
from openvino.runtime import serialize
 
ie = Core()
onnx_model_path = r"自己的模型路径.onnx"
model_onnx = ie.read_model(model=onnx_model_path)
# compiled_model_onnx = ie.compile_model(model=model_onnx, device_name="CPU")
serialize(model=model_onnx, xml_path="生成xml的模型路径.xml", bin_path="生成bin模型的路径.bin", version="UNSPECIFIED")

运行之后你就得到了xml和bin模型,如果报错了,就说明你openvino没装好,自己再去对照一下上面步骤

C++部署

自己去创个新项目,配置一下项目环境

包含目录添加

D:\opencv\build\include
D:\opencv\build\include\opencv2
D:\openvino_2024\runtime\include
D:\openvino_2024\runtime\include\openvino

库目录添加

D:\opencv\build\x64\vc15\lib
D:\openvino_2024\runtime\lib\intel64\Release

链接器->输入->附加依赖项

opencv_world452.lib
openvino.lib

这就算全部配置完了,直接上代码

openvino.cpp

#include"openvino.h"

YOLO_OPENVINO::YOLO_OPENVINO()
{
}

YOLO_OPENVINO::~YOLO_OPENVINO()
{
}


YOLO_OPENVINO::Resize YOLO_OPENVINO::resize_and_pad(cv::Mat& img, cv::Size new_shape)
{
    float width = img.cols;
    float height = img.rows;
    float r = float(new_shape.width / max(width, height));
    int new_unpadW = int(round(width * r));
    int new_unpadH = int(round(height * r));

    cv::resize(img, resize.resized_image, cv::Size(new_unpadW, new_unpadH), 0, 0, cv::INTER_AREA);

    resize.dw = new_shape.width - new_unpadW;//w方向padding值 
    resize.dh = new_shape.height - new_unpadH;//h方向padding值 
    cv::Scalar color = cv::Scalar(100, 100, 100);
    cv::copyMakeBorder(resize.resized_image, resize.resized_image, 0, resize.dh, 0, resize.dw, cv::BORDER_CONSTANT, color);

    return resize;
}

void YOLO_OPENVINO::yolov5_compiled(std::string xml_path, ov::CompiledModel& compiled_model)
{
    // Step 1. Initialize OpenVINO Runtime core
    ov::Core core;
    // Step 2. Read a model
    //std::shared_ptr<ov::Model> model = core.read_model("best.xml");
    std::shared_ptr<ov::Model> model = core.read_model(xml_path);
    // Step 4. Inizialize Preprocessing for the model 初始化模型的预处理
    ov::preprocess::PrePostProcessor ppp = ov::preprocess::PrePostProcessor(model);
    // Specify input image format 指定输入图像格式
    ppp.input().tensor().set_element_type(ov::element::u8).set_layout("NHWC").set_color_format(ov::preprocess::ColorFormat::BGR);
    // Specify preprocess pipeline to input image without resizing 指定输入图像的预处理管道而不调整大小
    ppp.input().preprocess().convert_element_type(ov::element::f32).convert_color(ov::preprocess::ColorFormat::RGB).scale({ 255., 255., 255. });
    //  Specify model's input layout 指定模型的输入布局
    ppp.input().model().set_layout("NCHW");
    // Specify output results format 指定输出结果格式
    ppp.output().tensor().set_element_type(ov::element::f32);
    // Embed above steps in the graph 在图形中嵌入以上步骤
    model = ppp.build();
    compiled_model = core.compile_model(model, "CPU");
}

void YOLO_OPENVINO::yolov5_detector(ov::CompiledModel compiled_model, cv::Mat input_detect_img, cv::Mat output_detect_img, vector<cv::Rect>& nms_box)
{
    // Step 3. Read input image
    cv::Mat img = input_detect_img.clone();
    int img_height = img.rows;
    int img_width = img.cols;
    vector<cv::Mat>images;
    vector<cv::Rect> boxes;
    vector<int> class_ids;
    vector<float> confidences;

    if (img_height < 5000 && img_width < 5000)
    {
        images.push_back(img);
    }
    else
    {
        images.push_back(img(cv::Range(0, 0.6 * img_height), cv::Range(0, 0.6 * img_width)));
        images.push_back(img(cv::Range(0, 0.6 * img_height), cv::Range(0.4 * img_width, img_width)));
        images.push_back(img(cv::Range(0.4 * img_height, img_height), cv::Range(0, 0.6 * img_width)));
        images.push_back(img(cv::Range(0.4 * img_height, img_height), cv::Range(0.4 * img_width, img_width)));
    }

    for (int m = 0; m < images.size(); m++)
    {
        // resize image
        Resize res = resize_and_pad(images[m], cv::Size(640, 640));
        // Step 5. Create tensor from image
        float* input_data = (float*)res.resized_image.data;//缩放后图像数据
        ov::Tensor input_tensor = ov::Tensor(compiled_model.input().get_element_type(), compiled_model.input().get_shape(), input_data);


        // Step 6. Create an infer request for model inference 
        ov::InferRequest infer_request = compiled_model.create_infer_request();
        infer_request.set_input_tensor(input_tensor);

        //计算推理时间
        auto start = std::chrono::system_clock::now();
        infer_request.infer();
        auto end = std::chrono::system_clock::now();
        std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << "ms" << std::endl;



        //Step 7. Retrieve inference results 
        const ov::Tensor& output_tensor = infer_request.get_output_tensor();
        ov::Shape output_shape = output_tensor.get_shape();
        float* detections = output_tensor.data<float>();

        for (int i = 0; i < output_shape[1]; i++)//遍历所有框
        {
            float* detection = &detections[i * output_shape[2]];//bbox(x y w h obj cls)

            float confidence = detection[4];//当前bbox的obj
            if (confidence >= CONFIDENCE_THRESHOLD) //判断是否为前景
            {
                float* classes_scores = &detection[5];
                cv::Mat scores(1, output_shape[2] - 5, CV_32FC1, classes_scores);
                cv::Point class_id;
                double max_class_score;
                cv::minMaxLoc(scores, 0, &max_class_score, 0, &class_id);//返回最大得分和最大类别

                if (max_class_score > SCORE_THRESHOLD)//满足得分
                {
                    confidences.push_back(confidence);

                    class_ids.push_back(class_id.x);

                    float x = detection[0];//框中心x 
                    float y = detection[1];//框中心y 
                    float w = detection[2];//49
                    float h = detection[3];//50

                    float rx = (float)images[m].cols / (float)(res.resized_image.cols - res.dw);//x方向映射比例
                    float ry = (float)images[m].rows / (float)(res.resized_image.rows - res.dh);//y方向映射比例

                    x = rx * x;
                    y = ry * y;
                    w = rx * w;
                    h = ry * h;

                    if (m == 0)
                    {
                        x = x;
                        y = y;
                    }
                    else if (m == 1)
                    {
                        x = x + 0.4 * img_width;
                        y = y;

                    }
                    else if (m == 2)
                    {
                        x = x;
                        y = y + 0.4 * img_height;
                    }
                    else if (m == 3)
                    {
                        x = x + 0.4 * img_width;
                        y = y + 0.4 * img_height;
                    }

                    float xmin = x - (w / 2);//bbox左上角x
                    float ymin = y - (h / 2);//bbox左上角y
                    boxes.push_back(cv::Rect(xmin, ymin, w, h));
                }
            }
        }
    }

    std::vector<int> nms_result;
    cv::dnn::NMSBoxes(boxes, confidences, SCORE_THRESHOLD, NMS_THRESHOLD, nms_result);
    std::vector<Detection> output;

    for (int i = 0; i < nms_result.size(); i++)
    {
        Detection result;
        int idx = nms_result[i];
        result.class_id = class_ids[idx];
        result.confidence = confidences[idx];
        result.box = boxes[idx];
        nms_box.push_back(result.box);//传给Qt NMS后的box
        output.push_back(result);
    }


    // Step 9. Print results and save Figure with detections
    for (int i = 0; i < output.size(); i++)
    {
        auto detection = output[i];
        auto box = detection.box;
        auto classId = detection.class_id;
        auto confidence = detection.confidence;


        float xmax = box.x + box.width;
        float ymax = box.y + box.height;

        cv::rectangle(img, cv::Point(box.x, box.y), cv::Point(xmax, ymax), cv::Scalar(0, 255, 0), 3);
        cv::rectangle(img, cv::Point(box.x, box.y - 20), cv::Point(xmax, box.y), cv::Scalar(0, 255, 0), cv::FILLED);
        cv::putText(img, std::to_string(classId), cv::Point(box.x, box.y - 5), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 0));

    }
    img.copyTo(output_detect_img);


}

openvino.h

#pragma once
#pragma once
#pragma once
#include <opencv2/dnn.hpp>
#include <openvino/openvino.hpp>
#include <opencv2/opencv.hpp>

using namespace std;

class YOLO_OPENVINO
{
public:
    YOLO_OPENVINO();
    ~YOLO_OPENVINO();

public:
    struct Detection
    {
        int class_id;
        float confidence;
        cv::Rect box;
    };

    struct Resize
    {
        cv::Mat resized_image;
        int dw;
        int dh;
    };

    Resize resize_and_pad(cv::Mat& img, cv::Size new_shape);
    void yolov5_compiled(std::string xml_path, ov::CompiledModel& compiled_model);
    void yolov5_detector(ov::CompiledModel compiled_model, cv::Mat input_detect_img, cv::Mat output_detect_img, vector<cv::Rect>& nms_box);

private:

    const float SCORE_THRESHOLD = 0.4;
    const float NMS_THRESHOLD = 0.4;
    const float CONFIDENCE_THRESHOLD = 0.1;

    //vector<cv::Mat>images;//图像容器 
    //vector<cv::Rect> boxes;
    //vector<int> class_ids;
    //vector<float> confidences;
    //vector<cv::Rect>output_box;
    Resize resize;

};

main.cpp

#include"openvino.h"
#include<string>
#include<vector>
#include<iostream>
using namespace cv;
using namespace std;
YOLO_OPENVINO yolo_openvino;
std::string path = "yolov5s.xml";
ov::CompiledModel model;
cv::Mat input_img, output_img;
vector<cv::Rect>output_box;
int main()
{
    String path1 = "D:\\py\\images";//文件夹路径
    vector<String>src_test;
    glob(path1, src_test, false);//将文件夹路径下的所有图片路径保存到src_test中

    if (src_test.size() == 0) {//判断文件夹里面是否有图片
        printf("error!!!\n");
        exit(1);
    }
    /* input_img = cv::imread("3.jpg");
     yolo_openvino.yolov5_compiled(path, model);
     yolo_openvino.yolov5_detector(model, input_img, output_img, output_box);*/

    yolo_openvino.yolov5_compiled(path, model);
    for (int i = 0; i < src_test.size(); i++) {//依照顺序读取文价下面的每张图片,并显示
        int pos = src_test[i].find_last_of("\\");
        std::string img_name(src_test[i].substr(pos + 1));
        Mat frame = imread(src_test[i]);
        yolo_openvino.yolov5_detector(model, frame, output_img, output_box);
        for (int i = 0; i < output_box.size(); i++)
        {
            cv::rectangle(frame, cv::Point(output_box[i].x, output_box[i].y), cv::Point(output_box[i].x + output_box[i].width, output_box[i].y + output_box[i].height), cv::Scalar(0, 255, 0), 3);
        }
        output_box.clear();
        cv::imwrite("检测图片保存的路径" + img_name, frame);

    }


}

运行效果图就不展示了,代码没有问题的,如果报错了,肯定是你自己的细节问题,不懂的下面评论

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2074559.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何解决 Cloudflare | 使用 Puppeteer 和 Node.JS

我认为&#xff0c;现在自动化任务越多&#xff0c;越能体现它们的价值&#xff0c;因此挑战也变得更加明显和困难。例如&#xff0c;Cloudflare 目前提供了强有力的安全措施来保护网站免受所有形式的自动化工具的侵扰。 但对于从事自动化项目&#xff08;如网络爬虫、数据提取…

STM32(七):定时器——输入捕获

IC&#xff08;Input Capture&#xff09;输入捕获 输入捕获模式下&#xff0c;当通道输入引脚出现指定电平跳变时&#xff0c;当前CNT的值将被锁存到CCR中&#xff0c;可用于测量PWM波形的频率、占空比、脉冲间隔、电平持续时间等参数。 每个高级定时器和通用定时器都拥有4个输…

基于vscode安装EPS-IDF环境与创建例程

安装ESP-IDF 在vscode中安装esp-idf插件 然后打开插件&#xff0c;左侧选择Configure ESP-IDF Extension ![![[Pasted image 20240821221256.png]](https://i-blog.csdnimg.cn/direct/3993e22c37644097b464aef0bbc244a5.png) 点击安装 自动下载ESP-IDF 安装完成&#xff01…

计算机毕业设计推荐- 基于Python的高校岗位招聘数据分析平台

&#x1f496;&#x1f525;作者主页&#xff1a;毕设木哥 精彩专栏推荐订阅&#xff1a;在 下方专栏&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; 实战项目 文章目录 实战项目 一、基于Python的高校岗位招聘分…

Gitee的使用方法

是跟着这位up的视频学习的&#xff0c;老师讲的很好 https://www.bilibili.com/video/BV1hf4y1W7yT/share_sourcecopy_web&vd_source985ed259d2e2be1d81c218c58be165b9 需要的安装包我学习完成后&#xff0c;会放到我的gitee仓库里&#xff0c;也当作是练习一下。 insta…

PriorMapNet:Enhancing Online Vectorized HD Map Construction with Priors

参考代码&#xff1a;None 动机与出发点 训练场景中的车道线千变万化会导致query方式预测方式变得较难收敛或者性能较低&#xff0c;之前的一些工作有将mask信息引入到pipeline中为query提供instance-level的语义信息&#xff0c;但是对于point-level信息就需要自己去学习了。…

动态规划:从记忆化搜索到递推 打家劫舍

目录 LeetCode198 打家劫舍 1、递归搜索保存计算结果记忆化搜索 2、1:1翻译成递推 3、空间优化 LeetCode213 打家劫舍II LeetCode198 打家劫舍 1、递归搜索保存计算结果记忆化搜索 回溯三问&#xff1a; &#xff08;1&#xff09;当前操作&#xff1f;枚举第i个房子选/不…

计算机的错误计算(七十三)

摘要 计算机的错误计算&#xff08;七十二&#xff09;探讨了大数的余割函数的错误计算 。本节讨论另外一类数值&#xff1a; 附近数 的余割函数的计算精度问题。 例1. 已知 计算 csc(x) . 若在 Excel 中计算&#xff0c;则有 若用Java 编程实现 , 即有下列代码&#x…

认知杂谈26

今天分享 有人说的一段争议性的话 I I 上班的双刃剑&#xff1a;安稳与束缚的较量 上班这事儿啊&#xff0c;好多人都觉得那就是稳定的代表。每天按时去打卡&#xff0c;每个月都能稳稳地拿到工资&#xff0c;听起来好像挺美的&#xff0c;就跟理想生活似的。但咱要是仔细琢…

UE管理内容 —— FBX Asset Metadata Pipeline

随着实时3D制作大小和复杂程度的增加&#xff0c;以及构成现代制作流程的工具数量的不断增加&#xff0c;增加智能自动化来提高美术效率变得越发重要&#xff1b;这种智能自动化通常主要依靠元数据&#xff1a;有关资源的自定义数据&#xff0c;在项目中为资源赋予意义&#xf…

基于GA遗传优化的三维空间WSN网络最优节点部署算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 空间覆盖度模型 基于GA的优化方法 5.完整程序 1.程序功能描述 基于GA遗传优化的三维空间WSN网络最优节点部署算法matlab仿真。分别对三维空间的节点覆盖率&#xff0c;节点覆盖使用数量进行…

为什么走线宽度不同会引起阻抗畸变

事先说明&#xff1a;内容不是原创&#xff0c;或者只是自己的技术总结。仅仅用于本人日常记录 1 参考博客 参考博客来源&#xff1a; 原博客 2 基本知识点 2.1 为什么阻抗突变会引起反射 信号沿传输线传播时&#xff0c;其路径上的每一步&#xff0c;都有相应的瞬时阻抗&…

项目需求 | vscode远程免密登录Linux服务器指南-含所需的命令和步骤

步骤1&#xff1a;安装Remote - SSH扩展 在VSCode中&#xff0c;打开扩展视图&#xff0c;搜索并安装Remote Development扩展包&#xff0c;它包含了Remote - SSH扩展。 步骤2&#xff1a;生成SSH密钥对 在本地计算机上打开终端或命令提示符&#xff0c;执行以下命令&#…

约瑟夫环问题【算法 06】

约瑟夫环问题 约瑟夫环&#xff08;Josephus Problem&#xff09;是一个经典的数学和计算问题&#xff0c;其核心是解决在一群人围成一圈&#xff0c;每隔一定人数就淘汰一个人&#xff0c;最后剩下的那个人的编号。 问题描述 假设有 ( n ) 个人围成一圈&#xff0c;从第一个…

负载调制平衡放大器LMBA理论分析与ADS理想架构仿真

负载调制平衡放大器LMBA理论分析与ADS理想架构仿真 负载调制平衡放大器Load Modulation Balanced PA&#xff0c;简称LMBA是2016年Cripps大佬分析实践的&#xff1a; An Efficient Broadband Reconfigurable Power Amplifier Using Active Load Modulation 本文ADS工程下载链…

回顾MVC

Tomcat是servlet的容器,想用HttpServlet需要导入tomcat jar包 下图是没用springmvc时的场景&#xff0c;首先在web.xml里面配置访问路径为/Hello然后 通过get请求去调用login方法最后重定向到index.jsp中 index.jsp里面的内容 重定向到index.jsp中 在控制台获取到username里面的…

考研数学|强化速成!1000/660/880题重点刷哪本?

马上9月了&#xff0c;还在纠结做什么题吗&#xff0c;1000/660/880&#xff0c;这几本习题册都不错。我的建议是选一本主力习题册660。其中1000和880题都可以作为主力习题册&#xff0c;而660题专门考察客观题&#xff0c;可以作为辅助习题册来做。该怎么选呢&#xff1f;如果…

pytorch深度学习基础 8(简单的神经网络替换线性模型)

接上一节的思路&#xff0c;这一节我们将使用神经网络来代替我们的之前的线性模型作为逼近函数。我们将保持其他的一切不变&#xff0c;只重新定义模型&#xff0c;小编这里构建的是最简单的神经网络&#xff0c;一个线性模块&#xff0c;一个激活函数&#xff0c;然后一个线性…

8月25日笔记

IOX的使用 iox是一款功能强大的端口转发&内网代理工具&#xff0c;该工具的功能类似于lcx和ew&#xff0c;但是iox的功能和性能都更加强大。 实际上&#xff0c;lcx和ew都是非常优秀的工具&#xff0c;但还是有地方可以提升的。在一开始使用这些工具的一段时间里&#xff…

8月26日星期一今日早报简报微语报早读

8月26日星期一&#xff0c;农历七月廿三&#xff0c;早报微语早读。 1、中国战队EDG获得2024无畏契约全球冠军赛总冠军&#xff1b; 2、亚洲首例猴痘Ib变异病例出现&#xff0c;可通过飞沫传播&#xff1b; 3、三文鱼刺身隔夜返包销售 胖东来&#xff1a;奖励投诉者10万&…