# tensorrt_infer **Repository Path**: calacaly/tensorrt_infer ## Basic Information - **Project Name**: tensorrt_infer - **Description**: tensorrt infer test - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-03-09 - **Last Updated**: 2026-07-28 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 🚀 TensorRT推理工具 - 现代化高性能推理框架

C++17 TensorRT OpenCV License

**高性能TensorRT 推理框架 | 支持目标检测与语义分割 | 批量处理 | 可视化** --- ## 📑 目录导航
点击展开完整目录 ### 🚀 快速上手 - [5 分钟快速上手](#-5-分钟快速上手最简单方式) - [使用 main 程序推理](#-使用-main-程序进行推理最常用) - [模型说明](#-模型说明) ### 🛠️ 构建与编译 - [环境要求](#-环境要求) - [xmake 构建指南](#-编译和使用) - [安装 xmake](#1-安装-xmake) - [配置和编译](#2-配置构建环境) - [运行和调试](#4-运行程序) - [构建库文件](#-构建共享库和静态库) - [动态库 (.so)](#-修改-xmakedlua-添加库目标) - [静态库 (.a)](#-修改-xmakedlua-添加库目标) ### 🔗 项目集成 - [在其他项目中使用](#-在其他项目中使用编译的库) - [方式一:共享库](#方式一使用共享库推荐) - [方式二:源码引用](#方式二直接引用源码适合开发阶段) - [方式三:CMake 集成](#方式三使用-cmake-项目集成) - [OpenCV 静态链接](#-修改-opencv-为静态依赖) ### 📡 API 使用 - [API 接口说明](#-api-使用说明) - [快速开始](#快速-start-1) - [详细用法](#方式-1 使用便捷函数最简单推荐) - [示例代码](#-示例代码) - [InferenceAPI 示例](#inferenceapi-示例) - [SimpleModelManager 示例](#simplemodelmanager-示例) - [EnhancedBatchManager 示例](#enhancedbatchmanager-示例) ### ⚙️ 高级配置 - [CUDA/TensorRT 配置](#cuda-和-tensorrt-配置详解) - [标准环境](#1-标准环境配置系统级安装) - [WSL 环境](#2-wsl-环境配置自定义路径) - [OpenCV 配置](#opencv-依赖配置详解) - [xmake 包管理](#方式一使用-xmake-包管理推荐) - [系统 OpenCV](#方式二手动指定系统-opencv) ### 📖 其他 - [项目结构](#-项目结构) - [核心优势](#-核心优势) - [数据流程图](DATA_FLOW.md) - 📊 6 种推理模式的详细数据流转 - [扩展模型算法教程](EXTENSION_TUTORIAL.md) - 🔨 如何添加自定义模型 - [总结](#-总结)
--- ## 📋 项目简介 **TensorRT Infer** 是一个现代化的高性能深度学习推理框架,提供完整的图像预处理、TensorRT推理和后处理功能。支持单图处理和批量处理模式,内置可视化功能。 ### 🔥 核心特性 - **⚡ 高性能推理**: 基于 NVIDIA TensorRT 10.10 优化引擎 - **🔄 批量处理**: 智能多线程并发处理能力 - **🎨 双模式支持**: SimpleModelManager(单图)+ EnhancedBatchManager(批量) - **🎯 完整后处理**: 坐标映射、置信度过滤(默认 0.2)、类别映射 - **📊 可视化**: 检测结果可视化并保存(目标检测 + 语义分割) - **🔧 统一配置**: 所有层级使用统一的置信度阈值配置 - **📊 灵活 API**: InferenceAPI 提供简洁的推理接口 ## 🎯 设计理念 ### 🎨 核心哲学 **「简洁即力量」** - 我们相信最好的框架是简洁、高效且易于使用的 ### 🔑 设计原则 1. **🎯 完整推理链** - 从图像加载到结果可视化的完整流程 2. **🎨 模块化设计** - SimpleModelManager(单图)+ EnhancedBatchManager(批量) 3. **✅ 开箱即用** - 内置后处理和可视化功能,默认置信度 0.2 4. **📊 高性能** - 使用 TensorRT 10.10 和多线程优化 5. **⚡ 统一配置** - 所有层级使用统一的置信度阈值,避免重复推理 6. **🔧 易用性** - 简洁的 CLI 接口和清晰的代码结构 ## 🚀 快速开始 ### 💻 使用 main 程序进行推理(最常用) 编译完成后,直接使用命令行工具进行推理。 #### 1️⃣ 单图目标检测 ```bash # 基本用法 ./build/linux/x86_64/release/tensorrt_infer models/yolo11n.engine det input.jpg # 查看检测结果 # 程序会自动: # 1. 加载模型 # 2. 处理图像 # 3. 执行推理 # 4. 输出检测结果(类别、位置、置信度) # 5. 保存可视化结果到当前目录 ``` **输出示例**: ``` [INFO] 检测到 3 个目标 [INFO] 目标 #1: person (置信度:0.92) [120, 45, 380, 520] [INFO] 目标 #2: bus (置信度:0.87) [50, 100, 600, 400] [INFO] 目标 #3: car (置信度:0.75) [200, 150, 350, 280] [INFO] 可视化结果已保存:input_result.jpg ``` --- #### 2️⃣ 单图语义分割 ```bash # 使用分割模型 ./build/linux/x86_64/release/tensorrt_infer models/yolo11n-seg.engine seg input.jpg # 输出分割掩码和可视化结果 ``` --- #### 3️⃣ 批量处理多张图像 ```bash # 处理整个文件夹的图像 ./build/linux/x86_64/release/tensorrt_infer -b models/yolo11n.engine det ./images/ -O ./output/ # 带详细日志输出 ./build/linux/x86_64/release/tensorrt_infer -b models/yolo11n.engine det ./images/ -O ./output/ -v ``` **参数说明**: - `-b` 或 `--batch`: 启用批量处理模式 - `-O` 或 `--output`: 指定输出目录 - `-v` 或 `--verbose`: 显示详细日志 --- #### 4️⃣ 自定义配置 ```bash # 调整置信度阈值(默认:0.2) ./build/linux/x86_64/release/tensorrt_infer models/yolo11n.engine det input.jpg --confidence 0.5 # 查看所有可用参数 ./build/linux/x86_64/release/tensorrt_infer --help ``` **常用参数**: ``` 模型类型: det 目标检测模型 seg 语义分割模型 选项: -b, --batch 批量处理模式 -O, --output 输出目录 -c, --confidence 置信度阈值(默认:0.2) -v, --verbose 详细输出模式 -h, --help 显示帮助信息 ``` --- ### 基本用法 ```bash # 单图目标检测 ./build/linux/x86_64/release/tensorrt_infer models/yolo11n.engine det input.jpg # 单图语义分割 ./build/linux/x86_64/release/tensorrt_infer models/yolo11n-seg.engine seg input.jpg # 批量处理(使用 -b 或 --batch 标志) ./build/linux/x86_64/release/tensorrt_infer -b models/yolo11n.engine det ./images/ -O ./output/ # 带详细输出的批量处理 ./build/linux/x86_64/release/tensorrt_infer -b models/yolo11n.engine det ./images/ -O ./output/ -v ``` ### 核心流程 ``` 输入图像 → 预处理 → TensorRT 推理 → 后处理 → 可视化输出 ↓ ↓ ↓ LetterBox GPU 推理 坐标映射 + 过滤 绘制检测框 ``` ## 🛠️ 环境要求 - **GPU**: NVIDIA GPU(支持 CUDA Compute Capability 6.0+) - **显存**: 至少 4GB(推荐 8GB+) - **内存**: 系统内存 8GB+ #### 软件依赖 - **CUDA Toolkit** 12.0+ (推荐 12.9) - **TensorRT** 10.0+ (推荐 10.10) - **GCC/Clang** 支持 C++17 标准 - **xmake** v2.7+ 构建系统 - **OpenCV** 4.x(自动下载) - **spdlog**(自动下载) - **CLI11**(自动下载) ## 📁 项目结构 ``` tensorrt_infer/ ├── src/ │ ├── core/ # 核心模块 │ │ ├── image_processing/ # 图像处理模块 │ │ │ ├── image_loader.hpp │ │ │ ├── image_types.hpp │ │ │ ├── image_write.hpp │ │ │ ├── preprocessor.hpp │ │ │ └── processing_pipeline.hpp │ │ ├── visualization/ # 可视化模块 ⭐ │ │ │ ├── batch_visualizer.hpp │ │ │ └── simple_visualizer.hpp │ │ ├── utils/ # 工具模块 ⭐ │ │ │ ├── cuda_utils.hpp │ │ │ ├── memory_pool.hpp │ │ │ ├── performance.hpp │ │ │ ├── thread_safety.hpp │ │ │ └── timer.hpp │ │ ├── types/ # 类型定义 ⭐ │ │ │ ├── interfaces.hpp │ │ │ └── unified_types.hpp │ │ ├── cli_parser.hpp # CLI 参数解析 │ │ ├── coco_names.hpp # COCO 类别名称 │ │ ├── debug_output.hpp # 调试输出 │ │ ├── postprocessor.hpp # 后处理器 │ │ └── preprocess_result.hpp # 预处理结果 │ ├── engine/ # 引擎模块 │ │ ├── model_interface.hpp # 模型接口 │ │ ├── model_factory.hpp # 模型工厂 │ │ ├── trt_base.hpp # TensorRT 基础 │ │ ├── config_manager.hpp # 配置管理器 │ │ ├── simple_model_manager.hpp # 单图管理器 ⭐ │ │ └── enhanced_batch_manager.hpp # 批量管理器 ⭐ │ ├── models/ # 模型实现 │ │ ├── detection_model.hpp │ │ └── segmentation_model.hpp │ ├── common.hpp # 通用工具 │ └── main.cpp # 主程序入口 ├── models/ # 模型文件目录 ├── xmake.lua # 构建配置 └── README.md # 项目文档 ``` ### 🔨 想要扩展自己的模型算法? 本框架采用模块化设计,支持轻松扩展自定义模型。我们提供了完整的教程: - 📖 **详细教程**:[`EXTENSION_TUTORIAL.md`](EXTENSION_TUTORIAL.md) - 如何继承 `IModel` 接口 - 如何实现自定义模型类 - 如何在 `ModelFactory` 中注册新模型 - 完整的代码示例(姿态估计、分类模型、多任务模型) - 编译和测试步骤 - GPU 后处理优化技巧 快速开始: ```bash # 1. 阅读 EXTENSION_TUTORIAL.md # 2. 参考 src/models/detection_model.hpp 和 segmentation_model.hpp # 3. 创建你的 pose_model.hpp 和 pose_model.cpp # 4. 在 ModelFactory 中注册 # 5. 编译并测试你的模型 ``` ## 🔧 编译和使用 ### 🚀 5 分钟快速上手(最简单方式) 如果你想快速体验,只需执行以下 3 步: ```bash # 1. 安装 xmake(如果已安装可跳过) curl -fsSL https://xmake.io/shget.text | bash source ~/.xmake/profile # 2. 编译项目 cd tensorrt_infer xmake # 3. 运行推理(替换为你的模型和图片路径) ./build/linux/x86_64/release/tensorrt_infer models/yolo11n.engine det input.jpg ``` 就这么简单!编译好的程序在 `./build/linux/x86_64/release/` 目录下。 --- ### 📋 xmake 完整指南 **xmake** 是一个基于 Lua 的轻量级跨平台构建工具,语法简洁,配置灵活。 #### 1. 安装 xmake **推荐使用官方脚本快速安装**: ```bash # Linux/macOS curl -fsSL https://xmake.io/shget.text | bash # 或者使用 wget wget https://xmake.io/shget.text -O - | bash # 安装完成后,重启终端或执行 source ~/.xmake/profile ``` **其他安装方式**: ```bash # Ubuntu/Debian sudo apt install xmake # Arch Linux sudo pacman -S xmake # Alpine Linux sudo apk add xmake # macOS (Homebrew) brew install xmake # Windows (Scoop) scoop install xmake # Windows (Winget) winget install xmake ``` **验证安装**: ```bash xmake --version ``` --- #### 2. 配置构建环境 ```bash cd tensorrt_infer # 标准 Linux 环境配置 xmake config -p linux -a x86_64 -m release # 或者使用简写 xmake f -p linux -a x86_64 -m release ``` **配置参数说明**: - `-p linux`: 指定平台为 Linux - `-a x86_64`: 指定架构为 x86_64 - `-m release`: 发布模式(最高优化) **可选配置**: ```bash # Debug 模式(带调试信息) xmake f -m debug # 指定输出目录 xmake f -o ./output # 查看配置帮助 xmake config --help ``` --- #### 3. 编译项目 ```bash # 编译所有目标(主程序 + API 示例) xmake # 或者显示详细输出 xmake -v # 强制重新编译 xmake -f -v # 单独编译主程序 xmake tensorrt_infer # 单独编译 API 示例 xmake api_example ``` **编译输出位置**: ``` build/linux/x86_64/release/tensorrt_infer build/linux/x86_64/release/api_example ``` --- #### 4. 运行程序 ```bash # 运行主程序(带参数) xmake run tensorrt_infer -- models/yolo11n.engine det input.jpg # 运行 API 示例 xmake run api_example # 查看程序的帮助信息 xmake run tensorrt_infer -- --help # 或者直接执行编译后的二进制文件 ./build/linux/x86_64/release/tensorrt_infer --help ./build/linux/x86_64/release/api_example ``` --- #### 5. 调试程序 ```bash # 切换到 Debug 模式 xmake config -m debug # 重新编译 xmake # 使用调试器运行(自动检测 lldb/gdb) xmake run -d tensorrt_infer # 指定调试器(如 gdb) xmake config --debugger=gdb xmake run -d tensorrt_infer ``` --- #### 6. 清理和维护 ```bash # 清理构建文件 xmake clean # 完全清理(包括配置) xmake clean --all # 查看构建配置 xmake config # 更新 xmake 到最新版本 xmake update ``` --- ### 📝 xmake.lua 配置解析 项目的 `xmake.lua` 配置文件结构: ```lua -- 定义构建规则 add_rules("mode.debug", "mode.release") -- 设置 C++ 标准 set_languages("c++17") -- 添加依赖包 add_requires("spdlog") -- 日志库 add_requires("fmt") -- 格式化库 add_requires("cli11") -- CLI 参数解析 add_requires("opencv", {configs = {contrib = true}}) -- 图像处理 add_requires("stb") -- 图像加载 -- 定义主程序目标 target("tensorrt_infer") set_kind("binary") add_files("src/**.cpp") add_headerfiles("src/(**.hpp)") add_includedirs("src") add_packages("spdlog", "fmt", "cli11", "opencv", "stb") add_wsl_cuda_tensorrt_config() -- CUDA/TensorRT 配置 -- 定义 API 示例目标 target("api_example") set_kind("binary") add_files("examples/api_example.cpp", "src/api/inference_api.cpp") add_headerfiles("src/api/(**.hpp)") add_includedirs("src") add_packages("spdlog", "fmt", "opencv", "stb") add_wsl_cuda_tensorrt_config() ``` **CUDA 和 TensorRT 配置**: - 标准环境:自动链接 `/usr/local/cuda` 和系统 TensorRT 库 - WSL 环境:使用专用配置,指向 CUDA 12.9 和 TensorRT 10.10 --- ### 📦 构建共享库和静态库 除了编译可执行文件,项目还支持构建为库文件供其他项目使用。 #### 1. 修改 xmake.lua 添加库目标 在 `xmake.lua` 中添加以下配置: ```lua -- 构建共享库(.so) target("tensorrt_lib") set_kind("shared") -- shared 表示动态库 add_files("src/api/inference_api.cpp") add_headerfiles("src/api/(**.hpp)") add_includedirs("src") add_packages("spdlog", "fmt", "opencv", "stb") add_wsl_cuda_tensorrt_config() -- 设置库文件名(可选,默认为 libtensorrt_lib.so) set_basename("tensorrt_infer") -- 构建静态库(.a) target("tensorrt_lib_static") set_kind("static") -- static 表示静态库 add_files("src/api/inference_api.cpp") add_headerfiles("src/api/(**.hpp)") add_includedirs("src") add_packages("spdlog", "fmt", "opencv", "stb") add_wsl_cuda_tensorrt_config() -- 设置库文件名 set_basename("tensorrt_infer_static") ``` #### 2. 编译库文件 ```bash # 编译共享库 xmake tensorrt_lib # 编译静态库 xmake tensorrt_lib_static # 查看生成的库文件 ls build/linux/x86_64/release/lib*.so lib*.a # 输出: # libtensorrt_infer.so # 共享库 # libtensorrt_infer_static.a # 静态库 ``` **输出位置**: ``` build/linux/x86_64/release/libtensorrt_infer.so # 共享库 build/linux/x86_64/release/libtensorrt_infer_static.a # 静态库 ``` --- ### 🔗 在其他项目中使用编译的库 #### 方式一:使用共享库(推荐) **步骤 1:安装库到系统目录** ```bash # 安装库和头文件 xmake install # 或指定安装目录 xmake install -o /usr/local/tensorrt_infer ``` **步骤 2:在其他项目的 xmake.lua 中引用** ```lua add_requires("spdlog", "opencv") -- 添加你的库作为依赖 add_requires("tensorrt_infer", {system = true}) target("my_project") set_kind("binary") add_files("src/*.cpp") -- 链接 tensorrt_infer 库 add_links("tensorrt_infer") -- 添加头文件路径(如果未自动包含) add_includedirs("/usr/local/include") -- 添加库搜索路径 add_linkdirs("/usr/local/lib") -- 其他依赖 add_packages("spdlog", "opencv") ``` **步骤 3:在代码中使用** ```cpp #include "api/inference_api.hpp" int main() { // 使用 InferenceAPI 进行推理 auto& api = InferenceAPI::getInstance(); api.initialize("model.engine", "det"); cv::Mat result = api.inferImage("input.jpg"); return 0; } ``` --- #### 方式二:直接引用源码(适合开发阶段) **步骤 1:在项目 xmake.lua 中包含源文件** ```lua add_requires("spdlog", "opencv", "cli11", "stb") target("my_project") set_kind("binary") add_files("src/*.cpp") -- 直接包含 tensorrt_infer 的源文件 add_files("../tensorrt_infer/src/api/inference_api.cpp") -- 添加头文件路径 add_includedirs("../tensorrt_infer/src") -- 添加依赖包 add_packages("spdlog", "opencv", "cli11", "stb") -- 添加 CUDA/TensorRT 配置 add_includedirs("/usr/local/cuda/include") add_linkdirs("/usr/local/cuda/lib64") add_links("nvinfer", "cudart") ``` **步骤 2:在代码中使用** ```cpp #include "api/inference_api.hpp" // 直接包含头文件 int main() { // 直接使用 API cv::Mat result = detectObject( "model.engine", "det", "input.jpg" ); return 0; } ``` --- #### 方式三:使用 CMake 项目集成 如果你的项目使用 CMake,可以这样集成: ```cmake cmake_minimum_required(VERSION 3.15) project(MyProject) set(CMAKE_CXX_STANDARD 17) # 查找 OpenCV find_package(OpenCV REQUIRED) include_directories(${OpenCV_INCLUDE_DIRS}) # 添加 tensorrt_infer 作为子目录 add_subdirectory(../tensorrt_infer tensorrt_infer_build) # 创建你的可执行文件 add_executable(my_app src/main.cpp) # 链接 tensorrt_infer 库 target_link_libraries(my_app tensorrt_lib # 或者 tensorrt_lib_static ${OpenCV_LIBS} ) # 包含头文件 target_include_directories(my_app PRIVATE ../tensorrt_infer/src ) ``` --- ### 🔧 修改 OpenCV 为静态依赖 默认情况下,xmake 使用动态链接的 OpenCV。如果需要静态链接 OpenCV: #### 方法一:修改 xmake.lua 配置 ```lua -- 修改前(动态链接) add_requires("opencv", {configs = {contrib = true}}) -- 修改后(静态链接) add_requires("opencv", { configs = { contrib = true, shared = false -- 设置为 false 使用静态库 } }) ``` **完整示例**: ```lua add_rules("mode.debug", "mode.release") set_languages("c++17") -- 静态链接 OpenCV add_requires("opencv", { configs = {contrib = true, shared = false} }) add_requires("spdlog") add_requires("fmt") add_requires("cli11") add_requires("stb") target("tensorrt_infer") set_kind("binary") add_files("src/**/*.cpp") add_packages("spdlog", "fmt", "cli11", "opencv", "stb") add_wsl_cuda_tensorrt_config() ``` #### 方法二:命令行配置 ```bash # 配置 xmake 使用静态 OpenCV xmake require --config opencv shared=false # 重新编译 xmake clean xmake f -p linux -a x86_64 -m release xmake -v ``` #### 静态链接的优缺点 **优点**: - ✅ 生成的可执行文件独立,无需系统安装 OpenCV - ✅ 避免不同系统 OpenCV 版本兼容性问题 - ✅ 部署简单,单个文件即可运行 **缺点**: - ❌ 可执行文件体积较大(可能增加几十 MB) - ❌ 内存占用增加(多个程序无法共享库内存) - ❌ OpenCV 更新时需要重新编译程序 **建议**: - 🔹 **开发环境**:使用动态链接,加快编译速度 - 🔹 **生产部署**:使用静态链接,简化部署流程 - 🔹 **Docker 容器**:使用动态链接,减小镜像体积 --- ### ⚙️ CUDA 和 TensorRT 配置详解 项目提供了两套 CUDA/TensorRT 配置函数,可根据实际环境选择使用。 #### 1. 标准环境配置(系统级安装) 适用于 CUDA 和 TensorRT 通过包管理器安装在系统标准路径的情况。 **配置函数**:`add_cuda_tensorrt_config()` ```lua function add_cuda_tensorrt_config() -- 添加 CUDA 头文件包含路径 add_includedirs("/usr/local/cuda/include") -- 添加 CUDA 库文件链接路径 add_linkdirs("/usr/local/cuda/lib64") -- 添加 TensorRT 库文件链接路径(系统安装位置) add_linkdirs("/usr/lib/x86_64-linux-gnu") -- 设置运行时动态链接库搜索路径 add_rpathdirs("/usr/local/cuda/lib64") add_rpathdirs("/usr/lib/x86_64-linux-gnu") -- 链接所需库文件 add_links("nvinfer", "cudart") end ``` **如何修改**: 如果你的 CUDA 或 TensorRT 不在标准路径,需要修改对应的路径: ```lua -- 修改 CUDA 路径 add_includedirs("/your/custom/cuda/path/include") -- 改为你的 CUDA 头文件路径 add_linkdirs("/your/custom/cuda/path/lib64") -- 改为你的 CUDA 库路径 -- 修改 TensorRT 路径 add_linkdirs("/your/custom/tensorrt/path/lib") -- 改为你的 TensorRT 库路径 -- 如果 TensorRT 有独立的头文件路径 add_includedirs("/your/custom/tensorrt/path/include") ``` **查找 CUDA/TensorRT 路径的方法**: ```bash # 查找 CUDA 路径 which nvcc # 输出:/usr/local/cuda/bin/nvcc # 则 CUDA include 在:/usr/local/cuda/include # 则 CUDA lib 在:/usr/local/cuda/lib64 # 查找 TensorRT 路径 find /usr -name "libnvinfer.so" 2>/dev/null # 常见位置:/usr/lib/x86_64-linux-gnu/libnvinfer.so # 或者:/usr/local/lib/libnvinfer.so ``` --- #### 2. WSL 环境配置(自定义路径) 适用于 WSL 环境或手动安装的 CUDA 和 TensorRT。 **配置函数**:`add_wsl_cuda_tensorrt_config()` ```lua function add_wsl_cuda_tensorrt_config() -- 添加 CUDA 头文件包含路径 add_includedirs("/usr/local/cuda-12.9/include") -- 添加 CUDA 库文件链接路径 add_linkdirs("/usr/local/cuda-12.9/lib64") -- 添加 TensorRT 头文件和库文件路径 add_includedirs("/opt/TensorRT/TensorRT-10.10.0.31/include") add_linkdirs("/opt/TensorRT/TensorRT-10.10.0.31/lib") -- 设置运行时动态链接库搜索路径 add_rpathdirs("/usr/local/cuda-12.9/lib64") add_rpathdirs("/opt/TensorRT/TensorRT-10.10.0.31/lib") -- 链接所需库文件 add_links("nvinfer", "cudart") end ``` **如何修改**: 根据你的实际安装路径修改: ```lua -- 假设你的 CUDA 安装在 /opt/cuda-12.8 add_includedirs("/opt/cuda-12.8/include") add_linkdirs("/opt/cuda-12.8/lib64") -- 假设你的 TensorRT 安装在 /home/user/tensorrt add_includedirs("/home/user/tensorrt/include") add_linkdirs("/home/user/tensorrt/lib") -- 修改运行时路径(用于程序执行时找到库文件) add_rpathdirs("/opt/cuda-12.8/lib64") add_rpathdirs("/home/user/tensorrt/lib") ``` --- #### 3. 切换配置方法 在 `target` 中指定使用的配置函数: ```lua target("tensorrt_infer") set_kind("binary") add_files("src/**/*.cpp") add_packages("spdlog", "fmt", "cli11", "opencv", "stb") -- 使用标准环境配置 add_cuda_tensorrt_config() -- 或者使用 WSL 环境配置 -- add_wsl_cuda_tensorrt_config() ``` **注意**:同一时间只能使用一种配置,注释掉不需要的配置。 --- ### 🎨 OpenCV 依赖配置详解 项目提供两种 OpenCV 依赖配置方式:使用 xmake 包管理(推荐)和手动指定系统 OpenCV。 #### 方式一:使用 xmake 包管理(推荐)✅ **优点**: - ✅ 自动下载和编译 - ✅ 版本可控 - ✅ 跨平台一致 - ✅ 无需手动配置路径 **配置方法**: ```lua -- 1. 声明依赖(文件开头) add_requires("opencv", {configs = {contrib = true}}) -- 2. 在 target 中添加包 target("tensorrt_infer") add_packages("opencv") ``` **完整示例**: ```lua add_rules("mode.debug", "mode.release") set_languages("c++17") -- 声明 OpenCV 依赖(包含 contrib 模块) add_requires("opencv", {configs = {contrib = true}}) target("tensorrt_infer") set_kind("binary") add_files("src/**/*.cpp") add_packages("opencv") -- 自动包含头文件路径和链接库 ``` **查看 OpenCV 安装路径**: ```bash # 查看 xmake安装的OpenCV 位置 xmake require --info opencv # 输出示例: # package: opencv # version: 4.8.1 # install_dir: ~/.xmake/packages/o/opencv/4.8.1/... ``` --- #### 方式二:手动指定系统 OpenCV 如果你已经通过 `apt`、`yum` 或其他方式安装了 OpenCV,可以不使用 xmake 的包管理。 **适用场景**: - 🔸 系统已安装 OpenCV - 🔸 需要使用特定版本的系统 OpenCV - 🔸 离线环境无法使用 xmake 包管理 **步骤 1:移除 xmake 的 OpenCV 依赖** ```lua -- 删除或注释掉这行 -- add_requires("opencv", {configs = {contrib = true}}) ``` **步骤 2:使用 pkg-config 获取 OpenCV 配置** ```bash # 验证系统是否安装 OpenCV pkg-config --modversion opencv4 # 输出:4.8.1 # 获取编译参数 pkg-config --cflags opencv4 # 输出:-I/usr/include/opencv4 # 获取链接参数 pkg-config --libs opencv4 # 输出:-lopencv_core -lopencv_imgproc ... ``` **步骤 3:在 xmake.lua 中手动配置** **方法 A:使用 pkg-config 集成(推荐)** ```lua add_rules("mode.debug", "mode.release") set_languages("c++17") -- 移除 add_requires("opencv") target("tensorrt_infer") set_kind("binary") add_files("src/**/*.cpp") -- 使用 pkg-config 集成 OpenCV add_packages("pkgconfig::opencv4") -- 或者手动指定(如果 pkg-config 不可用) -- add_cxflags("$(shell pkg-config --cflags opencv4)") -- add_ldflags("$(shell pkg-config --libs opencv4)") ``` **方法 B:硬编码路径(不推荐,仅限特殊场景)** ```lua target("tensorrt_infer") set_kind("binary") add_files("src/**/*.cpp") -- 手动添加 OpenCV头文件路径 add_includedirs("/usr/include/opencv4") add_includedirs("/usr/include") -- 手动添加 OpenCV 链接库 add_links( "opencv_core", "opencv_imgproc", "opencv_imgcodecs", "opencv_highgui", "opencv_videoio" ) -- 添加库搜索路径(如果需要) add_linkdirs("/usr/lib/x86_64-linux-gnu") ``` **完整的混合配置示例**: ```lua add_rules("mode.debug", "mode.release") set_languages("c++17") -- 其他依赖仍使用 xmake 管理 add_requires("spdlog") add_requires("fmt") add_requires("cli11") add_requires("stb") -- 注释掉 OpenCV 的 xmake 依赖 -- add_requires("opencv", {configs = {contrib = true}}) target("tensorrt_infer") set_kind("binary") add_files("src/**/*.cpp") add_headerfiles("src/(**.hpp)") add_includedirs("src") -- 添加其他依赖包 add_packages("spdlog", "fmt", "cli11", "stb") -- 手动添加系统 OpenCV add_packages("pkgconfig::opencv4") -- 添加 CUDA/TensorRT 配置 add_cuda_tensorrt_config() ``` --- #### 常见问题 **Q1: 编译时提示找不到 `opencv2/opencv.hpp`?** A: 检查头文件路径是否正确: ```lua -- 如果是 xmake安装的OpenCV add_packages("opencv") -- xmake 会自动处理路径 -- 如果是系统 OpenCV add_includedirs("/usr/include/opencv4") -- 确保路径正确 ``` **Q2: 链接时提示找不到 OpenCV 库?** A: 检查库路径和链接库名称: ```bash # 查看系统 OpenCV 库位置 pkg-config --libs opencv4 ``` 确保 `add_links()` 中的库名称与输出一致。 **Q3: 如何切换 OpenCV 版本?** A: 使用 xmake 包管理时,可以指定版本: ```lua -- 指定特定版本 add_requires("opencv 4.8.1", {configs = {contrib = true}}) -- 或者使用版本范围 add_requires("opencv >=4.5.0", {configs = {contrib = true}}) ``` **Q4: 如何禁用 OpenCV contrib 模块?** A: 修改配置即可: ```lua -- 不使用 contrib 模块 add_requires("opencv", {configs = {contrib = false}}) -- 或者直接删除 configs 参数 add_requires("opencv") ``` --- 为方便使用,可以创建简单的构建脚本: ```bash #!/bin/bash # build.sh - 一键构建脚本 set -e echo "🔧 配置构建环境..." xmake f -p linux -a x86_64 -m release echo "🚀 开始编译..." xmake -v echo "✅ 构建完成!" echo "📦 可执行文件:" ls -lh build/linux/x86_64/release/ ``` 使用方法: ```bash chmod +x build.sh ./build.sh ``` --- ### 常见问题 #### Q: xmake 找不到命令? A: 安装后需要重启终端,或者手动加载环境变量: ```bash source ~/.xmake/profile ``` #### Q: 如何切换 Debug/Release 模式? A: 使用以下命令切换: ```bash xmake config -m debug # Debug 模式 xmake config -m release # Release 模式 ``` #### Q: 如何查看编译详细输出? A: 使用 `-v` 参数: ```bash xmake -v # 显示详细信息 xmake -vD # 显示调试信息 ``` #### Q: 如何只编译部分目标? A: 指定目标名称: ```bash xmake tensorrt_infer # 只编译主程序 xmake api_example # 只编译示例 xmake simple_manager_example # SimpleModelManager 示例 xmake batch_manager_example # EnhancedBatchManager 示例 ``` #### Q: 如何清理重新编译? A: ```bash xmake clean && xmake -v ``` --- ### ⚠️ 错误处理与故障排查 #### 错误 1: 模型加载失败 **现象**: ``` [ERROR] Failed to load model: models/yolo11n.engine ``` **可能原因**: 1. 模型文件路径不正确 2. 模型文件不存在或损坏 3. TensorRT 版本不兼容 4. GPU 驱动问题 **解决方案**: ```bash # 1. 检查模型文件是否存在 ls -lh models/yolo11n.engine # 2. 确认 TensorRT 安装 nvcc --version ldconfig -p | grep nvinfer # 3. 重新导出模型 python3 export_model.py --weights yolo11n.pt --format engine ``` --- #### 错误 2: CUDA out of memory **现象**: ``` [ERROR] CUDA error: out of memory ``` **可能原因**: 1. GPU 显存不足 2. Batch Size 设置过大 3. 其他程序占用显存 **解决方案**: ```bash # 1. 查看 GPU 显存使用情况 nvidia-smi # 2. 减小 Batch Size ./tensorrt_infer -b models/yolo11n.engine det ./images/ --batch-size 4 # 3. 关闭其他占用显存的程序 ``` --- #### 错误 3: 图像加载失败 **现象**: ``` [ERROR] Failed to load image: input.jpg ``` **可能原因**: 1. 图像文件不存在 2. 图像格式不支持 3. 文件权限问题 **解决方案**: ```bash # 1. 检查文件是否存在 ls -lh input.jpg # 2. 确认支持的格式 # 支持:.jpg, .jpeg, .png, .bmp # 3. 检查文件权限 chmod 644 input.jpg ``` --- #### 错误 4: 推理结果为空 **现象**: ``` [INFO] 检测到 0 个目标 ``` **可能原因**: 1. 置信度阈值设置过高 2. 图像中没有目标 3. 模型不适合当前场景 **解决方案**: ```bash # 1. 降低置信度阈值 ./tensorrt_infer models/yolo11n.engine det input.jpg --confidence 0.1 # 2. 更换测试图像 # 使用包含清晰目标的图像 # 3. 检查模型类型是否匹配 # 检测模型用 det,分割模型用 seg ``` --- #### 错误 5: 可视化结果异常 **现象**: - 检测框位置不正确 - 颜色异常 - 图像尺寸不对 **可能原因**: 1. 坐标映射错误 2. LetterBox 填充问题 3. 原图尺寸异常 **解决方案**: ```bash # 1. 启用详细日志查看中间结果 ./tensorrt_infer models/yolo11n.engine det input.jpg -v # 2. 检查预处理参数 # 默认输入尺寸:640×640 # 3. 尝试不同尺寸的图像 # 验证是否为特定尺寸问题 ``` --- #### 错误 6: 批量处理性能低 **现象**: - 批量处理速度慢 - CPU/GPU 利用率低 **可能原因**: 1. 线程数设置不当 2. I/O 瓶颈 3. GPU 调度问题 **解决方案**: ```bash # 1. 调整 Batch Size ./tensorrt_infer -b models/yolo11n.engine det ./images/ --batch-size 8 # 2. 使用 SSD 存储 # 避免网络存储的 I/O 延迟 # 3. 监控 GPU 利用率 watch -n 1 nvidia-smi ``` --- #### 错误 7: 编译错误 - 找不到 CUDA/TensorRT **现象**: ``` error: cannot find cuda include directory error: cannot find nvinfer ``` **解决方案**: ```lua -- 在 xmake.lua 中修改 CUDA/TensorRT 路径 target("tensorrt_infer") add_includedirs("/your/custom/cuda/include") add_linkdirs("/your/custom/cuda/lib64") add_includedirs("/your/custom/tensorrt/include") add_linkdirs("/your/custom/tensorrt/lib") ``` --- #### 错误 8: 程序退出时出现 CUDA 错误日志 **现象**: ``` CUDA context cleanup error ``` **解决方案**: 已在新版 API 中修复,确保使用最新版本的 `InferenceAPI`: ```cpp // ✅ 正确:使用栈上对象,自动清理 { InferenceAPI api; api.initialize("model.engine", "det"); // ... } // 自动清理,无 CUDA 错误 // ❌ 错误:不要使用裸指针 InferenceAPI* api = new InferenceAPI(); // 忘记 delete 会导致资源泄漏 ``` --- ### 💡 调试技巧 #### 1. 启用详细日志 ```bash # 全局详细日志 ./tensorrt_infer models/yolo11n.engine det input.jpg -v # 或在代码中设置 spdlog::set_level(spdlog::level::debug); ``` #### 2. 查看预处理结果 ```cpp // 在 preprocessor.hpp 中添加调试输出 spdlog::debug("Input size: {}x{}", input_width, input_height); spdlog::debug("Output vector size: {}", output.size()); ``` #### 3. 监控 GPU 内存 ```bash # 实时监控 watch -n 1 nvidia-smi # 或使用 nvtop(如果安装) nvtop ``` #### 4. 性能分析 ```cpp // 使用 PerformanceTimer PerformanceTimer timer; timer.start(); // ... 执行操作 ... timer.stop(); spdlog::info("耗时:{:.2f} ms", timer.elapsed_ms()); ``` --- --- ### 运行示例 使用编译好的程序进行推理: ```bash # 查看帮助信息 xmake run tensorrt_infer -- --help # 单张目标检测 xmake run tensorrt_infer -- models/yolo11n.engine det bus.jpg # 单张语义分割 xmake run tensorrt_infer -- models/yolo11n-seg.engine seg bus.jpg # 批量处理(使用 -b 或 --batch 标志) xmake run tensorrt_infer -- -b models/yolo11n.engine det ./images/ -O ./output/ # 带详细输出的批量处理 xmake run tensorrt_infer -- -b models/yolo11n.engine det ./images/ -O ./output/ -v # 指定置信度阈值 xmake run tensorrt_infer -- models/yolo11n.engine det bus.jpg --confidence 0.5 # 或者直接执行二进制文件 ./build/linux/x86_64/release/tensorrt_infer models/yolo11n.engine det input.jpg ``` ### 📡 API 使用说明 项目提供灵活的 C++ API,支持**一次加载、多次推理、按需清理**的使用模式。 #### 💡 典型使用流程 ``` 1. 创建 API 对象 (InferenceAPI api) ↓ 2. 加载模型 (initialize) ↓ 3. 单次或批量推理 (inferImage / inferBatch / inferSegmentation) ↓ 4. 重复步骤 3(可选,多次推理) ↓ 5. 可视化或其他处理 ↓ 6. 自动清理(离开作用域时析构函数自动释放资源) ``` ### API 核心类:InferenceAPI **特性**: - ✅ 极简接口,开箱即用(默认置信度 0.2) - ✅ 支持单图和批量处理 - ✅ **返回 cv::Mat 格式检测结果**(目标检测) - ✅ **返回 pair**(语义分割) - ✅ 自动管理模型加载和释放 - ✅ **非单例设计**,资源管理清晰 - ✅ 支持栈上和堆上两种使用方式 - ✅ **可动态配置**置信度阈值 ### 快速开始 #### 方式 1: 栈上对象(最简单,推荐) **特点**: - ✅ 作用域结束时自动清理资源 - ✅ 代码简洁,不易出错 - ✅ 适合大多数场景 ```cpp #include "api/inference_api.hpp" int main() { // 1. 创建 API 对象(栈上) InferenceAPI api; // 2. 加载模型 if (!api.initialize("models/yolo11n.engine", "det")) { spdlog::error("模型加载失败"); return -1; } // 3. 第一次推理 cv::Mat result1 = api.inferImage("image1.jpg"); spdlog::info("图 1 检测到 {} 个目标", result1.rows); // 4. 第二次推理(复用已加载的模型) cv::Mat result2 = api.inferImage("image2.jpg"); spdlog::info("图 2 检测到 {} 个目标", result2.rows); // 5. 批量推理(可选) std::vector images = {"img3.jpg", "img4.jpg", "img5.jpg"}; std::vector batch_results = api.inferBatch(images); return 0; } // 离开作用域时自动清理,无需手动释放 ``` --- #### 方式 2: 堆上对象(灵活控制生命周期) **特点**: - ✅ 使用智能指针管理生命周期 - ✅ 适合需要动态控制对象的场景 - ✅ 可以在多个函数间共享 ```cpp #include "api/inference_api.hpp" #include int main() { // 1. 创建 API 对象(堆上,使用智能指针) auto api = std::make_unique(); // 2. 加载模型 if (!api->initialize("models/yolo11n.engine", "det")) { spdlog::error("模型加载失败"); return -1; } // 3. 单图推理 cv::Mat result = api->inferImage("input.jpg"); // 4. 批量推理 std::vector image_paths = {"img1.jpg", "img2.jpg", "img3.jpg"}; std::vector results = api->inferBatch(image_paths); // 5. 显式清理(可选,reset() 会自动调用析构函数) api.reset(); return 0; } ``` ### API 接口详解 #### 1. 初始化模型 ```cpp bool initialize(const std::string& engine_path, const std::string& model_type); ``` **参数**: - `engine_path`: TensorRT 引擎文件路径(如 `models/yolo11n.engine`) - `model_type`: 模型类型 - `"det"`: 目标检测模型 - `"seg"`: 语义分割模型 **返回值**: - `true`: 初始化成功 - `false`: 初始化失败 **示例**: ```cpp InferenceAPI api; if (!api.initialize("yolo11n.engine", "det")) { // 处理错误 } ``` --- #### 2.1 配置置信度阈值(重要) ```cpp void setConfidenceThreshold(float threshold); ``` **参数**: - `threshold`: 置信度阈值,范围 0.0-1.0,默认值 0.2 **示例**: ```cpp InferenceAPI api; api.initialize("models/yolo11n.engine", "det"); // 使用默认置信度 (0.2) 推理 auto result1 = api.inferImage("input.jpg"); // 调整置信度阈值为 0.5(更严格) api.setConfidenceThreshold(0.5f); auto result2 = api.inferImage("input2.jpg"); // 降低置信度阈值为 0.1(检测更多目标) api.setConfidenceThreshold(0.1f); auto result3 = api.inferImage("input3.jpg"); ``` **注意**: - ✅ 置信度配置会传递到所有层级(解析、可视化) - ✅ 可以在多次推理之间动态调整 - ✅ 避免在不同地方使用不同的硬编码值 --- #### 2. 单图目标检测 ```cpp cv::Mat inferImage(const std::string& image_path); ``` **参数**: - `image_path`: 输入图像路径 **返回值**: - `cv::Mat`: `[N, 6]` 格式的检测结果 - `N`: 检测到的目标数量 - 每行数据:`[x1, y1, x2, y2, confidence, class_id]` - 如果失败,返回空 `cv::Mat` **输出格式说明**: | 索引 | 字段 | 类型 | 说明 | |------|------|------|------| | 0 | x1 | float | 左上角 X 坐标 | | 1 | y1 | float | 左上角 Y 坐标 | | 2 | x2 | float | 右下角 X 坐标 | | 3 | y2 | float | 右下角 Y 坐标 | | 4 | confidence | float | 置信度 (0.0-1.0) | | 5 | class_id | float | 类别 ID (整数) | **示例**: ```cpp cv::Mat detections = api.inferImage("bus.jpg"); for (int i = 0; i < detections.rows; ++i) { float* box = detections.ptr(i); std::cout << "目标 " << i << ": " << "置信度=" << box[4] << " 类别=" << static_cast(box[5]) << std::endl; } ``` --- #### 3. 语义分割推理 ```cpp std::pair inferSegmentation(const std::string& image_path); ``` **参数**: - `image_path`: 输入图像路径 **返回值**: - `std::pair`: - `first`: `output0` - `[300, 38]` 检测框 + 类别概率 + mask 系数 - 每行包含:`[x1, y1, x2, y2, confidence, class_id, ...mask_coeffs(32 个)]` - `second`: `output1` - `[32, 25600]` (NCHW 原型掩码特征 [32,160,160]) **示例**: ```cpp InferenceAPI api; if (!api.initialize("yolo11n-seg.engine", "seg")) { spdlog::error("模型加载失败"); return -1; } // 推理并获取原始输出 auto [output0, output1] = api.inferSegmentation("bus.jpg"); if (!output0.empty() && !output1.empty()) { spdlog::info("✅ 语义分割推理成功!"); spdlog::info("Output0 (检测框 + 掩码系数): {} x {}, type={}", output0.rows, output0.cols, output0.type()); spdlog::info("Output1 (原型掩码): {} x {}, type={}", output1.rows, output1.cols, output1.type()); // output1: [32, 25600] (NCHW 布局,32 通道×160×160) // 解析 output0 的前 3 个检测框 for (int i = 0; i < std::min(3, output0.rows); ++i) { const float* row = output0.ptr(i); spdlog::info(" 框 {}: [x1={:.2f}, y1={:.2f}, x2={:.2f}, y2={:.2f}, conf={:.4f}, class={:.0f}]", i, row[0], row[1], row[2], row[3], row[4], row[5]); } // 查看 output1 的统计信息 double min_val, max_val; cv::minMaxLoc(output1, &min_val, &max_val); spdlog::info("Output1 统计:Min={:.6f}, Max={:.6f}", min_val, max_val); } ``` --- ### ⚠️ 语义分割 API 重要说明 **`inferSegmentation()` 返回的是模型原始输出,mask 系数未经坐标重映射!** #### 问题说明 YOLOv11-seg 语义分割模型的输出结构: - **output0**: `[300, 38]` = 检测框 (4) + 置信度 (1) + 类别 (1) + mask 系数 (32) - ⚠️ x1,y1,x2,y2 是模型空间坐标(640×640),需要 Letterbox 逆变换 - ⚠️ **mask 系数对应 160×160 原型掩码,也需要 Letterbox 逆变换** - **output1**: `[32, 25600]` (NCHW 原型掩码特征 [32,160,160]) - ⚠️ 这些原型掩码是在 160×160 分辨率下生成的,未考虑原图尺寸和 letterbox 变换 #### Mask 生成流程 ``` 1. 提取 output0 的 32 个 mask 系数:coeffs[32] 2. 从 output1 重建 32 个 160×160 原型掩码:proto_masks[32][160][160] 3. 线性组合:mask_160 = Σ(coeffs[i] × proto_masks[i]) 4. Sigmoid 激活 5. 二值化 6. ⚠️ 逆向 Letterbox 变换(当前未实现,待修复) ``` #### 坐标映射问题 - ✅ **检测框坐标**:会通过 `visualize()` 自动重映射 - ❌ **Mask 系数**:当前未重映射,直接使用可能导致位置偏差 对于长宽比差异较大的图像,直接使用 mask 系数会导致: - Mask 位置偏移 - 分割区域不准确 - 边缘对齐误差 #### 修复方案 详见 [`SEGMENTATION_MASK_REMAP_GUIDE.md`](SEGMENTATION_MASK_REMAP_GUIDE.md) 文档,提供三种修复方案: 1. **方案 1**:在 `PreprocessResult` 中添加 `remapMask()` 函数(推荐) 2. **方案 2**:修改 API 返回值(破坏性变更) 3. **方案 3**:添加工具函数(最简单) #### 临时解决方案 如果需要正确的 mask,可以手动实现坐标重映射: ```cpp // 伪代码示例 auto [output0, output1] = api.inferSegmentation("image.jpg"); // 1. 提取 mask 系数 std::vector coeffs(32); for (int c = 0; c < 32; ++c) { coeffs[c] = output0.at(0, 6 + c); // 第 7 列开始是 mask 系数 } // 2. 重建 160×160 的 mask cv::Mat mask_160(160, 160, CV_32F, cv::Scalar(0)); for (int c = 0; c < 32; ++c) { const float* proto_row = output1.ptr(c); for (int y = 0; y < 160; ++y) { for (int x = 0; x < 160; ++x) { int idx = y * 160 + x; mask_160.at(y, x) += coeffs[c] * proto_row[idx]; } } } // 3. Sigmoid + 二值化 cv::Mat mask_binary; cv::threshold(mask_160, mask_binary, 0.0f, 255.0f, cv::THRESH_BINARY); // 4. ⚠️ 这里需要添加 Letterbox 逆变换(待实现) // cv::Mat mask_original = remapMask(mask_binary, resize_params); ``` --- #### 4. 批量推理 ```cpp std::vector inferBatch(const std::vector& image_paths); ``` **参数**: - `image_paths`: 图像路径列表 **返回值**: - `std::vector`: 每张图的检测结果,每个 `Mat` 格式为 `[N, 6]` **示例**: ```cpp std::vector images = {"img1.jpg", "img2.jpg", "img3.jpg"}; std::vector results = api.inferBatch(images); for (size_t i = 0; i < results.size(); ++i) { std::cout << "图 " << i+1 << ": " << results[i].rows << " 个目标" << std::endl; } ``` --- #### 5. 可视化结果 ```cpp bool visualize(const std::string& image_path, const std::string& output_path); ``` **参数**: - `image_path`: 输入图像路径 - `output_path`: 输出图像路径(保存检测结果) **返回值**: - `true`: 可视化成功 - `false`: 可视化失败 **示例**: ```cpp if (api.visualize("input.jpg", "output.jpg")) { std::cout << "可视化已保存到 output.jpg" << std::endl; } ``` --- #### 6. 辅助函数 ```cpp // 检查是否已初始化 bool isInitialized() const; // 获取类别名称 std::string getClassName(int class_id) const; ``` **示例**: ```cpp if (api.isInitialized()) { std::string class_name = api.getClassName(0); // "person" } ``` --- ### 便捷函数 为简化使用,API 提供了两个便捷函数: #### 1. detectObject - 单图检测 ```cpp cv::Mat detectObject( const std::string& engine_path, const std::string& model_type, const std::string& image_path ); ``` **特点**: - 自动加载和释放模型 - 一次性调用,无需手动管理生命周期 - 适合偶尔调用场景 **示例**: ```cpp cv::Mat result = detectObject("yolo11n.engine", "det", "input.jpg"); ``` --- #### 2. detectObjectsBatch - 批量检测 ```cpp std::vector detectObjectsBatch( const std::string& engine_path, const std::string& model_type, const std::vector& image_paths ); ``` **特点**: - 自动管理模型生命周期 - 批量处理多张图像 - 适合一次性批量任务 **示例**: ```cpp std::vector images = {"img1.jpg", "img2.jpg", "img3.jpg"}; std::vector results = detectObjectsBatch( "yolo11n.engine", "det", images ); ``` --- ### 完整示例代码 详见 [`examples/api_example.cpp`](examples/api_example.cpp): ```cpp #include "api/inference_api.hpp" #include int main() { // 方式 1: 使用便捷函数 cv::Mat result = detectObject( "models/yolo11n.engine", "det", "input.jpg" ); // 方式 2: 使用单例类 auto& api = InferenceAPI::getInstance(); api.initialize("models/yolo11n.engine", "det"); cv::Mat detection = api.inferImage("input.jpg"); api.visualize("input.jpg", "output.jpg"); return 0; } ``` ### 编译 API 示例 ```bash # 使用 xmake 编译基础示例 xmake api_example # 运行基础示例 xmake run api_example # 编译高级示例(一次加载、多次推理) xmake api_advanced_example # 运行高级示例 xmake run api_advanced_example # 或直接执行 ./build/linux/x86_64/release/api_example ./build/linux/x86_64/release/api_advanced_example ``` **示例文件说明**: - `examples/api_example.cpp`: 基础 API 使用示例 - `examples/api_advanced_example.cpp`: 高级使用模式(一次加载、多次推理)✨ **新增批量语义分割** - 基本多次推理(栈上对象) - 混合推理模式(单次 + 批量) - 语义分割 API 测试 - 完整可视化流程(批量目标检测) - **批量语义分割推理** ✨ 新增 - 性能对比 - 错误处理 - `examples/simple_manager_example.cpp`: SimpleModelManager 使用示例 - `examples/batch_manager_example.cpp`: EnhancedBatchManager 使用示例 --- ### 📝 示例代码 #### InferenceAPI 示例 **基础示例** (`examples/api_example.cpp`): ```cpp #include "api/inference_api.hpp" int main() { // 方式 1: 使用便捷函数(最简单) cv::Mat result = detectObject( "models/yolo11n.engine", "det", "input.jpg" ); // 方式 2: 使用栈上对象(推荐) { InferenceAPI api; if (!api.initialize("models/yolo11n.engine", "det")) { return -1; } // 单图推理 cv::Mat detection = api.inferImage("input.jpg"); // 批量推理 std::vector images = {"img1.jpg", "img2.jpg", "img3.jpg"}; std::vector results = api.inferBatch(images); // 可视化 api.visualize("input.jpg", "output.jpg"); } // 自动清理资源 return 0; } ``` **编译和运行**: ```bash # 编译 xmake api_example # 运行 xmake run api_example ``` --- #### SimpleModelManager 示例 **示例代码** (`examples/simple_manager_example.cpp`): ```cpp #include "engine/simple_model_manager.hpp" int main() { SimpleModelManager manager; // 加载模型 if (!manager.loadAndInitialize("models/yolo11n.engine", ModelType::DETECTION)) { return -1; } // 推理(推荐方式:infer() + SimpleVisualizer) auto result = manager.infer("data/inputs/bus_1.jpg"); // 加载原始图像 auto image_data = ImageProcessingPipeline::loadImage("data/inputs/bus_1.jpg"); // 获取预处理参数 auto preprocess_result = ImageProcessingPipeline::loadAndPreprocess( "data/inputs/bus_1.jpg", 640, 640, true); PreprocessResult prep_struct( std::move(preprocess_result.first), preprocess_result.second, image_data.width, image_data.height ); // 运行可视化流程 SimpleVisualizer::runVisualization( "data/inputs/bus_1.jpg", result.outputs, prep_struct, "data/outputs/result.jpg", 0.2f // 置信度阈值 ); // 查看检测结果 if (!result.empty()) { spdlog::info("检测到 {} 个目标", result.rows); } return 0; } ``` **特点**: - ✅ 最简单的 API,一行代码完成推理 + 可视化 - ✅ 自动处理所有细节(预处理、推理、后处理) - ✅ 适合快速验证和简单应用场景 **编译和运行**: ```bash # 编译 xmake simple_manager_example # 运行 xmake run simple_manager_example ``` --- #### EnhancedBatchManager 示例 **示例代码** (`examples/batch_manager_example.cpp`): ```cpp #include "engine/enhanced_batch_manager.hpp" #include "engine/config_manager.hpp" int main() { // 1. 创建配置管理器 ConfigManager config; config.setFloat(ConfigManager::ConfigKey::CONFIDENCE_THRESHOLD, 0.3f); config.setInt(ConfigManager::ConfigKey::BATCH_SIZE, 8); // 2. 创建批量管理器 EnhancedBatchManager manager(config); // 3. 加载模型 if (!manager.loadAndInitialize("models/yolo11n.engine", ModelType::DETECTION)) { return -1; } // 4. 准备图像列表 std::vector image_paths = { "data/inputs/bus_1.jpg", "data/inputs/bus_2.jpg", "data/inputs/bus_3.jpg" }; // 5. 批量处理并可视化 auto results = manager.processBatchAndVisualize( image_paths, "data/outputs/batch_result", true // 显示详细日志 ); return 0; } ``` **特点**: - ✅ 智能批量处理策略(小批量顺序,大批量并发) - ✅ 多线程并发,性能提升 3-5 倍 - ✅ 自动负载均衡和资源管理 - ✅ 完整的统计信息和性能监控 **编译和运行**: ```bash # 编译 xmake batch_manager_example # 运行 xmake run batch_manager_example ``` --- ### 注意事项 1. **内存管理**: - 使用便捷函数时,模型会自动加载和释放 - 使用单例类时,确保在程序结束时释放资源 2. **线程安全**: - `InferenceAPI` 是单例模式,内部已处理线程安全 - 多线程环境下可安全调用 3. **错误处理**: - 检查 `initialize()` 返回值确保初始化成功 - 检查推理结果是否为空 `Mat` 4. **性能建议**: - 批量处理时使用 `inferBatch()` 而非循环调用 `inferImage()` - 多次调用时推荐使用单例类,避免重复加载模型 --- ## 💡 核心优势 ### 传统推理框架的问题 大多数推理框架的后处理都是黑盒: ``` 推理 → 解析输出 → 置信度过滤 → NMS → 坐标映射 → 可视化 ``` 这种设计存在以下问题: 1. **缺乏灵活性**:不同的应用场景需要不同的后处理策略 2. **难以调试**:黑盒的后处理过程不利于问题排查 3. **性能损耗**:不必要的后处理步骤影响性能 4. **学习成本高**:用户需要了解复杂的后处理逻辑 ### 我们的解决方案 采用模块化设计,提供清晰的 API: ``` SimpleModelManager: infer() - 执行推理 + SimpleVisualizer - 可视化 EnhancedBatchManager: processBatchAndVisualize() - 智能批量处理 ``` 优势: 1. **完全掌控**:提供完整的后处理功能,同时保持代码清晰 2. **易于调试**:详细的日志输出和清晰的调用链 3. **高性能**:使用 TensorRT 10.10 和多线程优化 4. **简洁高效**:main.cpp 仅 142 行,职责清晰 ## 📝 总结 **TensorRT Infer** 是一个现代化的高性能推理框架,提供完整的图像预处理、TensorRT推理、后处理和可视化功能。 ### 核心特性 - ✅ **双模式支持**:SimpleModelManager(单图)+ EnhancedBatchManager(批量) - ✅ **完整功能**:从图像加载到结果可视化的端到端流程 - ✅ **高性能**:TensorRT 10.10 + 多线程优化 - ✅ **易用性**:简洁的 CLI 接口(-b 批量模式,-O 输出目录) - ✅ **模块化**:清晰的代码结构(core/utils/types/visualization) ### 适用场景 - 🔹 需要快速部署 YOLO 系列模型的推理应用 - 🔹 需要批量处理大量图像的场景 - 🔹 需要完全掌控推理流程的开发者 - 🔹 学习和研究 TensorRT推理的最佳实践 如果你需要一个开箱即用、内置完整后处理的框架,那么这个项目非常适合你! ---

Made with ❤️ by calacaly