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

基于c++的yolov5推理之前处理详解及代码(一)

目录

一、前言:

二、关于环境安装:

三、首先记录下自己的几个问题

  问题:c++部署和python部署的区别?

四、正文开始

  4.1 图像预处理讲解

  1、BGR---->RBG

  2、等比例放缩图片(涉及到短边的填充)

  3、归一化

  4、HWC---->NCHW

  5、将图像转为一维向量格式并将整理为连续内存

  4.2图像内存开辟与传递


一、前言:

  之前实现了基于win环境中的python的加速部署过程,现在将c++实现过程进行记录,这次记录会非常详细。总的来说只要整个过程的思路捋清楚,保证思路是正确的,做起工作来就比较有方向性,开始记录。

二、关于环境安装:

  环境:wsl2+Ubuntu2004+cuda113+cudnn8.9.5.30+tensrort8.6.1.6+opencv4.2.0

  主要要安装的是cuda和cudnn和tensorrt。确定好版本,我本地cuda是11.7,cuda可以向下兼容,所以我wsl中使用11.3也是支持的。参考博客:【教程】Install NVIDIA TensorRT on WSL 在WSL上安装英伟达TensorRT_wsl tensorrt-CSDN博客,win11 WSL ubuntu安装CUDA、CUDNN、TensorRT最有效的方式-CSDN博客,这两个博客互补一下。

  tips:1、安装位置最好新建一个文件夹,放在一起,在设定环境变量的时候会方便些。

   2、opencv4版本会和libtorch1.10冲突,如果没有装libtorch之前opencv是好的,装了libtorch发现这两个库都用不了,大概率是版本冲突了(一踩坑,心态崩了一天时间,sad)但是不用libtorch也完全不影响推理。

三、首先记录下自己的几个问题

  问题:c++部署和python部署的区别?

    我最开始个人理解可能c++会更多设计自己手动开辟回收内存,在我实现c++部署之后,会过头看python实现过程,发现python也是手动开辟回收内存的,所以他们最重要的区别到底在哪里呢?

    回答:最重要的东西确实还是内存管理上,然后自然而然的会影响性能,还有系统集成中。      在内存管理方面:

        1、C++版本需要显式地管理所有资源的生命周期,包括内存分配和释放。

        2、Python版本虽然也进行了一些手动内存管理,但仍然依赖于Python的垃圾回收机制来处理大部分对象的清理。

        3、C++版本提供了更细粒度的控制,可以精确地控制何时分配和释放资源。

        4、Python版本在语法上更简洁,并且某些资源管理被抽象化,使得代码更容易编写和维护。

      性能方面:我理解在一些计算开销没有非常限制的情况下,或者执行次数不多的情况下两者区别不会拉太卡,但是涉及到性能的极致使用的情况下,肯定是c++性能要高出python。

        1、C++:通常能提供更高的性能,尤其是在低延迟场景中。直接编译为机器码,没有解释器开销。

        2、Python:有解释器开销,但在许多情况下,性能差异可能不明显,特别是当大部分计算都在GPU上进行时。

      生态集成方面:

        python更加依赖于python开发环境,而c++可以编译为动态库,限制更少一些。总的来说在工业应用中肯定吃c++更加方便些。

四、正文开始

  前处理主要分为两部分,第一部分是对image的格式的转换,即cv::imread读取上来的单张图片要转为符合深度学习torch中dataload中读取上来的nchw格式的数据。第二部分就是将这样格式的数据从cpu传输到GPU中。第二部分相对操作固定一些。

  Opencv读取图片格式转换为深度学习图片输入格式

  一般有两方面需要转换,第一方面是格式,第二方面是尺寸。一般来说应该是先进行格式转换,然后在进行尺寸变化,因为尺寸变化要是涉及到放缩的话,uint8的数据空间可能会一点,可能会有一些精度的损失。

  使用opencv中cv::imread读取上来的image一般保存在cv::Mat中,OpenCV 中的 cv::Mat 格式如下:

  1. 数据类型cv::Mat 默认使用 8 位无符号整数(CV_8U)存储图像数据。

  2. 通道顺序cv::Mat 默认使用 BGR 顺序存储图像通道。

  3. 形状cv::Mat 通常具有二维或三维矩阵结构,对应于 (height, width, channels)

  而深度学习一般需要的输入数据格式如下:

  1. 数据类型:深度学习模型通常使用 32 位浮点数(float32)存储图像数据。

  2. 通道顺序:深度学习模型通常使用 RGB 顺序存储图像通道。

  3. 形状:深度学习模型的输入形状通常为 (batch_size, channels, height, width),即 NCHW 格式。

  以上是格式方面的区别,往往还有尺寸方面的区别。yolov5一般要求输入尺寸大小为640*640大小。我们还需要将图片进行缩放。注意:是等比例缩放。

  前处理流程和代码

  4.1 图像预处理讲解

  首先创建处理图像的函数:

