使用Openvino部署C++的Yolov5时类别信息混乱问题记录

embedded/2024/10/18 12:24:31/

使用Openvino部署C++的Yolov5时类别信息混乱问题记录

简单记录一下。

一、问题描述

问题描述:在使用Yolov5的onnx格式模型进行C++的Openvino进行模型部署时,通过读取classes.txt获得类别信息时,出现模型类别混乱,或者说根本就不给图像赋予类别标签的情况。
在这里插入图片描述

二、解决办法

通过debug程序,发现是读取txt文件时的问题,读入txt文件时,会读出几行空白的数据。
在这里插入图片描述
最终发现原因是classes.txt文件中,多了几个空白的换行。需要尽量留意,删除掉空白的换行

三、部署测试代码

三个部分,需要提取配置好opencv和openvino

1.main.cpp
#include <opencv2/opencv.hpp>  
#include <boost/filesystem.hpp>  
#include <iostream>  
#include <string>  
#include "yolov5vino.h"namespace fs = boost::filesystem;
YOLOv5VINO yolov5VINO;int main() {std::string sourceDir = "D:/work/C++Code/Yolov5Openvino/Test/testimgs";std::string destDir = "D:/work/C++Code/Yolov5Openvino/Test/output";std::string ModelPath = "D:/work/C++Code/Yolov5Openvino/Test/best.onnx";std::string ClassesPath = "D:/work/C++Code/Yolov5Openvino/Test/classes.txt";yolov5VINO.init(ModelPath, ClassesPath);// 确保目标目录存在  if (!fs::exists(destDir)) {fs::create_directories(destDir);}// 遍历源目录中的所有文件  for (fs::directory_iterator end, dir(sourceDir); dir != end; ++dir) {if (fs::is_regular_file(dir->status())) {std::string filePath = dir->path().string();std::string fileName = dir->path().filename().string();// 读取图片  cv::Mat img = cv::imread(filePath, cv::IMREAD_COLOR);if (img.empty()) {std::cerr << "Failed to load image: " << filePath << std::endl;continue;}std::vector<Detection> outputs;yolov5VINO.detect(img, outputs);yolov5VINO.drawRect(img, outputs);// 构造目标文件路径  std::string destFilePath = destDir + "/" + fileName;// 保存图  if (!cv::imwrite(destFilePath, img)) {std::cerr << "Failed to save image: " << destFilePath << std::endl;}else {std::cout << "Saved image: " << destFilePath << std::endl;}}}return 0;
}
2.Yolv5nivo.h
#pragma once
#ifndef YOLOV5VINO_H
#define YOLOV5VINO_H
#include <fstream>
#include <opencv2/opencv.hpp>
#include <inference_engine.hpp>
#define NOT_NCS2
using namespace std;
using namespace InferenceEngine;struct Detection
{int class_id;float confidence;cv::Rect box;
};class YOLOv5VINO
{
public:YOLOv5VINO();~YOLOv5VINO();void init(string modelPath, string classPath);cv::Mat formatYolov5(const cv::Mat& source);void detect(cv::Mat& image, vector<Detection>& outputs);void drawRect(cv::Mat& image, vector<Detection>& outputs);void loadClassList(string classPath);
private:float m_scoreThreshold = 0.5;float m_nmsThreshold = 0.6;float m_confThreshold = 0.5;//"CPU","GPU","MYRIAD"
#ifdef NCS2const std::string m_deviceName = "MYRIAD";const std::string m_modelFilename = "configFiles/yolov5sNCS2.xml";
#elseconst std::string m_deviceName = "CPU";const std::string m_modelFilename = "best.onnx";
#endif // NCS2const std::string m_classfile = "classes.txt";size_t m_numChannels = 3;size_t m_inputH = 416;size_t m_inputW = 416;size_t m_imageSize = 0;std::string m_inputName = "";std::string m_outputName = "";const vector<cv::Scalar> colors = { cv::Scalar(255, 255, 0), cv::Scalar(0, 255, 0), cv::Scalar(0, 255, 255), cv::Scalar(255, 0, 0) };InferRequest m_inferRequest;Blob::Ptr m_inputData;public:vector<std::string> m_classNames;//const vector<std::string> m_classNames = { "138A","8151","B1100","JH8161","RE85","S22","KA90","T105","TX2295" };// const vector<string> m_classNames = { "person", "bicycle", "car", "motorcycle", "airplane", "bus", "train", "truck", "boat", "traffic light" };
};
#endif
3.yolov5vino.cpp
#include "yolov5vino.h"YOLOv5VINO::YOLOv5VINO()
{
}YOLOv5VINO::~YOLOv5VINO()
{
}void YOLOv5VINO::init(string modelPath, string classPath)
{InferenceEngine::Core ie;InferenceEngine::CNNNetwork network = ie.ReadNetwork(modelPath);InputsDataMap inputs = network.getInputsInfo();OutputsDataMap outputs = network.getOutputsInfo();for (auto item : inputs){m_inputName = item.first;auto input_data = item.second;input_data->setPrecision(Precision::FP32);input_data->setLayout(Layout::NCHW);input_data->getPreProcess().setColorFormat(ColorFormat::RGB);std::cout << "input name = " << m_inputName << std::endl;}for (auto item : outputs){auto output_data = item.second;output_data->setPrecision(Precision::FP32);m_outputName = item.first;std::cout << "output name = " << m_outputName << std::endl;}auto executable_network = ie.LoadNetwork(network, m_deviceName);m_inferRequest = executable_network.CreateInferRequest();m_inputData = m_inferRequest.GetBlob(m_inputName);m_numChannels = m_inputData->getTensorDesc().getDims()[1];m_inputH = m_inputData->getTensorDesc().getDims()[2];m_inputW = m_inputData->getTensorDesc().getDims()[3];m_imageSize = m_inputH * m_inputW;loadClassList(classPath);}void YOLOv5VINO::loadClassList(string classPath)
{std::ifstream ifs(classPath);std::string line;while (getline(ifs, line)){m_classNames.push_back(line);}ifs.close();
}cv::Mat YOLOv5VINO::formatYolov5(const cv::Mat& source)
{int col = source.cols;int row = source.rows;int max = MAX(col, row);cv::Mat result = cv::Mat::zeros(max, max, CV_8UC3);source.copyTo(result(cv::Rect(0, 0, col, row)));return result;
}void YOLOv5VINO::detect(cv::Mat& image, vector<Detection>& outputs)
{cv::Mat input_image = formatYolov5(image);cv::Mat blob_image;cv::resize(input_image, blob_image, cv::Size(m_inputW, m_inputH));cv::cvtColor(blob_image, blob_image, cv::COLOR_BGR2RGB);float* data = static_cast<float*>(m_inputData->buffer());for (size_t row = 0; row < m_inputH; row++) {for (size_t col = 0; col < m_inputW; col++) {for (size_t ch = 0; ch < m_numChannels; ch++) {
#ifdef NCS2data[m_imageSize * ch + row * m_inputW + col] = float(blob_image.at<cv::Vec3b>(row, col)[ch]);
#elsedata[m_imageSize * ch + row * m_inputW + col] = float(blob_image.at<cv::Vec3b>(row, col)[ch] / 255.0);
#endif // NCS2}}}auto start = std::chrono::high_resolution_clock::now();m_inferRequest.Infer();auto output = m_inferRequest.GetBlob(m_outputName);const float* detection_out = static_cast<PrecisionTrait<Precision::FP32>::value_type*>(output->buffer());//维度信息const SizeVector outputDims = output->getTensorDesc().getDims();//1,6300[25200],9float x_factor = float(input_image.cols) / m_inputW;float y_factor = float(input_image.rows) / m_inputH;float* dataout = (float*)detection_out;const int dimensions = outputDims[2];const int rows = outputDims[1];vector<int> class_ids;vector<float> confidences;vector<cv::Rect> boxes;for (int i = 0; i < rows; ++i){float confidence = dataout[4];if (confidence >= m_confThreshold){float* classes_scores = dataout + 5;cv::Mat scores(1, m_classNames.size(), CV_32FC1, classes_scores);cv::Point class_id;double max_class_score;minMaxLoc(scores, 0, &max_class_score, 0, &class_id);if (max_class_score > m_scoreThreshold){confidences.push_back(confidence);class_ids.push_back(class_id.x);float x = dataout[0];float y = dataout[1];float w = dataout[2];float h = dataout[3];int left = int((x - 0.5 * w) * x_factor);int top = int((y - 0.5 * h) * y_factor);int width = int(w * x_factor);int height = int(h * y_factor);boxes.push_back(cv::Rect(left, top, width, height));}}dataout += dimensions;}vector<int> nms_result;cv::dnn::NMSBoxes(boxes, confidences, m_scoreThreshold, m_nmsThreshold, nms_result);for (int i = 0; i < nms_result.size(); i++){int idx = nms_result[i];Detection result;result.class_id = class_ids[idx];result.confidence = confidences[idx];result.box = boxes[idx];outputs.push_back(result);}std::sort(outputs.begin(), outputs.end(), [](const Detection& a, const Detection& b) {return a.confidence > b.confidence; // 从大到小排序  });
}void YOLOv5VINO::drawRect(cv::Mat& image, vector<Detection>& outputs)
{int detections = outputs.size();for (int i = 0; i < detections; ++i){auto detection = outputs[i];auto box = detection.box;auto classId = detection.class_id;const auto color = colors[classId % colors.size()];rectangle(image, box, color, 3);rectangle(image, cv::Point(box.x, box.y - 40), cv::Point(box.x + box.width, box.y), color, cv::FILLED);putText(image, m_classNames[classId].c_str(), cv::Point(box.x, box.y - 5), cv::FONT_HERSHEY_SIMPLEX, 1.5, cv::Scalar(0, 0, 0), 2);}}

http://www.ppmy.cn/embedded/88947.html

相关文章

PHP教育培训小程序系统源码

&#x1f680;【学习新纪元】解锁教育培训小程序的无限可能✨ &#x1f4da; 引言&#xff1a;教育培训新风尚&#xff0c;小程序来引领&#xff01; Hey小伙伴们&#xff0c;是不是还在为找不到合适的学习资源而烦恼&#xff1f;或是厌倦了传统教育模式的单调&#xff1f;今…

【2024蓝桥杯/C++/B组/小球反弹】

题目 分析 Sx 2 * k1 * x; Sy 2 * k2 * y; &#xff08;其中k1, k2为整数&#xff09; Vx * t Sx; Vy * t Sy; k1 / k2 (15 * y) / (17 * x)&#xff1b; 目标1&#xff1a;根据k1与k2的关系&#xff0c;找出一组最小整数组&#xff08;k1, k2&#xff09;&#xff…

面试经验|问题

请谈一下对公司的看法&#xff0c;为什么想来工作&#xff1f;我这样相信对这个职位你是最好的人选&#xff1f;你为何要跳槽&#xff1f;你最大的优点和缺点分别是什么&#xff1f;你有哪些兴趣爱好或具备什么资格证书&#xff1f;工作中你所取得的最大成就是什么&#xff1f;…

vim、sublime、notepad文本编辑器的使用

VIM&#xff1a; Windows上配置gvim并作为C和C的IDE Windows上配置gvim并作为C和C的IDE | Reasuon sublime notepad

rust常用的宏使用记录(九)

matches! 宏使用 matches! 是 Rust 标准库中一个非常有用的宏&#xff0c;它允许你方便地匹配一个表达式的结果是否符合某个模式。它的基本用法如下&#xff1a;matches!(expression, pattern) 这个宏返回一个布尔值&#xff0c;如果 expression 匹配 pattern&#xff0c;则返回…

材质球向shader传值失败

unity中导入spine模型&#xff0c;当模型挂载SkeletonMecanim组件后&#xff0c;发现材质球向shader传值失败&#xff0c;改为SetPropertyBlock后可行。 //spine模型使用材质球传参数&#xff0c;当spine模型上挂载有SkeletonMecanim的情况下&#xff0c;会传值失败!!!!// for…

dpdk实现udp协议栈

使用DPDK实现UDP用户态协议栈&#xff0c;实现流程中包括&#xff1a; 三类线程 1、收发包线程 2、用户态协议栈线程 3、udp服务端线程 两类缓冲区&#xff1a; 1、协议栈收包缓冲区和协议栈发包缓冲区 2、udp收包缓冲区和udp发包缓冲区 协议栈缓冲区中存储的数据是str…

从零开始学习黑客技术,看这一篇就够了

黑客&#xff0c;对于很多人来说&#xff0c;是一个神秘的代名词&#xff0c;加之影视作品夸张的艺术表现&#xff0c;使得黑客这个本来只专注于技术的群体&#xff0c;散发出亦正亦邪的神秘色彩。 黑客源自英文hacker一词&#xff0c;最初曾指热心于计算机技术、水平高超的电…