当前位置: 首页 > news >正文

opencv dnn模块 示例(20) 目标检测 object_detection 之 yolor

文章目录

  • 1、论文介绍
    • 1.1、YOLOR思想动机
    • 1.2、隐式知识学习
      • 1.2.1、隐式知识如何工作
      • 1.2.2、隐式知识统一网络建模
    • 1.3、实验
    • 1.4、总结
  • 2、测试
    • 2.1、opencv dnn
      • 2.1.1、代码
      • 2.1.2、结果
    • 2.2、测试效率

YOLOR出自论文You Only Learn One Representation: Unified Network for Multiple Tasks,受人类学习方式(使用五官,通过常规和潜意识学习,总结丰富的经验并编码存储,进而处理已知或未知的信息)的启发,论文提出了一个统一的网络来同时编码显式知识和隐式知识,在网络中执行了kernel space alignment(核空间对齐)、prediction refinement(预测细化)和 multi-task learning(多任务学习),同时对多个任务形成统一的表示。结果表明神经网络中引入隐式知识有助于所有任务的性能提升,进一步的分析发现隐式表示之所以能带来性能提升,是因为其具备了捕获不同任务的物理意义的能力。

1、论文介绍

paper: https://arxiv.org/abs/2105.04206
code: https://github.com/WongKinYiu/yolor

1.1、YOLOR思想动机

图1:人可以根据同一幅输入图像回答不同问题,本文也旨在训练一个单一的神经网络来服务于多个任务

如图1所示,人可以从多个角度来分析同一个目标,然而通常训练CNN时只给予了一个角度,也就是说针对某一个任务得到的CNN特征很难适用于其他问题。作者认为造成上述问题的原因主要是模型只提取了神经元特征而丢弃了隐式知识的学习运用,然而就像人脑一样隐式知识对分析各种各样的任务是非常有用的。

人类对隐式知识的学习通常通过潜意识,然而并没有系统的定义怎样学习和获得隐式知识。对于神经网络而言,一般将浅层特征定义为显式知识,深层特征定义为隐式知识。本文将直接可观察的知识定义为显式知识,隐藏在神经网络中且无法观察的知识定义为隐式知识

图2:多目的神经网络架构。(a)不同任务对应不同模型;(b)不同任务共享骨干网络,使用不同的输出头;(c)本文提出的统一网络:融合显式知识和隐式知识的一个表征服务多个任务。

如图2所示,提出了一个统一的网络来集成显式知识和隐式知识,通过学习统一的表达,使得各个子表示能够适用于不同任务。基于前人工作的理论基础,本文结合压缩感知和深度学习来构建统一网络。

本文主要贡献如下:

  1. 提出了一个可同时完成多种任务的统一网络,它通过融合显式知识和隐式知识学习一个可以完成多个任务的统一表征,提出的网络可以有效的提升模型的表现,仅增加千分之一不到的计算成本;

  2. 通过 kernel space alignment(核空间对齐)、prediction refinement(预测细化)和 multi-task learning(多任务学习)来完成隐式知识的学习,并验证了其有效性;

  3. 分别讨论了隐式知识的建模方式,包括向量、神经网络、矩阵分解,并验证了这些方式的有效性;

  4. 证实了所提出的内隐表征学习方法能够准确地对应于特定的物理特征,并以视觉的方式进行了呈现;还证实了如果算子符合目标的物理意义,它可以用来整合隐式知识和显式知识,并会产生乘数效应;

  5. 与SOTA比较,YOLOR能够实现和目标检测Scaled-YOLOv4-P7一样的精度,但是推理速度快了88%。

1.2、隐式知识学习

1.2.1、隐式知识如何工作

流形空间约简
核空间对齐
更多功能和处理方式

1.2.2、隐式知识统一网络建模

隐式知识的表示
Unified Networks:
隐式知识的建模
向量/矩阵/张量
矩阵分解
训练
推理

1.3、实验

3.1 实验设置

3.2 FPN特征对齐
3.3 目标检测预测细化

3.4 多任务规范表征

3.5 隐式知识建模不同算子比较

3.6 隐式知识建模不同方式比较

3.7 隐式知识模型分析

3.8 隐式知识提升目标检测

