基于OpenCV的YOLOv5图片检测

利用OpenCV的DNN模块加载onnx模型文件进行图片检测。

1、使用的yolov5工程代码,调用export.py导出onnx模型。
2、下载opencv版本,https://opencv.org/releases/
      使用opencv版本4.5.3或以上,本文使用的opencv4.6.0        
3、使用vc2015编写使用代码。

// dnnUseOnnx.cpp : 定义控制台应用程序的入口点。#include <fstream>
#include <iostream>
#include <string>
#include <map>
#include <opencv2/opencv.hpp>struct DetectResult
{int classId;float score;cv::Rect box;
};class YOLOv5Detector
{
public:void initConfig(std::string onnxpath, int iw, int ih, float threshold, bool bIsEnableCuda);void detect(cv::Mat& frame, std::vector<DetectResult>& result);private:int input_w = 640;int input_h = 640;cv::dnn::Net net;int threshold_score = 0.25;
};void YOLOv5Detector::initConfig(std::string onnxpath, int iw, int ih, float threshold, bool bIsEnableCuda)
{this->input_w = iw;this->input_h = ih;this->threshold_score = threshold;try{this->net = cv::dnn::readNetFromONNX(onnxpath);//依据情况选定是否使用CUDAif (bIsEnableCuda){std::cout << "Attempty to use CUDA\n";net.setPreferableBackend(cv::dnn::DNN_BACKEND_CUDA);net.setPreferableTarget(cv::dnn::DNN_TARGET_CUDA_FP16);}else{std::cout << "Running on CPU\n";net.setPreferableBackend(cv::dnn::DNN_BACKEND_OPENCV);net.setPreferableTarget(cv::dnn::DNN_TARGET_CPU);}}catch (cv::Exception & e) {printf("exception %s\n", e.err.c_str());}
}void YOLOv5Detector::detect(cv::Mat& frame, std::vector<DetectResult>& results)
{// 图象预处理 - 格式化操作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);if (frame.channels() == 1){cv::cvtColor(frame, frame, cv::COLOR_GRAY2BGR);}cv::Rect roi(0, 0, w, h);frame.copyTo(image(roi));float x_factor = image.cols / 640.0f;float y_factor = image.rows / 640.0f;cv::Mat blob = cv::dnn::blobFromImage(image, 1 / 255.0, cv::Size(this->input_w, this->input_h), cv::Scalar(0, 0, 0),true, false);this->net.setInput(blob);cv::Mat preds = this->net.forward("output0");//outputname,使用Netron看一下输出的名字,一般为output0或者output//如果preds里有Mat的维数大于2,那么设断点调试的时候,可以看到rows和cols都等于-1,当Mat的dims>2时,想要访问Mat的高和宽,可以通过size属性获取。如下:printf("output:%d,%d,%d\n", preds.size[0], preds.size[1], preds.size[2]);//打印输出:output:1,25200,85//YOLOV5的输出1,25200,85如何理解和解析//1、25200代表着检测框的数量,比如我们取出第一个检测框a,也就是[1,1,85],取出来之后我们解析85,前五个为box的中点坐标、长宽值以及置信,后面80我们取Max(80个类别)中最大值,类别的处于多少行对应于label class.txt别中的类是哪一类别。cv::Mat det_output(preds.size[1], preds.size[2], CV_32F, preds.ptr<float>());float confidence_threshold = 0.5;std::vector<cv::Rect> boxes;boxes.clear();std::vector<int> classIds;classIds.clear();std::vector<float> confidences;confidences.clear();for (int i = 0; i < det_output.rows; i++){float confidence = det_output.at<float>(i, 4);if (confidence < 0.45){continue;}cv::Mat classes_scores = det_output.row(i).colRange(5, preds.size[2]);//colRange(5, num_class);num_class:最大分类数cv::Point classIdPoint;double score;minMaxLoc(classes_scores, 0, &score, 0, &classIdPoint);// 置信度 0~1之间if (score > this->threshold_score){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 * confidence);}}// NMSstd::vector<int> indexes;cv::dnn::NMSBoxes(boxes, confidences, 0.25, 0.45, indexes);for (size_t i = 0; i < indexes.size(); i++){DetectResult dr;int index = indexes[i];int idx = classIds[index];dr.box = boxes[index];dr.classId = idx;dr.score = confidences[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);results.push_back(dr);}std::ostringstream ss;std::vector<double> layersTimings;double freq = cv::getTickFrequency() / 1000.0;double time = net.getPerfProfile(layersTimings) / freq;ss << "FPS: " << 1000 / time << " ; time : " << time << " ms";putText(frame, ss.str(), cv::Point(20, 40), cv::FONT_HERSHEY_PLAIN, 2.0, cv::Scalar(255, 0, 0), 2, 8);
}std::map<int, std::string> classNames = { { 0, "person" },{ 1, "bicycle" },{ 2, "car" },{ 3, "motorcycle" } ,{ 4, "airplane" } ,{ 5, "bus" },{ 6, "train" },{ 7, "truck" },{ 8, "boat" },{ 9, "traffic light" },
{ 10, "fire hydrant" },{ 11, "stop sign'" },{ 12, "parking meter" },{ 13, "bench" } ,{ 14, "bird" } ,{ 15, "cat" },{ 16, "dog" },{ 17, "horse" },{ 18, "sheep" },{ 19, "cow" }, 
{ 20, "elephant" },{ 21, "bear" },{ 22, "zebra" },{ 23, "giraffe" } ,{ 24, "backpack" } ,{ 25, "umbrella" },{ 26, "handbag" },{ 27, "tie" },{ 28, "suitcase" },{ 29, "frisbee" },
{ 30, "skis" },{ 31, "snowboard" },{ 32, "sports ball" },{ 33, "kite" } ,{ 34, "baseball bat" } ,{ 35, "baseball glove" },{ 36, "skateboard" },{ 37, "surfboard" },{ 38, "tennis racket" },{ 39, "bottle" },
{ 40, "wine glass" },{ 41, "cup" },{ 42, "fork" },{ 43, "knife" } ,{ 44, "spoon" } ,{ 45, "bowl" },{ 46, "banana" },{ 47, "apple" },{ 48, "sandwich" },{ 49, "orange" },
{ 50, "broccoli" },{ 51, "carrot" },{ 52, "hot dog" },{ 53, "pizza" } ,{ 54, "donut" } ,{ 55, "cake" },{ 56, "chair" },{ 57, "couch" },{ 58, "potted plant" },{ 59, "bed" },
{ 60, "dining table" },{ 61, "toilet" },{ 62, "tv" },{ 63, "laptop" } ,{ 64, "mouse" } ,{ 65, "remote" },{ 66, "keyboard" },{ 67, "cell phone" },{ 68, "microwave" },{ 69, "oven" },
{ 70, "toaster" },{ 71, "sink" },{ 72, "refrigerator" },{ 73, "book" } ,{ 74, "clock" } ,{ 75, "vase" },{ 76, "scissors" },{ 77, "teddy bear" },{ 78, "hair drier" },{ 79, "toothbrush" }
};int main(int argc, char* argv[])
{std::shared_ptr<YOLOv5Detector> detector = std::make_shared<YOLOv5Detector>();detector->initConfig(R"(D:\python-project\yolov5\yolov5s.onnx)", 640, 640, 0.25f, false);cv::Mat frame = cv::imread(R"(D:\python-project\yolov5\data\images\bus.jpg)");std::vector<DetectResult> results;detector->detect(frame, results);for (DetectResult& dr : results){cv::Rect box = dr.box;cv::putText(frame, classNames[dr.classId]+ " "+ std::to_string(dr.score), cv::Point(box.tl().x, box.tl().y - 10), cv::FONT_HERSHEY_SIMPLEX,.5, cv::Scalar(0, 0, 0));}cv::imshow("OpenCV-DNN-yolov5", frame);cv::waitKey();results.clear();
}

运行效果:

注意事项:

1)、readNetFromONNX加载onnx模型出错。 interp_mode != "asymmetric",这个错误信息表明你在使用OpenCV的readNetFromONNX函数加载ONNX模型时,模型中的某些节点的插值模式(interp_mode)不是"asymmetric"。
解决方法:使用opencv版本4.5.3或以上,本文使用的opencv4.6.0
2)、监测到目标比yolov5工程detect.py推理出来的目标少。
解决方法:det_output.row(i).colRange(5, num_class);num_class:最大分类数

