最近实现了YOLOv10的tensorRT推理代码除了后处理部分只适合YOLOv10之外,其余部分基本可以在yolo系列通用~学习记录~。

#include <fstream>
#include <iostream>
#include <vector>
#include <opencv2/opencv.hpp>
#include "NvInfer.h"
#include "cuda_runtime_api.h"
#include "preprocess.hpp"
#include "postprocess.hpp"
#include "packageimage.hpp"
using namespace cv;
using namespace std;
using namespace nvinfer1;const int INPUT_H = 640;
const int INPUT_W = 640;
const int NUM_CLASSES = 5;
const float CONF_THRESH = 0.5;
const float IOU_THRESH = 0.5;
const int Inputsize_w = 640;
const int Inputsize_h = 200;
const int batch_size = 7;// 替换为你的类别名
std::vector<std::string> class_names = { };// Logger 类(TensorRT 要求)
class Logger : public ILogger {
public:void log(Severity severity, const char* msg) noexcept override {if (severity <= Severity::kINFO)std::cout << "[TRT] " << msg << std::endl;}
} gLogger;// 安全 CUDA 分配
void* safeCudaMalloc(size_t size) {void* ptr = nullptr;cudaMalloc(&ptr, size);return ptr;
}int main() {std::string engine_path = "";std::string image_path = "";std::string imagesave_path = "";// 读取 engine 文件std::ifstream file(engine_path, std::ios::binary);if (!file) {std::cerr << "Failed to open engine file.\n";return -1;}file.seekg(0, file.end);size_t engine_size = file.tellg();file.seekg(0, file.beg);std::vector<char> engine_data(engine_size);file.read(engine_data.data(), engine_size);file.close();// 创建 runtime 和 engineIRuntime* runtime = createInferRuntime(gLogger);ICudaEngine* engine = runtime->deserializeCudaEngine(engine_data.data(), engine_size);IExecutionContext* context = engine->createExecutionContext();// 获取输入输出索引int inputIndex = engine->getBindingIndex("images");//int outputIndex = engine->getBindingIndex(engine->getBindingName(1)); // 假第二个绑定是输出int outputIndex = engine->getBindingIndex("output0");std::vector<Patches> batches;package(batches, image_path, Inputsize_w, Inputsize_h, INPUT_H, INPUT_W);// 图像预处理/*cv::Mat img = cv::imread(image_path);cv::Mat blob;float ratio;int pad_w, pad_h;preprocess(img, blob, ratio, pad_w, pad_h, INPUT_W, INPUT_H);*/// 分配 Host 和 Device 内存size_t input_size = batch_size * 3 * INPUT_H * INPUT_W * sizeof(float);size_t output_size = batch_size * 300 * 6 * sizeof(float); // 假设最多 300 个目标,每个6个值float* input_host = new float[batch_size * 3 * INPUT_H * INPUT_W];float* output_host = new float[batch_size * 300 * 6];for (int i = 0; i < batch_size; i++){memcpy(input_host + i * 3 * INPUT_H * INPUT_W, batches[i].patch.ptr<float>(), 3 * INPUT_H * INPUT_W * sizeof(float));}float* input_device = (float*)safeCudaMalloc(input_size);float* output_device = (float*)safeCudaMalloc(output_size);void* bindings[2];bindings[inputIndex] = input_device;bindings[outputIndex] = output_device;cudaMemcpy(input_device, input_host, input_size, cudaMemcpyHostToDevice);context->setBindingDimensions(inputIndex, Dims4(batch_size, 3, INPUT_H, INPUT_W));context->enqueueV2(bindings, 0, nullptr);cudaMemcpy(output_host, output_device, output_size, cudaMemcpyDeviceToHost);// 原图用于绘制结果cv::Mat img = cv::imread(image_path);std::cout << "batch_size = " << batch_size << ", batches.size() = " << batches.size() << std::endl;for (int i = 0; i < batch_size; i++) {std::vector<Detection> results;float* cur_output = output_host + i * 300 * 6;postprocess(cur_output, 300, CONF_THRESH, results,batches[i].pad_w, batches[i].pad_h, batches[i].ratio);std::cout << "Patch " << i << " detected " << results.size() << " objects." << std::endl;for (const auto& det : results) {int x = det.bbox.x + batches[i].x_offset;int y = det.bbox.y + batches[i].y_offset;int w = det.bbox.width;int h = det.bbox.height;cv::rectangle(img, cv::Point(x, y), cv::Point(x + w, y + h), cv::Scalar(0, 255, 0), 2);std::string label = class_names[det.class_id] + " " + std::to_string(det.conf);cv::putText(img, label, cv::Point(x, y - 5), 0, 0.5, cv::Scalar(255, 255, 255), 1);}}cv::imwrite(imagesave_path, img);std::cout << "Result saved as: " << imagesave_path << std::endl;// 清理资源delete[] input_host;delete[] output_host;cudaFree(input_device);cudaFree(output_device);context->destroy();engine->destroy();runtime->destroy();return 0;
}