cv::Mat preImage(cv::Mat& rawBGRImage,int inputH, int inputW)

  我们创建一个preImage的函数,返回类型是cv::Mat类型,参数输入是一个cv::Mat类型的rawBGRImage的引用,同时输入两个整数,代表深度学习输入的大小,这里为640*640。

  第一步:

  1、BGR---->RBG

// BGR --> RGBcv::cvtColor(oriImage,image,cv::COLOR_BGR2RGB);

  2、等比例放缩图片(涉及到短边的填充)

首先获得原始图像的h和w;假设1280*1920int ori_h = oriImage.rows;int ori_w = oriImage.cols;std::cout<<"原始图片的size是"<<oriImage.size<<std::endl;
两边不一样长的图片要保证长边缩小到640,短边进行填充操作。// 取最小的因子,以保证长的一边被正确缩放,短边过度缩放可在后面使用padding填充// 这两个结果肯定小于1,使用整除会将结果截断为0double r = std::min(static_cast<double>(inputH) / ori_h, static_cast<double>(inputW) / ori_w);  std::cout<<"缩放因子 r 是"<< r <<std::endl;int new_h = std::round(ori_h * r);//四舍五入int new_w = std::round(ori_w * r);std::cout<<"新图片的size是"<<new_h <<","<<new_w<<std::endl;
计算填充大小,640减去新图像的边长//计算padding的大小,int dh = inputH - new_h;int dw = inputW - new_w;std::cout<<"需要填充的size是"<<dh <<","<<dw<<std::endl;// 使用双线性插值将图像进行等比例缩放cv::resize(image,image,cv::Size(new_h,new_w),0, 0, cv::INTER_LINEAR);
此时得到了一幅(427,640)的图像,需要对h边进行填充 //判断是否需要填充   if(dh > 0 || dw > 0){cv::resize(image,image,cv::Size(new_h,new_w),0, 0, cv::INTER_LINEAR);
计算填充的像素// Pad the short side with (128,128,128)int top = dh / 2;int bottom = dh - top;int left = dw / 2;int right = dw - left;std::cout<<"方框是"<<top <<","<<bottom<<","<<left<<","<<right<<std::endl;
进行填充,其中top,bottom,left,right等代表填充到图像上下左右的像素行数//扩充边界cv::copyMakeBorder(image, image, left, right, top, bottom, cv::BORDER_CONSTANT, cv::Scalar(128, 128, 128));std::cout<<"扩充边界之后的图片的size是"<<image.size<<std::endl;}
得到一幅填充到640*640大小的图像

  3、归一化

image.convertTo(image, CV_32F); //自动转,如果原图是32f,只拷贝,不做转换。image /= 255.0; // 8u转32f之后,原始像素值还是不变的,只是可表示范围变大了。

  4、HWC---->NCHW

// HWC to CHW format:并处理成cv中的dnn多维格式数据,类似于tensor?cv::Mat imageCHW;cv::dnn::blobFromImage(image, imageCHW, 1.0, cv::Size(), cv::Scalar(), false, false);//这种缩放会影响图像精度//该函数默认bs维度=1。cv::dnn::blobFromImages函数可以自由设定bs维度的值std::cout << "NCHW shape: " << imageCHW.size << std::endl;

    函数介绍:

    cv::dnn::blobFromImage 函数是 OpenCV 中的一个实用工具,用于将图像转换为深度学习模型所需的多维格式(通常是 NCHW,即 batch size、channels、height、width)。这是深度学习中常用的数据格式。

