YOLOv10tensorRT推理代碼C++

最近實現了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;解決方法&#…