1.4、总结

2、测试

这里以 yolor-p6-640-640 进行测试。网络模型可以看到,输出一共有4个,实际是4个尺度上的结果,最终通过reshape和concat合并成一个输出(输出格式与yolov5一致)。
在这里插入图片描述

2.1、opencv dnn

2.1.1、代码

使用和yolov5相同的测试代码。

#pragma once#include "opencv2/opencv.hpp"#include <fstream>
#include <sstream>#include <random>using namespace cv;
using namespace dnn;float inpWidth;
float inpHeight;
float confThreshold, scoreThreshold, nmsThreshold;
std::vector<std::string> classes;
std::vector<cv::Scalar> colors;bool letterBoxForSquare = true;cv::Mat formatToSquare(const cv::Mat &source);void postprocess(Mat& frame, cv::Size inputSz, const std::vector<Mat>& out, Net& net);void drawPred(int classId, float conf, int left, int top, int right, int bottom, Mat& frame);std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<int> dis(100, 255);int testYoloR()
{// 根据选择的检测模型文件进行配置 confThreshold = 0.25;scoreThreshold = 0.45;nmsThreshold = 0.5;float scale = 1 / 255.0;  //0.00392Scalar mean = {0,0,0};bool swapRB = true;inpWidth = 640;inpHeight = 640;String modelPath = R"(E:\DeepLearning\yolor\yolor-p6-640-640.onnx)";String configPath;String framework = "";//int backendId = cv::dnn::DNN_BACKEND_OPENCV;//int targetId = cv::dnn::DNN_TARGET_CPU;int backendId = cv::dnn::DNN_BACKEND_CUDA;int targetId = cv::dnn::DNN_TARGET_CUDA;  String classesFile = std::string(R"(\data\coco.names)");// Open file with classes names.if(!classesFile.empty()) {const std::string& file = classesFile;std::ifstream ifs(file.c_str());if(!ifs.is_open())CV_Error(Error::StsError, "File " + file + " not found");std::string line;while(std::getline(ifs, line)) {classes.push_back(line);colors.push_back(cv::Scalar(dis(gen), dis(gen), dis(gen)));}}// Load a model.Net net = readNet(modelPath, configPath, framework);net.setPreferableBackend(backendId);net.setPreferableTarget(targetId);//std::vector<String> outNames = net.getUnconnectedOutLayersNames();std::vector<String> outNames{"output"};{int dims[] = {1,3,inpHeight,inpWidth};cv::Mat tmp = cv::Mat::zeros(4, dims, CV_32F);std::vector<cv::Mat> outs;net.setInput(tmp);for(int i = 0; i<10; i++)net.forward(outs, outNames); // warmup}// Create a windowstatic const std::string kWinName = "Deep learning object detection in OpenCV";cv::namedWindow(kWinName, 0);// Open a video file or an image file or a camera stream.VideoCapture cap;cap.open(R"(E:\DeepLearning\yolov5\data\images\bus.jpg)");cv::TickMeter tk;// Process frames.Mat frame, blob;while(waitKey(1) < 0) {//tk.reset();//tk.start();cap >> frame;if(frame.empty()) {waitKey();break;}// Create a 4D blob from a frame.cv::Mat modelInput = frame;if(letterBoxForSquare && inpWidth == inpHeight)modelInput = formatToSquare(modelInput);blobFromImage(modelInput, blob, scale, cv::Size2f(inpWidth, inpHeight), mean, swapRB, false);// Run a model.net.setInput(blob);std::vector<Mat> outs;//tk.reset();//tk.start();auto tt1 = cv::getTickCount();net.forward(outs, outNames);auto tt2 = cv::getTickCount();tk.stop();postprocess(frame, modelInput.size(), outs, net);//tk.stop(); Put efficiency information.//std::vector<double> layersTimes;//double freq = getTickFrequency() / 1000;//double t = net.getPerfProfile(layersTimes) / freq;//std::string label = format("Inference time: %.2f ms  (%.2f ms)", t, /*tk.getTimeMilli()*/ (tt2 - tt1) / cv::getTickFrequency() * 1000);std::string label = format("Inference time: %.2f ms", (tt2 - tt1) / cv::getTickFrequency() * 1000);cv::putText(frame, label, Point(0, 15), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 0));cv::imshow(kWinName, frame);}return 0;
}cv::Mat formatToSquare(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 postprocess(Mat& frame, cv::Size inputSz, const std::vector<Mat>& outs, Net& net)
{// yolov5 has an output of shape (batchSize, 25200, 85) (Num classes + box[x,y,w,h] + confidence[c])auto tt1 = cv::getTickCount();float x_factor = inputSz.width / inpWidth;float y_factor = inputSz.height / inpHeight;std::vector<int> class_ids;std::vector<float> confidences;std::vector<cv::Rect> boxes;int rows = outs[0].size[1];int dimensions = outs[0].size[2];float *data = (float *)outs[0].data;for(int i = 0; i < rows; ++i) {float confidence = data[4];if(confidence >= confThreshold) {float *classes_scores = data + 5;cv::Mat scores(1, classes.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 > scoreThreshold) {confidences.push_back(confidence);class_ids.push_back(class_id.x);float x = data[0];float y = data[1];float w = data[2];float h = data[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));}}data += dimensions;}std::vector<int> indices;NMSBoxes(boxes, confidences, scoreThreshold, nmsThreshold, indices);auto tt2 = cv::getTickCount();std::string label = format("NMS time: %.2f ms", (tt2 - tt1) / cv::getTickFrequency() * 1000);cv::putText(frame, label, Point(0, 30), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 0));for(size_t i = 0; i < indices.size(); ++i) {int idx = indices[i];Rect box = boxes[idx];drawPred(class_ids[idx], confidences[idx], box.x, box.y,box.x + box.width, box.y + box.height, frame);}
}void drawPred(int classId, float conf, int left, int top, int right, int bottom, Mat& frame)
{rectangle(frame, Point(left, top), Point(right, bottom), Scalar(0, 255, 0));std::string label = format("%.2f", conf);Scalar color = Scalar::all(255);if(!classes.empty()) {CV_Assert(classId < (int)classes.size());label = classes[classId] + ": " + label;color = colors[classId];}int baseLine;Size labelSize = getTextSize(label, FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine);top = max(top, labelSize.height);rectangle(frame, Point(left, top - labelSize.height),Point(left + labelSize.width, top + baseLine), color, FILLED);cv::putText(frame, label, Point(left, top), FONT_HERSHEY_SIMPLEX, 0.5, Scalar());
}

2.1.2、结果

测试如图,发现误识别了一个 traffic light。对比源py测试脚本,修改 bool letterBoxForSquare = false; 将等比缩放关闭后检测正常。

在这里插入图片描述

2.2、测试效率

RTX-1080ti,i7-7700k

opencv cpu:630ms
opencv gpu :52ms
opencv gpu (fp16):793ms

以下统计时间包含: 预处理+推理+后处理
openvino(cpu):274ms
onnxruntime(gpu):30ms
tensorrt:23ms

相关文章:

opencv dnn模块 示例(20) 目标检测 object_detection 之 yolor

文章目录 1、论文介绍1.1、YOLOR思想动机1.2、隐式知识学习1.2.1、隐式知识如何工作1.2.2、隐式知识统一网络建模 1.3、实验1.4、总结 2、测试2.1、opencv dnn2.1.1、代码2.1.2、结果 2.2、测试效率 YOLOR出自论文You Only Learn One Representation: Unified Network for Mult…...

【队列的顺序表示,链式表示】

文章目录 队列的表示和实现相关术语队列的表示链队的表示链队的定义链队的初始化销毁链队列 链队列的入队出栈 队列的表示和实现 相关术语 队列&#xff08;Queue&#xff09;是仅在表尾进行插入操作&#xff0c;在表头进行删除操作的线性表。表尾即an端&#xff0c;称为队尾…...

Pydantic 实践

1. 简介 pydantic 库是一种常用的用于数据接口 schema 定义与检查的库。 通过 pydantic 库&#xff0c;我们可以更为规范地定义和使用数据接口&#xff0c;这对于大型项目的开发将会更为友好。 当然&#xff0c;除了 pydantic 库之外&#xff0c;像是 valideer 库、marshmallo…...

获取pandas中的众数

pandas.DataFrame 也有一个 mode() 方法。 以下面的 pandas.DataFrame 为例。 df pd.DataFrame({‘col1’: [‘X’, ‘X’, ‘Y’, ‘X’], ‘col2’: [‘X’, ‘Y’, ‘Y’, ‘X’]}, index[‘row1’, ‘row2’, ‘row3’, ‘row4’]) print(df) col1 col2 row1 X X row2…...

SOLIDWORKS Simulation2024仿真10大新功能

SOLIDWORKS Simulation新增功能 1. 增强型轴承接头 •通过指定压缩、拉伸和弯曲的刚度&#xff0c;轻松创建自定义轴承接头。•通过向非线性和大型位移算例添加自定义条件&#xff0c;提高模拟精度。 优点&#xff1a;使用功能强大的接口&#xff0c;更轻松 、 更 准 确 地 设…...

Java程序设计2023-第二次上机练习

这里要用到一些面向对象的基本知识 目录 7-1 伪随机数 输入格式: 输出格式: 输入样例: 输出样例: 7-2 jmu-Java-03面向对象基础-01-构造方法与toString 1.编写无参构造函数&#xff1a; 2.编写有参构造函数 3.覆盖toString函数&#xff1a; 4.对每个属性生成setter…...

如何在 uniapp 里面使用 pinia 数据持久化 (pinia-plugin-persistedstate)

想要在 uniapp 里面使用 pinia-plugin-persistedstate 会遇到的问题就是 uniapp里面没有浏览器里面的 sessionStorage localStorage 这些 api。 我们只需要替换掉 pinia-plugin-persistedstate 默认的储存 api 就可以了。使用 createPersistedState 重新创建一个实例, 把里面的…...

智慧矿山AI算法助力护帮板支护监测,提升安全与效率

在智慧矿山AI算法系列中&#xff0c;护帮板支护监测是保障矿山安全和提高生产效率的重要环节。护帮板作为矿山支护体系中的重要组成部分&#xff0c;在矿山生产中起到了关键的作用。那么&#xff0c;护帮板在哪种状态下是正常打开的呢&#xff1f;本文将对此进行介绍。 护帮板的…...

shell中的运算

目录 1.运算符号 2.运算指令 练习 1.运算符号 运算符号意义加法-减法*乘法/除法%除法后的余数**乘方自加一- -自减一<小于<小于等于>大于>大于等于等于ji ->jji*j*i->jj*i/j/i->jj/i%j%i->jj%i 2.运算指令 (()) //((a12))let //let a12 …...

【Java 进阶篇】解决Java Web应用中请求参数中文乱码问题

在Java Web应用开发中&#xff0c;处理请求参数时经常会遇到中文乱码的问题。当浏览器向服务器发送包含中文字符的请求参数时&#xff0c;如果不正确处理&#xff0c;可能会导致乱码问题&#xff0c;使得参数无法正确解析和显示。本文将详细探讨Java Web应用中请求参数中文乱码…...

51单片机-点阵屏led

代码配置 这样就能选择每一列哪个亮了 进行位选&#xff0c;段清零&#xff0c;这样就不会影响多列同时了 实现动画 1、使用文字摸提取文件&#xff0c;提取图案的16进制表示数组 offest作为偏移量&#xff0c;count作为计时。count10,偏移量加1&#xff0c;就相当于得到下一…...

Angular-03:组件模板

各种学习后的知识点整理归纳&#xff0c;非原创&#xff01; 组件模板 ① 数据绑定② 属性绑定③ 类名绑定④ 样式绑定⑤ 事件绑定⑥ 获取原生DOM对象6.1 在组件模板中获取6.2 在组件类中获取 ⑦ 双向数据绑定⑧ 内容投影8.1 select选择器8.2 单槽投影8.3 多槽投影 ⑨ 安全操作…...

mysql 操作慢查询日志

1、mysql 批量插入300w数据 CREATE PROCEDURE test_insert_200w() BEGINDECLARE i INT;SET i1;WHILE i<3000000 DOINSERT INTO shop_user (password, telephone, username) VALUES (admin, 15510304125, concat(admin, i));SET ii1;END WHILE; END; //执行sql call test_in…...

illuminate/database 使用 二

上一篇文章写怎么单独使用illuminate/database&#xff0c;这回讲下怎么整合到项目里使用。为此特意看了下laravel对其使用。本篇文章&#xff0c;参照laravel的使用&#xff0c;简单实现。 一 原理 laravel 里使用illuminate/config。 illuminate/config composer 地址&…...

二叉树的概念

文章目录 二叉树一、树的概念1.树形结构1.1. 树的特点&#xff1a;1.2 概念&#xff1a;1.3 树的表示形式 2.树的应用 二、二叉树1.二叉数的概念2.满二叉树3.完全二叉树4.二叉树的性质练习&#xff1a; 二叉树 一、树的概念 1.树形结构 1.1. 树的特点&#xff1a; 1.根节点没…...

SpringCloud之Eureka的学习【详细】

目录 服务架构演变 单体架构 分布式架构 分布式架构需要考虑的问题 微服务 架构比较 微服务技术对比 服务拆分注意事项 案例 服务远程调用 RestTemplate Eureka注册中心 RestTemplate存在的问题 服务调用考虑的问题 Eureka的作用 搭建EurekaServer 服务注册 …...

学习ftp

文章目录 一、FTP介绍二、两种模式&#xff08;主动模式和被动模式&#xff09;三、FTP配置文件详解四、实际场景举例五、黑白名单六、网络限制 一、FTP介绍 1.FTP&#xff08;File Transfer Protocol&#xff09;是一种应用广泛且古老的互联网文件传输协议。 2.主要应用于互联…...

Android笔记(九):Compose组件的状态(一)

在使用Compose定义UI界面时&#xff0c;可以发现界面的变换往往与Compose组件内部的状态相关&#xff0c;当状态值发生变化时&#xff0c;Compose构成的可组合的界面也会刷新发生相应的变化。将在本笔记中将对可组合项的状态的定义、状态提升、状态丢失和状态的保存进行简单介绍…...

3.2. onnx export multi_batch

前言 将onnx bs=1 修改为多batch操作 参考链接: https://www.cnblogs.com/tangjunjun/p/16500116.html https://blog.csdn.net/weixin_43863869/article/details/128638397?spm=1001.2101.3001.6650.3&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault…...

探索低代码PaaS平台的优势与选择原因

PaaS是一种云产品&#xff0c;它为应用程序的开发和部署提供基础结构。它提供中间件、开发工具和人工智能来创建功能强大的应用程序&#xff0c;大多数PaaS服务都与存储和网络基础架构捆绑在一起&#xff0c;就像基础架构即服务&#xff08;IaaS&#xff09;一样&#xff0c;可…...

微信小程序之bind和catch

这两个呢&#xff0c;都是绑定事件用的&#xff0c;具体使用有些小区别。 官方文档&#xff1a; 事件冒泡处理不同 bind&#xff1a;绑定的事件会向上冒泡&#xff0c;即触发当前组件的事件后&#xff0c;还会继续触发父组件的相同事件。例如&#xff0c;有一个子视图绑定了b…...

VB.net复制Ntag213卡写入UID

本示例使用的发卡器&#xff1a;https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...

多场景 OkHttpClient 管理器 - Android 网络通信解决方案

下面是一个完整的 Android 实现&#xff0c;展示如何创建和管理多个 OkHttpClient 实例&#xff0c;分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...

【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密

在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

全球首个30米分辨率湿地数据集(2000—2022)

数据简介 今天我们分享的数据是全球30米分辨率湿地数据集&#xff0c;包含8种湿地亚类&#xff0c;该数据以0.5X0.5的瓦片存储&#xff0c;我们整理了所有属于中国的瓦片名称与其对应省份&#xff0c;方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...

C# 类和继承(抽象类)

抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台

🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...

OPENCV形态学基础之二腐蚀

一.腐蚀的原理 (图1) 数学表达式&#xff1a;dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一&#xff0c;腐蚀跟膨胀属于反向操作&#xff0c;膨胀是把图像图像变大&#xff0c;而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...

vulnyx Blogger writeup

信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面&#xff0c;gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress&#xff0c;说明目标所使用的cms是wordpress&#xff0c;访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...

C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...