cv::Mat blobFromImage(const cv::Mat& image, //输入图像double scalefactor = 1.0, //缩放因子,用于缩放图像的每个像素值。默认值是 1.0const cv::Size& size = cv::Size(),//目标图像的大小。cv::Size(width, height) 格式。如果为 Size(),则保持原始图像大小。const cv::Scalar& mean = cv::Scalar(),//用于减去的均值向量,cv::Scalar(mean_r, mean_g, mean_b) 格式。用于均值归一化。bool swapRB = false,//是否交换R和B通道bool crop = false,//是否在缩放后裁剪图像。如果设置为 true,则图像会被裁剪以适应目标大小int ddepth = CV_32F//默认32位
);

  5、将图像转为一维向量格式并将整理为连续内存

    //此处还待确认,是否一定需要转为一维向量。实际测试下来发现转或不转都可以识别。

    cv::Mat imageNCHW = imageCHW.reshape(1, 1);std::cout << "zuihou d  NCHW shape: " << imageNCHW.size << std::endl;// Convert the image to row-major order, also known as "C order":// 复制矩阵 转换位行主序(C order)存储。意味着数据在内存中是按行连续存储的// 某些深度学习框架或推理引擎可能要求输入数据是连续存储的cv::Mat imageRowMajor;imageNCHW.copyTo(imageRowMajor);

  4.2图像内存开辟与传递

    首先设定图像大小并计算数据缓存区,然后将数据从cpu复制到gpu。

// 图像前处理函数实现
void YoLov5TRT::preprocessImage(const cv::Mat& image, float* gpu_input) {cv::Mat Image = image;// preImage函数中对图片进行详细前处理cv::Mat risezed_image = preImage(Image, H, W);size_t image_size = risezed_image.total() * risezed_image.channels(); // 计算输入大小,用来分配缓存区std::vector<float> input_data(image_size); // 分配输入数据缓冲区// 5. 使用 memcpy 复制数据std::memcpy(input_data.data(), risezed_image.data, image_size * sizeof(float));// 6. 异步复制数据到 GPUcudaMemcpyAsync(gpu_input, input_data.data(), image_size * sizeof(float), cudaMemcpyHostToDevice, stream_);
}

相关文章:

基于c++的yolov5推理之前处理详解及代码(一)

目录 一、前言&#xff1a; 二、关于环境安装&#xff1a; 三、首先记录下自己的几个问题 问题&#xff1a;c部署和python部署的区别&#xff1f; 四、正文开始 4.1 图像预处理讲解 1、BGR---->RBG 2、等比例放缩图片&#xff08;涉及到短边的填充&#xff09; 3、归一化…...

Oracle(55)什么是并行查询(Parallel Query)?

并行查询&#xff08;Parallel Query&#xff09;是数据库管理系统中的一种查询优化技术&#xff0c;它允许数据库引擎同时使用多个处理器或线程来执行查询操作。通过将查询任务分解为多个子任务&#xff0c;并在多个处理器上同时执行这些子任务&#xff0c;可以显著提高查询的…...

关于 Lora中 Chirp Spread Spectrum(CSS)调制解调、发射接收以及同步估计的分析

本文结合相关论文对CSS信号的数学形式、调制解调、发射接收以及同步估计做了全面分析&#xff0c;希望有助于更好地理解lora信号 long-range (LoRa) modulation, also known as chirp spread spectrum (CSS) modulation, in LoRaWAN to ensure robust transmission over long d…...

Java - API

API全称"Application Programming Interface"&#xff0c;指应用程序编程接口 API&#xff08;JDK17.0&#xff09;链接如下 : Overview (Java SE 17 & JDK 17) (oracle.com)https://docs.oracle.com/en/java/javase/17/docs/api/中文版&#xff1a; Java17中…...

力扣 3152. 特殊数字Ⅱ

题目描述 queries二维数组是nums数组待判断的索引区间&#xff08;左闭右闭&#xff09;。需要判断每个索引区间中的nums相邻元素奇偶性是否不同&#xff0c;如果都不同则该索引区间的搜索结果为True&#xff0c;否则为False。 暴力推演&#xff1a;也是我最开始的思路 遍历q…...