cv::Mat classes_scores = det_output.row(i).colRange(5, preds.size[2]);

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

css设置overflow:hiden行内元素会发生偏移的现象

父级元素包含几个行内元素 <div id"box"><p><span>按钮</span><span>测试文字文字文字测试文字文字文字</span><span>看这里</span></p></div>#box p{width: 800px;font-size: 30px;}#box p span{disp…

VMware启动时报错: “另一个程序已锁定文件的一部分,进程无法访问” 分析记录

项目场景&#xff1a; VMware启动时报错: “另一个程序已锁定文件的一部分,进程无法访问” 问题描述 VMware启动时报错: “另一个程序已锁定文件的一部分,进程无法访问” 原因分析&#xff1a; 虚拟机开启后会对部分文件继续加密&#xff0c;关闭时虚拟机会自动对其解密&…

css设置动态数组渲染及中间线平均分开显示

效果图&#xff1a; <template><div class"container"><div v-for"(item, index) in items" :key"index" class"item-container"><span class"item">{{ item }}</span><span v-if"in…

二级C语言2023-9易错题

1 二叉树结点数计算&#xff1a; 一棵二叉树有10个度为1的结点&#xff0c;7个度为2的结点&#xff0c;则该二叉树共有____个结点。 解&#xff1a; 2 指针&#xff1a; 有以下程序 #inctude<stdio.h> #include<stdlib.h> main() { int *a&#xff0c;*b&…

