openvino2022版本 推理yolov5 代码 c++

openvino2022版本 推理yolov5 代码 c++*

来来来各位兄弟姐妹大哥大姐们 如果这个文章对你们有帮助的话,请大家点点赞 。 小奴子在这里谢谢大家了。

本片文章对新手友好,请放心观看。咱们不讲理论,只来实际的。

//倒入openvino2022 库 具体使用方法会在cmakelist中
#include "openvino/openvino.hpp"

// system include
#include <stdio.h>
#include <math.h>

#include <iostream>
#include <fstream>
#include <vector>
#include <memory>
#include <functional>
#include <unistd.h>
//opencv
#include <opencv2/opencv.hpp>
//我这里是这个结构体是用于接收的  不需要的可以注释
struct AxleObjBoxInfo
{
    float left;
    float right;
    float top;
    float bottom;
    float score; ///< 得分
    int classID; ///< 类别
};

using namespace std;


//类别
static const char* labels[] = {"sw","dw"};
// hsv转bgr  画框时会用到的
static std::tuple<uint8_t, uint8_t, uint8_t> hsv2bgr(float h, float s, float v){
    const int h_i = static_cast<int>(h * 6);
    const float f = h * 6 - h_i;
    const float p = v * (1 - s);
    const float q = v * (1 - f*s);
    const float t = v * (1 - (1 - f) * s);
    float r, g, b;
    switch (h_i) {
    case 0:r = v; g = t; b = p;break;
    case 1:r = q; g = v; b = p;break;
    case 2:r = p; g = v; b = t;break;
    case 3:r = p; g = q; b = v;break;
    case 4:r = t; g = p; b = v;break;
    case 5:r = v; g = p; b = q;break;
    default:r = 1; g = 1; b = 1;break;}
    return make_tuple(static_cast<uint8_t>(b * 255), static_cast<uint8_t>(g * 255), static_cast<uint8_t>(r * 255));
}
//画框  颜色调节板
static std::tuple<uint8_t, uint8_t, uint8_t> random_color(int id){
    float h_plane = ((((unsigned int)id << 2) ^ 0x937151) % 100) / 100.0f;;
    float s_plane = ((((unsigned int)id << 3) ^ 0x315793) % 100) / 100.0f;
    return hsv2bgr(h_plane, s_plane, 1);
}