预处理:

//头文件:
// preprocess.hpp
#pragma once
#include <opencv2/opencv.hpp>/*** @brief 将原始图像预处理为 TensorRT 模型输入格式** @param img      输入图像(原图)* @param output   输出张量,格式为 [3, INPUT_H, INPUT_W],float32,CHW* @param scale    返回:缩放比例* @param pad_w    返回:左侧 padding 宽度* @param pad_h    返回:上方 padding 高度* @param new_w    模型输入宽度(例如 640)* @param new_h    模型输入高度(例如 640)*/
void preprocess(const cv::Mat& img, cv::Mat& output, float& scale, int& pad_w, int& pad_h, int new_w, int new_h);//cpp:
#include "preprocess.hpp"
#include <opencv2/opencv.hpp>void preprocess(const cv::Mat& img, cv::Mat& output, float& scale, int& pad_w, int& pad_h, int new_h, int new_w){ int orig_w = img.cols;int orig_h = img.rows;scale = std::min((float)new_w / orig_w, (float) new_h / orig_h);int resized_w = int(scale * orig_w);int resized_h = int(scale * orig_h);// 缩放图像cv::Mat resized;cv::resize(img, resized, cv::Size(resized_w, resized_h));cv::Mat padded(new_h, new_w, CV_8UC3, cv::Scalar(114, 114, 114));pad_w = (new_w - resized_w) / 2;pad_h = (new_h - resized_h) / 2;resized.copyTo(padded(cv::Rect(pad_w, pad_h, resized_w, resized_h)));cv::Mat float_img;padded.convertTo(float_img, CV_32FC3, 1.0 / 255.0);// HWC -> CHWstd::vector<cv::Mat> channels(3);cv::split(float_img, channels);output = cv::Mat(3, new_h * new_w, CV_32F);// 将每个通道拉平并写入 outputfor (int i = 0; i < 3; ++i) {memcpy(output.ptr<float>(i), channels[i].data, new_h * new_w * sizeof(float));}}

后处理

//头文件:
#pragma once
#include <vector>
#include <opencv2/opencv.hpp>struct Detection {cv::Rect bbox;    // 检测框int class_id;     // 类别编号float conf;       // 置信度
};/*** @brief 对模型输出进行后处理:置信度筛选 + NMS** @param output      TensorRT 输出(通常是 [N, 6])* @param num_preds   预测框数量(例如:1000)* @param conf_thresh 置信度阈值* @param out_dets    输出:保存最终保留的检测结果*/
void postprocess(const float* output, int num_preds, float conf_thresh, std::vector<Detection>& out_dets,int pad_w, int pad_h, float ratio);//cpp:
#include "postprocess.hpp"
#include <opencv2/opencv.hpp>
void postprocess(const float* output, int num_preds, float conf_thresh, std::vector<Detection>& out_dets, int pad_w, int pad_h, float ratio) {std::vector<Detection> raw_dets;for (int i = 0; i < num_preds; i++) {const float* det = output + i * 6;float x1 = det[0], y1 = det[1], x2 = det[2], y2 = det[3];float conf = det[4];int class_id = static_cast<int>(det[5]);if (conf < conf_thresh) {continue;}x1 = (x1 - pad_w) / ratio;y1 = (y1 - pad_h) / ratio;x2 = (x2 - pad_w) / ratio;y2 = (y2 - pad_h) / ratio;int left = static_cast<int>(x1);int top = static_cast<int>(y1);int right = static_cast<int>(x2);int bottom = static_cast<int>(y2);int width = right - left;int height = bottom - top;cv::Rect bbox(static_cast<int>(left),static_cast<int>(top),static_cast<int>(width),static_cast<int>(height));std::cout << "x1 = " << x1 << ", y1 = " << y1 << ", x2 = " << x2 << ", y2 = " << y2 << std::endl;out_dets.push_back(Detection{ bbox, class_id, conf });}
}

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

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