识别和缓解软件安全威胁的最佳工具

软件安全威胁会给企业带来重大损失&#xff0c;从经济损失到声誉受损。 企业必须主动识别和缓解这些威胁&#xff0c;防止它们造成危害。 幸运的是&#xff0c;有许多工具可以帮助企业识别和缓解软件安全威胁。 在本博客中&#xff0c;我们将探讨识别和缓解软件安全威胁的顶…...

Linux下的压缩与解压:掌握核心命令行工具

目录 一.前言 二.压缩文件概述 三.tar&#xff1a;Linux 的通用归档工具 常用 tar 命令 四.gzip&#xff1a;强大的压缩程序 常用 gzip 命令 五.zip 和 unzip&#xff1a;处理 ZIP 压缩文件 常用 zip 和 unzip 命令 实用技巧和最佳实践 六.结语 一.前言 在 Linux …...

BGP选路实验

要求&#xff1a; 1.如图连接网络&#xff0c;合理规格IP地址&#xff0c;AS200内IGP协议为OSPF&#xff1b; 2.R1属于AS 100&#xff1b;R2-R3-R4小AS234、R5-R6-R7小AS567&#xff0c;同时声明大AS 200&#xff0c;R8属于AS300&#xff1b; 3.R2-R5、R4-R7之间为联邦EBGP邻居…...

白骑士的C#教学高级篇 3.3 网络编程

网络编程是现代应用程序开发中至关重要的一部分。C# 提供了一套丰富的 API 来处理基本网络通信、Web请求与响应。在本节中&#xff0c;我们将深入探讨这些内容&#xff0c;帮助您掌握如何在 C# 中进行网络编程。 基本网络通信 基本网络通信通常涉及套接字&#xff08;Socket&a…...

AI大模型赋能游戏:更智能、更个性化的NPC

参考论文&#xff1a;https://arxiv.org/abs/2403.10249 在传统游戏中&#xff0c;NPC&#xff08;非玩家角色&#xff09;的行为往往是预先设定好的&#xff0c;缺乏灵活性和变化性。然而&#xff0c;基于大模型的NPC可以利用其强大的推理和学习能力&#xff0c;实时生成对话…...

pymysql的上下文管理器:简化数据库操作

pymysql的上下文管理器&#xff1a;简化数据库操作 当我们使用 pymysql 操作数据库时&#xff0c;管理数据库连接和游标的生命周期是一项重要的任务。Python 的上下文管理器提供了一种优雅的方式来处理资源的获取和释放。在本文中&#xff0c;我们将探索如何创建一个简单的 py…...

AI秘境-墨小黑奇遇记 - 修炼成神经(二)

在解开了感知机和门电路的谜题后&#xff0c;墨小黑对人工智能的世界渐渐产生了浓厚的兴趣。他开始意识到&#xff0c;自己不仅是在学习一门复杂的技术&#xff0c;更是在探索一个充满未知与挑战的神秘领域。 入夜&#xff0c;墨小黑一脸无奈地盯着电脑屏幕&#xff0c;思考着自…...

计算机网络之分组交换时延的计算

一.类型 分组交换的时延包括一下几种&#xff1a; 1.1发送时延 发送时延&#xff0c;也叫传输时延&#xff0c;结点将分组的所有比特推向链路所需要的时间&#xff0c;即从发送分组的第一个比特算起&#xff0c;到该分组的最后一个比特发送完为止。 发送时延 分组长度 / 发…...

虚幻5|入门AI行为树,建立敌人

本章分成两块部分一块是第一点的制作一个简单的AI&#xff0c;后面第二点之后是第二部分建立ai行为树。这两个部分是一个衔接&#xff0c;最好不要跳看 一&#xff0c;制作一个简单的AI 1.首先&#xff0c;我们创建一个敌人的角色蓝图&#xff0c;添加一个场景组件widget用于…...

ARM处理架构中的PMU(Performance Monitoring Unit)和 AMU(Activity Monitors Unit)简介

在 ARM 架构中,PMU(Performance Monitoring Unit)和 AMU(Activity Monitors Unit)是用于性能分析和监控的硬件单元,但它们的功能和应用场景有所不同。以下是它们的主要区别: 1. PMU (Performance Monitoring Unit) 功能:PMU 是一种用于监控处理器性能的硬件单元。它可…...