//主函数  std::string onnx_path onnx的路径  cv::Mat& images 传入图片  
//vector<AxleObjBoxInfo>&m_AxleObjBoxInfo  不需要可以注释 
void inference(std::string onnx_path,cv::Mat& images,vector<AxleObjBoxInfo>&m_AxleObjBoxInfo){
    //定义输出大小 1,3,h w 我这里是320 1280  你需要看你自己的模型输入
    size_t input_batch = 1;
    size_t input_channel = 3;
    size_t input_height = 320;
    size_t input_width = 1280;

    //定义 openvino推理工具
    ov::Core core;
    //读取模型
    auto model = core.compile_model(onnx_path);
    auto iq = model.create_infer_request();
    
    //获取 input 
    auto input = iq.get_input_tensor(0);
    //获取 output  我这里输出是一维度的  将三个输出改为一个 
    auto output = iq.get_output_tensor(0);
    //设置输入大小纬度
    input.set_shape({input_batch, input_channel, input_height, input_width});

    //获取输入
    float* input_data_host = input.data<float>();

    ///
    // letter box
    //auto image = cv::imread();
    auto image = images;
    // 通过双线性插值对图像进行resize
    float scale_x = input_width / (float)image.cols;
    float scale_y = input_height / (float)image.rows;
    float scale = std::min(scale_x, scale_y);
    float i2d[6], d2i[6];
    // resize图像,源图像和目标图像几何中心的对齐
    i2d[0] = scale;  i2d[1] = 0;  i2d[2] = (-scale * image.cols + input_width + scale  - 1) * 0.5;
    i2d[3] = 0;  i2d[4] = scale;  i2d[5] = (-scale * image.rows + input_height + scale - 1) * 0.5;

    cv::Mat m2x3_i2d(2, 3, CV_32F, i2d);  // image to dst(network), 2x3 matrix
    cv::Mat m2x3_d2i(2, 3, CV_32F, d2i);  // dst to image, 2x3 matrix
    cv::invertAffineTransform(m2x3_i2d, m2x3_d2i);  // 计算一个反仿射变换

    cv::Mat input_image(input_height, input_width, CV_8UC3);
    cv::warpAffine(image, input_image, m2x3_i2d, input_image.size(), cv::INTER_LINEAR, cv::BORDER_CONSTANT, cv::Scalar::all(114));  // 对图像做平移缩放旋转变换,可逆
    //cv::imwrite("input-image.jpg", input_image);
    
    int image_area = input_image.cols * input_image.rows;
    unsigned char* pimage = input_image.data;
    float* phost_b = input_data_host + image_area * 0;
    float* phost_g = input_data_host + image_area * 1;
    float* phost_r = input_data_host + image_area * 2;
    for(int i = 0; i < image_area; ++i, pimage += 3){
        // 注意这里的顺序rgb调换了
        *phost_r++ = pimage[0] / 255.0f;
        *phost_g++ = pimage[1] / 255.0f;
        *phost_b++ = pimage[2] / 255.0f;
    }
    ///
    //执行模型推理获取结果
    iq.infer();
    //接收结果 
    int output_numbox = output.get_shape()[1];
    int output_numprob = output.get_shape()[2];
    int num_classes = output_numprob - 5;
    float* output_data_host = output.data<float>();

    // decode box:从不同尺度下的预测狂还原到原输入图上(包括:预测框,类被概率,置信度)
    vector<vector<float>> bboxes;
    float confidence_threshold = 0.25;
    float nms_threshold = 0.5;
    for(int i = 0; i < output_numbox; ++i){
        float* ptr = output_data_host + i * output_numprob;
        float objness = ptr[4];
        if(objness < confidence_threshold)
            continue;

        float* pclass = ptr + 5;
        int label     = std::max_element(pclass, pclass + num_classes) - pclass;
        float prob    = pclass[label];
        float confidence = prob * objness;
        if(confidence < confidence_threshold)
            continue;

        // 中心点、宽、高
        float cx     = ptr[0];
        float cy     = ptr[1];
        float width  = ptr[2];
        float height = ptr[3];

        // 预测框
        float left   = cx - width * 0.5;
        float top    = cy - height * 0.5;
        float right  = cx + width * 0.5;
        float bottom = cy + height * 0.5;

        // 对应图上的位置
        float image_base_left   = d2i[0] * left   + d2i[2];
        float image_base_right  = d2i[0] * right  + d2i[2];
        float image_base_top    = d2i[0] * top    + d2i[5];
        float image_base_bottom = d2i[0] * bottom + d2i[5];
        bboxes.push_back({image_base_left, image_base_top, image_base_right, image_base_bottom, (float)label, confidence});
        
    }
    //printf("decoded bboxes.size = %d\n", bboxes.size());

    // nms非极大抑制
    std::sort(bboxes.begin(), bboxes.end(), [](vector<float>& a, vector<float>& b){return a[5] > b[5];});
    std::vector<bool> remove_flags(bboxes.size());
    std::vector<vector<float>> box_result;
    box_result.reserve(bboxes.size());

    auto iou = [](const vector<float>& a, const vector<float>& b){
        float cross_left   = std::max(a[0], b[0]);
        float cross_top    = std::max(a[1], b[1]);
        float cross_right  = std::min(a[2], b[2]);
        float cross_bottom = std::min(a[3], b[3]);

        float cross_area = std::max(0.0f, cross_right - cross_left) * std::max(0.0f, cross_bottom - cross_top);
        float union_area = std::max(0.0f, a[2] - a[0]) * std::max(0.0f, a[3] - a[1]) 
                         + std::max(0.0f, b[2] - b[0]) * std::max(0.0f, b[3] - b[1]) - cross_area;
        if(cross_area == 0 || union_area == 0) return 0.0f;
        return cross_area / union_area;
    };

    for(int i = 0; i < bboxes.size(); ++i){
        if(remove_flags[i]) continue;

        auto& ibox = bboxes[i];
        box_result.emplace_back(ibox);
        for(int j = i + 1; j < bboxes.size(); ++j){
            if(remove_flags[j]) continue;

            auto& jbox = bboxes[j];
            if(ibox[4] == jbox[4]){
                // class matched
                if(iou(ibox, jbox) >= nms_threshold)
                    remove_flags[j] = true;
            }
        }
    }
    printf("box_result.size = %d\n", box_result.size());
    
    for(int i = 0; i < box_result.size(); ++i){
        auto& ibox = box_result[i];
        float left = ibox[0];
        float top = ibox[1];
        float right = ibox[2];
        float bottom = ibox[3];
        int class_label = ibox[4];
        float confidence = ibox[5];
        //画图
        cv::Scalar color;
        tie(color[0], color[1], color[2]) = random_color(class_label);
        //cv::rectangle(image, cv::Point(left, top), cv::Point(right, bottom), color, 3);

        auto name      = cocolabels[class_label];
        auto caption   = cv::format("%s %.2f", name, confidence);
        int text_width = cv::getTextSize(caption, 0, 1, 2, nullptr).width + 10;
        m_AxleObjBoxInfo.push_back({left,top,right,bottom,confidence,class_label});
        //cout << "ku " << m_AxleObjBoxInfo.size()<<endl;
        //cv::rectangle(image, cv::Point(left-3, top-33), cv::Point(left + text_width, top), color, -1);
        //cv::putText(image, caption, cv::Point(left, top-5), 0, 1, cv::Scalar::all(0), 2, 16);
    }
    //cv::imwrite("image-draw.jpg", image);
}
int main(){
    std::string path = "模型路径";
    std::string img = "图片路径";
    cv::Mat images = cv::imread(img);
    std::vector<AxleObjBoxInfo> m_axleObjBoxInfoVector;
    //调用主函数
    inference(path,images,m_axleObjBoxInfoVector);
    return 0;
}

