# 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推理工具 - 现代化高性能推理框架
**高性能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