Service服务在Android中的使用

目录 一&#xff0c;Service简介 二&#xff0c;Service的两种启动方式 1&#xff0c;非绑定式启动Service 2&#xff0c;绑定式启动Service 三&#xff0c;Service的生命周期 1&#xff0c;非绑定式Service的生命周期 2&#xff0c;绑定式Service的生命周期 四&#xf…...

浅谈C语言位段

1、位段的定义 百度百科中是这样解释位段的: 位段&#xff0c;C语言允许在一个结构体中以位为单位来指定其成员所占内存长度&#xff0c;这种以位为单位的成员称为“位段”或称“位域”( bit field) 。利用位段能够用较少的位数存储数据。 以下&#xff0c;我们均在VS2022的…...

arcgisserver登陆信息不正确

密码明明对&#xff0c;但是登录提示登录信息不正确 Arcgis server 9.3.1 无法登录ArcGIS Manager 提示Incorrect Login Information 操作系统windows 2008 x64server 解决办法&#xff1a; 关闭window防火墙解决。 如果防火墙已经关闭&#xff1a; 通过修改用户口令后就可以重…...

KOLA: CAREFULLY BENCHMARKING WORLD KNOWLEDGE OF LARGE LANGUAGE MODELS

文章目录 题目摘要简介KOLA 基准实验评估结论和未来工作道德声明 题目 KOLA&#xff1a;仔细对大型语言模型的世界知识进行基准测试 论文地址:https://arxiv.org/abs/2306.09296 项目地址:https://github.com/ranahaani/GNews 摘要 大型语言模型 (LLM) 的卓越性能要求评估方法…...

Robot Operating System——机器人关节的角度、速度和力矩

大纲 应用场景定义字段解释 案例 sensor_msgs::msg::JointState 是 ROS (Robot Operating System) 中的一个消息类型&#xff0c;用于表示机器人关节的状态信息。它通常用于传输和处理机器人关节的角度、速度和力矩等信息。 应用场景 机器人控制 关节控制&#xff1a;在机器人…...

ES6从入门到精通:前言

ES6简介 ES6&#xff08;ECMAScript 2015&#xff09;是JavaScript语言的重大更新&#xff0c;引入了许多新特性&#xff0c;包括语法糖、新数据类型、模块化支持等&#xff0c;显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var&#xf…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合

强化学习&#xff08;Reinforcement Learning, RL&#xff09;是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程&#xff0c;然后使用强化学习的Actor-Critic机制&#xff08;中文译作“知行互动”机制&#xff09;&#xff0c;逐步迭代求解…...

反向工程与模型迁移:打造未来商品详情API的可持续创新体系

在电商行业蓬勃发展的当下&#xff0c;商品详情API作为连接电商平台与开发者、商家及用户的关键纽带&#xff0c;其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息&#xff08;如名称、价格、库存等&#xff09;的获取与展示&#xff0c;已难以满足市场对个性化、智能…...

工业安全零事故的智能守护者:一体化AI智能安防平台

前言&#xff1a; 通过AI视觉技术&#xff0c;为船厂提供全面的安全监控解决方案&#xff0c;涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面&#xff0c;能够实现对应负责人反馈机制&#xff0c;并最终实现数据的统计报表。提升船厂…...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)

0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述&#xff0c;后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作&#xff0c;其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...

深入理解JavaScript设计模式之单例模式

目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式&#xff08;Singleton Pattern&#…...

2021-03-15 iview一些问题

1.iview 在使用tree组件时&#xff0c;发现没有set类的方法&#xff0c;只有get&#xff0c;那么要改变tree值&#xff0c;只能遍历treeData&#xff0c;递归修改treeData的checked&#xff0c;发现无法更改&#xff0c;原因在于check模式下&#xff0c;子元素的勾选状态跟父节…...

大学生职业发展与就业创业指导教学评价

这里是引用 作为软工2203/2204班的学生&#xff0c;我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要&#xff0c;而您认真负责的教学态度&#xff0c;让课程的每一部分都充满了实用价值。 尤其让我…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

Reasoning over Uncertain Text by Generative Large Language Models

https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...