CMakeLists

#cmake最低版本要求
cmake_minimum_required(VERSION 3.10)
set(CMAKE_CXX_STANDARD 11)
set(TARGET_NAME chelun2)

find_package(OpenCV REQUIRED)

#自动寻找openvino 这里寻找的是~/.bashrc中的路径  你需要先安装2022版本然后设置好环境变量
#将可以直接使用了
find_package(OpenVINO REQUIRED)




# 编译detector_bbox.so  生成库文件
add_library(chelun2 SHARED ${PROJECT_SOURCE_DIR}/src/detect_chelun2.cpp)

target_link_libraries(${TARGET_NAME} PRIVATE openvino::runtime ${OpenCV_LIBS})

//生成可执行文件   尽量不要与生成库一起使用  
#add_executable(chelun2 src/main.cpp src/detect_chelun2.cpp) #run.cpp
#target_link_libraries(${TARGET_NAME} PRIVATE openvino::runtime ${OpenCV_LIBS})
  • 9
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
YOLOv5是一种流行的目标检测算法,而OpenVINO 2022是一款用于深度学习模型部署和加速推理的工具包。结合使用YOLOv5OpenVINO 2022可以实现高效的目标检测应用部署。 使用OpenVINO 2022部署YOLOv5推理有以下步骤: 1. 安装OpenVINO 2022:首先需要下载和安装OpenVINO 2022工具包。安装完成后,配置OpenVINO的环境变量等设置。 2. 模型转换:YOLOv5的原始模型是使用PyTorch训练的,为了能够在OpenVINO中进行推理,需要将模型转换为OpenVINO支持的IR(Intermediate Representation)格式。可以使用OpenVINO提供的Model Optimizer工具来完成模型转换,具体命令如下: ```bash mo.py --input_model <path_to_yolov5_model> --model_name yolov5 -o <output_dir> --data_type FP16 ``` 这里的`<path_to_yolov5_model>`是原始YOLOv5模型的路径,`<output_dir>`是转换后的IR模型的输出目录,`--data_type`指定了推理过程中使用的数据精度,可以根据需求选择FP16或FP32。 3. 推理应用开发:根据使用场景和需求,使用OpenVINO提供的API开发推理应用程序。可以使用C++、Python等主流编程语言进行开发OpenVINO提供了相应的API接口供开发者使用。开发过程中需要加载转换后的模型文件,并进行图像的预处理、推理计算等操作。 4. 编译和优化:使用OpenVINO提供的Model Optimizer工具,可以对推理应用进行编译和优化,以提高推理性能。具体命令如下: ```bash mo.py --input_model <model_xml> --model_name yolov5 --output_dir <output_dir> --data_type FP16 --batch 1 ``` 这里的`<model_xml>`是前面转换得到的IR模型的路径,`<output_dir>`是优化后的模型文件的输出目录,`--batch`指定了模型的批处理大小,可以根据需求进行调整。 5. 部署和推理:在部署和推理阶段,可以将优化后的模型和开发的应用程序部署到目标设备上,并进行推理计算。OpenVINO提供了适用于多种硬件平台的推理引擎,可以选择合适的推理引擎来进行部署。 综上所述,使用OpenVINO 2022部署YOLOv5推理需要进行模型转换、推理应用开发、编译和优化等步骤。通过结合YOLOv5OpenVINO 2022,可以实现高效的目标检测应用部署和推理
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值