相关文章

软件定时器详解:RTOS 中的“软时钟”机制与源码解析

在嵌入式实时系统开发中&#xff0c;定时器是不可或缺的工具。软件定时器&#xff08;Software Timer&#xff09; 提供了一种无需创建独立任务、便可在特定延时后执行回调函数的机制。它适用于那些不要求高精度、但需要周期性或一次性延时执行操作的场景。 一、什么是软件定时…

从Yocto中获取源码用传统的方式单独编译

要获取 Yocto 构建后的 Linux 内核和 U-Boot 源码,并进行独立编译,需获取完整的源码树(包含所有应用补丁和配置)及原始配置信息。以下是具体步骤: 获取最终源码路径确定构建目录位置: 内核工作目录 KERNEL_WORKDIR=$(bitbake -e virtual/kernel | grep ^WORKDIR= | cut…

【记录】服务器|常见的八种硬盘接口的简介和清晰的接口图片(2025年6月)

硬盘接口很多&#xff0c;在管服务器的时候总是要买&#xff0c;但是偶尔会忘记自己的服务器支持什么接口&#xff0c;此时就需要看引脚。 如果没插满&#xff0c;就可以直接拍接口的图片&#xff0c;与下面这些图片对照一下【文字介绍是AI直接生成的&#xff0c;图片是我到处…

在一个成熟产品中,如何设计数据库架构以应对客户字段多样化,确保系统的可维护性、可扩展性和高性能。

在SaaS系统、平台型应用或高度可配置的企业级软件中&#xff0c;我们常常会遇到一个现实问题&#xff1a;不同客户对同一个业务表存在差异化字段需求。例如&#xff0c;A客户需要一个“业务员等级”字段&#xff0c;B客户不需要&#xff1b;C客户希望订单表中增加“海外仓编码”…

社群营销应该怎么玩

现在做营销&#xff0c;光靠打广告可不行了。大家都喜欢扎堆儿&#xff0c;找志同道合的人一起玩&#xff0c;这就是社群的力量。那怎么用好这股力量呢&#xff1f;咱们慢慢聊。 首先得明白&#xff0c;社群不是拉个群就完事了。关键是要让大家觉得这里有意思&#xff0c;有收…

【论文阅读笔记】TransparentGS:当高斯溅射学会“看穿”玻璃,如何攻克透明物体重建难题?

文章目录 TransparentGS: Fast Inverse Rendering of Transparent Objects with GaussiansInfoAbstractIntroductionMethod预备知识3D GS的概念不再赘述渲染方程透明高斯Gaussian Light Field Probes多阶段重建实验结果和评估消融实验应用讨论和限制结论TransparentGS: Fast In…

某视频网站运维工程师面试题

某视频网站运维工程师面试题 1、 简单写下Xeon和Itanium这两个产品的本质区别&#xff1f; 2、 ECC内存每Bank的颗粒数是单数还是双数的&#xff1f; 3、 假如有5块1T的硬盘&#xff0c;要求组合成尽量多的实际使用空间并至少容忍坏2盘而不影响raid组工作。请问有几种模式来组…

Java底层原理:深入理解JVM性能调优与监控

一、JVM性能调优概述 JVM性能调优是Java应用优化的重要环节&#xff0c;通过合理配置JVM参数&#xff0c;可以提高Java应用的性能和稳定性。JVM性能调优的主要目标是减少垃圾回收的频率和时间&#xff0c;提高线程的运行效率&#xff0c;优化内存的使用。 &#xff08;一&…

Joblib库多进程/线程使用(一):使用generator参数实现边响应边使用

进程与线程的基本概念 特性进程 (Process)线程 (Thread)定义 操作系统分配资源的基本单位&#xff08;独立的内存空间&#xff09; 多进程可真正并行&#xff08;利用多核 CPU&#xff09; 进程内的执行单元&#xff08;共享进程资源&#xff09;独立性完全独立&#xff0c;崩…

css上下滚动文字

效果图 取得是数组里的数据 上下滚动切换 css .notice-new {background: #222222;border-radius: 19rpx;margin-top: 28rpx;font-size: 24rpx;color: white;font-weight: 500;padding: 0 20rpx;height: 55rpx;line-height: 55rpx;overflow: hidden;.notice-scroll-wrapper {pos…

概念篇: 01-带你认识Dockerfile

在本篇文章中&#xff0c;我们将带你认识 Dockerfile —— 构建 Docker 镜像的"蓝图"。我们会介绍它的基本概念和常用指令&#xff0c;帮助你理解如何使用它来打包你的应用。 简单了解 Docker&#xff08;背景知识&#xff09; 在我们深入 Dockerfile 之前&#xf…

技术伦理之争:OpenAI陷抄袭风波,法院强制下架宣传视频

在AI巨头OpenAI宣布以65亿美元天价收购苹果前设计总监Jony Ive的硬件公司IO仅一个月后&#xff0c;一场抄袭指控将这家科技明星企业推上风口浪尖。 源自谷歌X实验室的初创企业IYO将OpenAI告上法庭&#xff0c;指控其窃取智能耳塞核心技术&#xff0c;并通过巨额收购试图掩盖抄袭…

前沿解读:缺陷如何操控二维半导体中的电子摩擦耗散超快动力学

摩擦能耗约占全球一次能源损耗的1/3&#xff0c;在微纳器件中尤为突出。二维半导体&#xff08;如WS₂&#xff09;因其独特的电子特性成为研究热点&#xff0c;但电子摩擦的动态机制因电子行为的超快特性长期难以捕捉。近期清华团队在Nature Communications发表的研究[1]&…

什么是物联网 (IoT)?

你家是否安装了智能恒温器&#xff1f;或者你属于三分之一的美国健身追踪器用户&#xff0c;通过设备记录运动习惯&#xff1f;如果是&#xff0c;你已在使用物联网技术。这项技术不仅融入日常生活&#xff0c;更深刻改变着组织的运营方式。物联网通过多种技术连接数字与物理世…

[特殊字符] Windows 查看端口占用及服务来源教程(以 9018 端口为例)

下面是一份详细的 Windows 系统中排查 某端口&#xff08;如 9018&#xff09;被哪个程序占用 并确定其具体服务来源的完整教程&#xff0c;适合用于日常运维、开发部署排障等场景。 &#x1f3af; Windows 查看端口占用及服务来源教程&#xff08;以 9018 端口为例&#xff09…

异步爬虫 原理与解析

先遍历100遍一个程序 import requests import logging import timelogging.basicConfig(levellogging.INFO, format%(asctime)s - %(levelname)s: %(message)s) TOTAL_NUMBER 100 BASE_URL https://ssr4.scrape.center/start_time time.time() for id in range(1,TOTAL_NUM…

vscode管理go多个版本

#1.下载go安装包 https://developer.aliyun.com/mirror/golang/?spma2c6h.25603864.0.0.55ea7c45IsI4GM # 2.创建 sdk 目录&#xff08;如果不存在&#xff09; mkdir -p ~/sdk # 3.解压下载的 go1.16.15 到 ~/sdk/ tar -C ~/sdk -xzf go1.16.15.linux-amd64.tar.gz # 4.重…

香港维尔利健康科技集团推出AI辅助医学影像训练平台,助力医护人才数字化转型

香港维尔利健康科技集团近日正式发布其自主研发的“AI辅助医学影像训练平台&#xff08;V-MedTrain&#xff09;”&#xff0c;这一创新平台的上线&#xff0c;标志着医学影像教育迈入智能化辅助教学新时代。依托人工智能与大数据分析技术&#xff0c;香港维尔利健康科技集团在…

互联网+医疗,医疗服务的全方位革新

近年来&#xff0c;互联网医疗行业迅速崛起&#xff0c;为医疗健康服务带来了翻天覆地的变革。新模式、新业态层出不穷&#xff0c;不仅大幅提升了医疗健康服务的可及性&#xff0c;也使得群众就医体验更为舒适、便捷。互联网技术的广泛应用&#xff0c;不仅改变了医疗核心业务…

酒店智能门锁系统常见问题解决方法——东方仙盟

重做系统后 usb发卡器与注册时发卡器不一致 解决发方法: 用总卡重新注册软件,要可以开房间的总卡 房号不存在 2声---正确提示&#xff0c;表示是设置卡 3声---门锁已反锁&#xff0c;解决方法&#xff1a;用能开反锁的卡或解除反锁 6声---房号不对&#xff0c;解决方法&#…