Unity数据持久化4——2进制

概述 基础知识 各类型数据转字节数据 文件操作相关 文件相关 文件流相关 文件夹相关 练习题 using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Text; using UnityEngine;public class Exercises1 : MonoBehaviour {/…

6. Python 输出长方形,直角三角形,等腰三角形

使用Python输出长方形&#xff0c;直角三角形&#xff0c;等腰三角形 这里主要使用python语言里的循环知识&#xff0c;具体说是Python语言里的循环嵌套&#xff0c; 注意&#xff0c;在实际使用中&#xff0c;循环嵌套一般最多到达3层&#xff0c;嵌套太多会影响到程序执行。…

详解ChatBI Agent架构:打造高效数据统计系统

随着人工智能技术的迅猛发展&#xff0c;智能对话系统在各行各业中的应用越来越广泛。本文将介绍一种名为ChatBI Agent的架构设计&#xff0c;并以电信运营商系统的经分数据统计Agent为案例&#xff0c;结合具体的代码实现&#xff0c;帮助读者了解这一系统的设计理念和实现方式…

新产品,推出 MLX90372GVS 第三代 Triaxis® 位置传感器 IC,适用于汽车和工业系统(MLX90372GVS-ACE-308)

Triaxis 旋转和线性位置传感器IC&#xff1a; MLX90372GVS-ACE-103 MLX90372GVS-ACE-108 MLX90372GVS-ACE-301 MLX90372GVS-ACE-200 MLX90372GVS-ACE-208 MLX90372GVS-ACE-303 MLX90372GVS-ACE-300 MLX90372GVS-ACE-350 MLX90372GVS-ACE-100 MLX90372GVS-ACE-101 MLX90372GVS-…

6.C_数据结构_查询_哈希表

概述 哈希表的查询是通过计算的方式获取数据的地址&#xff0c;而不是依次比较。在哈希表中&#xff0c;有一个键值key&#xff0c;通过一些函数转换为哈希表的索引值。 其中&#xff1a;这个函数被称为哈希函数、散列函数、杂凑函数&#xff0c;记为&#xff1a;H(key) 哈希…

使用 nvm 管理 node 版本:如何在 macOS 和 Windows 上安装使用nvm

&#x1f525; 个人主页&#xff1a;空白诗 文章目录 一、引言二、nvm的安装与基本使用2.1 macOS安装nvm2.1.1 使用 curl 安装2.1.2 使用 Homebrew 安装 2.2 Windows安装nvm2.2.1 下载 nvm-windows2.2.2 安装 nvm-windows 2.3 安装node2.4 切换node版本 三、常见问题及解决方案…

STM32读写内部flash

一.简介 在 STM32 芯片内部有一个 FLASH 存储器&#xff0c;它主要用于存储代码&#xff0c;我们在电脑上编写好应用程序后&#xff0c;使用下载器把编译后的代码文件烧录到该内部 FLASH 中&#xff0c;由于 FLASH 存储器的内容在掉电后不会丢失&#xff0c;芯片重新上电复位后…

【redis-01】redis基本数据类型和使用场景

redis系列整体栏目 内容链接地址【一】redis基本数据类型和使用场景https://zhenghuisheng.blog.csdn.net/article/details/142406325 redis基本数据类型和使用场景 一&#xff0c;redis基本数据类型和使用场景1&#xff0c;String数据类型2&#xff0c;Hash数据类型3&#xff…

Linux top命令详解与重点内容说明

文章目录 重点说明基本信息进程(任务)信息cpu占用信息%Cpu(s)内存信息交换内存信息每列含义说明交互命令多窗口模式颜色配置命令参数 重点说明 top命令非常强大&#xff0c;也非常复杂&#xff0c;很难面面俱到&#xff0c;也没有必要&#xff0c;这篇文章的目的是介绍重点&am…

2024华为杯研究生数学建模竞赛(研赛)选题建议+初步分析

提示&#xff1a;C君认为的难度&#xff1a;DE<C<F&#xff0c;开放度&#xff1a;CDE>F。 华为专项的题目&#xff08;A、B题&#xff09;暂不进行选题分析&#xff0c;不太建议大多数同学选择&#xff0c;对自己专业技能有很大自信的可以选择华为专项的题目。后续会…

英集芯IP5912:集成开关充电功能的低功耗8位POWER MCU芯片

英集芯IP5912是一款功能丰富的、集成了降压充电管理功能的8位MCU芯片&#xff0c;它内置了一个5V输入的同步降压充电DC-DC&#xff0c;功率管也是内置的&#xff0c;同时提供最大1.5A的充电电流。封装方式采用SOP16&#xff0c;方案应用时只需要很少的外围器件&#xff0c;就可…

【多线程】CAS的原理及应用,看这篇文章就够啦

&#x1f490;个人主页&#xff1a;初晴~ &#x1f4da;相关专栏&#xff1a;多线程 / javaEE初阶 一、CAS概述 CAS&#xff08;Compare and Swap&#xff09;&#xff0c;中文译为 “比较并交换” &#xff0c;是一种无锁算法中常用的原子操作。CAS通常用于实现线程之间的同…

linux之nacos安装

1:下载nacos安装包 方式一、进入官网下载压缩包 官网地址 找到nacos-server-2.0.1.tar.gz 点击进行下载&#xff0c;下载完成后上传到服务器中。 方式二、使用wget命令下载 也有两种方式&#xff1a;第一种下载速度较慢 wget https://github.com/alibaba/nacos/releases/downl…

Zookeeper学习

文章目录 学习第 1 章 Zookeeper 入门1.1 概述Zookeeper工作机制 1.2 特点1.3 数据结构1.4 应用场景统一命名服务统一配置管理统一集群管理服务器动态上下线软负载均衡 1.5 下载zookeeper 第 2 章 Zookeeper 本地安装2.1 本地模式安装安装前准备配置修改操作 Zookeeper本地安装…

【React】React18.2.0核心源码解读

前言 本文使用 React18.2.0 的源码&#xff0c;如果想回退到某一版本执行git checkout tags/v18.2.0即可。如果打开源码发现js文件报ts类型错误请看本人另一篇文章&#xff1a;VsCode查看React源码全是类型报错如何解决。 阅读源码的过程&#xff1a; 下载源码 观察 package…

uniapp使用uview2上传图片功能

官网地址Upload 上传 | uView 2.0 - 全面兼容 nvue 的 uni-app 生态框架 - uni-app UI 框架 前提&#xff0c;需要下载vuew2插件 <view class"upload"><view class"u-demo-block__content"><view class"u-page__upload-item"&…