# YOLOs-CPP-EdgePlatform **Repository Path**: study-dp/yolos-cpp-edgeplatform ## Basic Information - **Project Name**: YOLOs-CPP-EdgePlatform - **Description**: No description available - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 7 - **Created**: 2025-10-09 - **Last Updated**: 2025-10-09 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # YOLOs-CPP-EdgePlatform (EdgePlatform Edition)
**专为边缘AI平台打造的 Header-Only YOLO 推理库** [![平台](https://img.shields.io/badge/平台-RDKx5%20|%20RK3588-blue)](https://gitee.com/FANKYT/yolos-cpp-edgeplatform) [![版本](https://img.shields.io/badge/版本-v1.0.0-green)](https://gitee.com/FANKYT/yolos-cpp-edgeplatform) [![许可证](https://img.shields.io/badge/许可证-MIT-orange)](LICENSE_INFO.md) [![语言](https://img.shields.io/badge/语言-C++14-red)](https://gitee.com/FANKYT) [![作者](https://img.shields.io/badge/作者-FANKYT-purple)](https://gitee.com/FANKYT) 针对 **D-Robotics RDKx5 (BPU)** 和 **Rockchip RK3588 (NPU)** 平台优化的 YOLO 目标检测库 参考 [YOLOs-CPP](https://github.com/Geekgineer/YOLOs-CPP) 的优雅设计 | 专为边缘计算打造
--- ## 📖 目录 - [项目简介](#-项目简介) - [核心特性](#-核心特性) - [项目结构](#-项目结构) - [快速开始](#-快速开始) - [API 文档](#-api-文档) - [模型准备](#-模型准备) - [版本对比](#-版本对比) - [性能优化](#-性能优化) - [常见问题](#-常见问题) - [开发计划](#-开发计划) - [致谢](#-致谢) --- ## 🎯 项目简介 **YOLOs-CPP-EdgePlatform** 是一个高性能的 YOLO 目标检测推理库,专为边缘AI平台设计。本项目借鉴了优秀开源项目 [YOLOs-CPP](https://github.com/Geekgineer/YOLOs-CPP) 的 **header-only** 设计理念,并针对嵌入式平台(RDKx5 BPU / RK3588 NPU)进行了深度优化。 ### 为什么选择 YOLOs-CPP-EdgePlatform? | 特性 | 传统方案 | YOLOs-CPP-EdgePlatform ✨ | |------|---------|-----------------| | **集成方式** | 编译库 + 链接 | 一个 `#include` | | **代码量** | 数百行样板代码 | **3 行代码** | | **版本切换** | 重新编写 | 换个头文件 | | **学习成本** | 需理解底层API | 只需了解接口 | | **内存管理** | 手动释放 | RAII 自动管理 | | **性能监控** | 手动计时 | ScopedTimer 自动 | ### 设计理念 ```cpp // 传统方式:需要 800+ 行代码 // - 模型加载 // - 图像预处理 // - 推理执行 // - 后处理解码 // - NMS筛选 // - 坐标还原 // - 内存释放 // YOLOs-CPP-EdgePlatform:3 行代码搞定! YOLO11Detector detector("model.bin", "coco.names"); auto results = detector.detect(image); // 完成!✨ ``` --- ## ✨ 核心特性 ### 🚀 易用性 - ✅ **Header-Only 设计** - 无需编译库,只需 `#include` - ✅ **统一 API 接口** - 所有 YOLO 版本共享相同接口 - ✅ **3 行代码检测** - 极简使用体验 - ✅ **完整中文注释** - 代码即文档 ### ⚡ 性能 - ✅ **BPU/NPU 硬件加速** - 充分利用专用AI芯片 - ✅ **零拷贝架构** - 最小化内存开销 - ✅ **提前过滤优化** - 避免无效计算 - ✅ **DFL 高效实现** - Distribution Focal Loss 优化 ### 🎨 完整性 - ✅ **YOLOv5** - Anchor-based,NV12输入 - ✅ **YOLOv8** - Anchor-free + DFL - ✅ **YOLOv11** - 最新架构,精度最高 ### 🛠️ 工程化 - ✅ **RAII 资源管理** - 自动内存管理 - ✅ **ScopedTimer 计时** - 性能分析工具 - ✅ **异常安全** - 完善的错误处理 - ✅ **详细文档** - README、快速指南、架构文档 --- ## 📁 项目结构 ``` YOLOs-CPP-EdgePlatform/ ├── include/ # 头文件目录 │ ├── det/ # 检测器实现 │ │ ├── BaseDetector.hpp # 抽象基类(统一接口) │ │ ├── YOLO5_RDK.hpp # YOLOv5 实现(Anchor-based) │ │ ├── YOLO8_RDK.hpp # YOLOv8 实现(DFL) │ │ └── YOLO11_RDK.hpp # YOLOv11 实现(最新) │ └── tools/ # 工具类 │ ├── Config.hpp # 编译配置宏 │ ├── ScopedTimer.hpp # RAII 计时器 │ └── Common.hpp # 通用数据结构 ├── examples/ # 示例程序 │ └── yolo11_detection_example.cpp ├── models/ # 模型文件目录 │ └── coco.names # COCO 80类标签 ├── README.md # 项目文档(本文件) ├── QUICKSTART.md # 快速上手指南 ├── ARCHITECTURE.md # 架构设计文档 ├── PROJECT_SUMMARY.md # 项目总结 ├── LICENSE_INFO.md # 版权信息 ├── build.sh # 一键编译脚本 └── CMakeLists.txt # CMake 配置 ``` **核心文件说明:** | 文件 | 行数 | 功能 | 作者 | |------|------|------|------| | `BaseDetector.hpp` | ~180 | 抽象基类,定义统一接口 | FANKYT | | `YOLO5_RDK.hpp` | ~550 | YOLOv5 完整实现 | FANKYT | | `YOLO8_RDK.hpp` | ~530 | YOLOv8 完整实现 | FANKYT | | `YOLO11_RDK.hpp` | ~530 | YOLOv11 完整实现 | FANKYT | | `ScopedTimer.hpp` | ~55 | 性能计时工具 | FANKYT | --- ## 🚀 快速开始 ### 1️⃣ 环境要求 #### 硬件平台 - ✅ D-Robotics RDKx5 (BPU) - 🔜 Rockchip RK3588 (NPU) [计划中] #### 软件依赖 **Ubuntu/Debian 系统:** ```bash # 安装 OpenCV sudo apt update sudo apt install -y libopencv-dev # 确认 BPU 库已安装 ls /usr/include/dnn/hb_dnn.h ls /usr/lib/libdnn.so ``` **RDKx5 开发环境:** - 系统镜像:RDK System 3.0+ - 工具链:gcc 7.5+ / g++ 7.5+ - CMake:3.10+ --- ### 2️⃣ 使用示例 #### 最简示例(3 行代码) ```cpp #include "det/YOLO11_RDK.hpp" using namespace yolos_ep; int main() { // 1. 初始化检测器 YOLO11Detector detector("yolo11n.bin", "coco.names"); // 2. 加载图像并检测 cv::Mat image = cv::imread("test.jpg"); auto results = detector.detect(image); // 3. 完成!results 包含所有检测结果 std::cout << "检测到 " << results.size() << " 个目标" << std::endl; return 0; } ``` #### 完整示例(带可视化) ```cpp #include #include #include "det/YOLO11_RDK.hpp" using namespace yolos_ep; int main(int argc, char** argv) { if (argc < 3) { std::cout << "用法: " << argv[0] << " <模型路径> <图像路径> [标签文件]" << std::endl; return -1; } try { // 1. 初始化检测器 std::cout << "=== 正在初始化 YOLO11 检测器 ===" << std::endl; YOLO11Detector detector(argv[1], argc > 3 ? argv[3] : "coco.names"); // 2. 加载图像 cv::Mat image = cv::imread(argv[2]); if (image.empty()) { std::cerr << "错误:无法加载图像 " << argv[2] << std::endl; return -1; } // 3. 执行检测 std::cout << "\n=== 正在执行检测 ===" << std::endl; auto detections = detector.detect(image, 0.25f, 0.45f); // 4. 处理结果 std::cout << "\n=== 检测结果 ===" << std::endl; std::cout << "检测到 " << detections.size() << " 个目标" << std::endl; const auto &classNames = detector.getClassNames(); for (size_t i = 0; i < detections.size(); i++) { const auto &det = detections[i]; // 绘制边界框 cv::rectangle(image, cv::Point(det.box.x, det.box.y), cv::Point(det.box.x + det.box.width, det.box.y + det.box.height), cv::Scalar(0, 255, 0), 2); // 绘制标签 std::string label = classNames[det.classId] + ": " + std::to_string(static_cast(det.conf * 100)) + "%"; cv::putText(image, label, cv::Point(det.box.x, det.box.y - 5), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 255), 1, cv::LINE_AA); // 打印检测信息 std::cout << " [" << i+1 << "] " << label << " at (" << det.box.x << ", " << det.box.y << ")" << std::endl; } // 5. 保存结果 cv::imwrite("result.jpg", image); std::cout << "\n结果已保存到 result.jpg" << std::endl; } catch (const std::exception &e) { std::cerr << "错误: " << e.what() << std::endl; return -1; } return 0; } ``` --- ### 3️⃣ 编译和运行 #### 方法一:使用构建脚本(推荐) ```bash # 一键编译 ./build.sh # 运行示例 ./build/yolo11_demo model.bin test.jpg coco.names ``` #### 方法二:手动使用 CMake ```bash mkdir build && cd build cmake .. make -j$(nproc) # 运行 ./yolo11_demo ../models/model.bin ../data/test.jpg ../models/coco.names ``` #### 方法三:直接使用 g++ ```bash g++ -o my_detector my_detector.cpp \ -I./include \ -I/usr/include \ `pkg-config --cflags --libs opencv4` \ -ldnn -lhbmem -std=c++14 -O3 ``` --- ## 📖 API 文档 ### BaseDetector(抽象基类) 所有 YOLO 检测器的统一接口: ```cpp class BaseDetector { public: // 核心检测接口 virtual std::vector detect( const cv::Mat &image, float confThreshold = 0.25f, float nmsThreshold = 0.45f) = 0; // 获取模型信息 virtual cv::Size getInputSize() const = 0; virtual int getNumClasses() const = 0; virtual const std::vector& getClassNames() const = 0; // 配置接口 virtual void setPreprocessType(PreprocessType type) = 0; }; ``` ### YOLO11Detector(RDKx5 实现) #### 构造函数 ```cpp YOLO11Detector( const std::string &modelPath, // .bin 模型文件路径 const std::string &labelsPath, // 类别标签文件路径 int numClasses = 80, // 类别数量(COCO默认80) int reg = 16 // DFL bins(默认16) ); ``` #### 核心方法 ```cpp // 执行目标检测 std::vector detect( const cv::Mat &image, // 输入图像(BGR格式) float confThreshold = 0.25f, // 置信度阈值 float nmsThreshold = 0.45f // NMS IoU 阈值 ); // 设置预处理方式 void setPreprocessType(PreprocessType type); // - PreprocessType::LETTERBOX 保持宽高比,填充灰边(推荐) // - PreprocessType::RESIZE 直接拉伸到目标尺寸 ``` ### 数据结构 ```cpp // 边界框 struct BoundingBox { float x, y; // 左上角坐标 float width, height; // 宽度和高度 float area() const; // 计算面积 }; // 检测结果 struct Detection { BoundingBox box; // 边界框 float conf; // 置信度 [0.0, 1.0] int classId; // 类别ID }; ``` ### 使用示例 ```cpp // 初始化 YOLO11Detector detector("yolo11n.bin", "coco.names"); // 设置预处理方式 detector.setPreprocessType(PreprocessType::LETTERBOX); // 执行检测 cv::Mat image = cv::imread("test.jpg"); auto results = detector.detect(image, 0.25f, 0.45f); // 遍历结果 for (const auto &det : results) { std::cout << "类别: " << det.classId << ", 置信度: " << det.conf << ", 位置: (" << det.box.x << ", " << det.box.y << ")" << std::endl; } ``` --- ## 🔧 模型准备 ### YOLO11 模型要求 #### 输入格式 ``` Tensor Type: HB_DNN_IMG_TYPE_RGB Layout: NCHW Shape: (1, 3, H, W) 例如 (1, 3, 640, 640) Data Type: int8 (量化为 uint8 - 128) ``` #### 输出格式(6个张量) ``` # 小目标检测头 (stride=8) output[0]: (1, H/8, W/8, CLASSES) - 分类分数 (float32, NONE) output[1]: (1, H/8, W/8, 64) - 边界框 (int32, SCALE) # 中目标检测头 (stride=16) output[2]: (1, H/16, W/16, CLASSES) output[3]: (1, H/16, W/16, 64) # 大目标检测头 (stride=32) output[4]: (1, H/32, W/32, CLASSES) output[5]: (1, H/32, W/32, 64) ``` ### 模型导出 参考 [D-Robotics RDK Model Zoo](https://developer.d-robotics.cc/rdk_doc/Quick_start/install_os) 官方文档进行模型量化和导出。 **推荐工具链:** 1. PyTorch/Ultralytics 训练模型 2. 导出为 ONNX 格式 3. 使用 `hb_mapper` 工具量化为 `.bin` --- ## 🎯 版本对比 ### 三个 YOLO 版本对比 | 特性 | YOLO5 | YOLO8 | YOLO11 | |------|-------|-------|---------| | **检测头** | 3个 | 6个 | 6个 | | **Anchor** | ✅ Anchor-based | ❌ Anchor-free | ❌ Anchor-free | | **后处理** | Sigmoid + Anchor解码 | DFL + Sigmoid | DFL + Sigmoid | | **输入格式** | NV12 (YUV420SP) | RGB (NCHW) | RGB (NCHW) | | **量化方式** | float32 (NONE) | float32 + int32 (SCALE) | float32 + int32 (SCALE) | | **NMS阈值** | 0.45 (推荐) | 0.7 (推荐) | 0.45 (推荐) | | **精度** | 中 | 高 | 最高 | | **速度** | 最快 | 快 | 中 | | **适用场景** | 实时性优先 | 精度速度平衡 | 精度优先 | ### 与 YOLOs-CPP 的对比 | 特性 | YOLOs-CPP | YOLOs-CPP-EdgePlatform | |-----|-----------|--------------| | **推理后端** | ONNX Runtime (CPU/CUDA) | BPU/NPU 硬件加速 | | **目标平台** | 通用桌面/服务器 | RDKx5/RK3588 嵌入式 | | **封装风格** | Header-only 单文件 | Header-only 单文件 ✓ | | **API 设计** | 直接调用 | 抽象基类 + 派生 ✓ | | **计时工具** | ScopedTimer | ScopedTimer ✓ | | **内存管理** | RAII | RAII + BPU专用API ✓ | ### 与官方示例对比 | 维度 | RDK官方示例 | YOLOs-CPP-EdgePlatform | |------|------------|--------------| | **代码组织** | main.cc 800行 | 模块化 header-only | | **使用方式** | 复制粘贴修改 | `#include` 即用 | | **学习成本** | 需理解BPU底层 | 只需了解API | | **可维护性** | 难以维护 | 清晰的模块分离 | | **可扩展性** | 需要重写 | 继承BaseDetector | | **版本切换** | 重新编写 | 换个include | --- ## ⚙️ 性能优化 ### 1. 启用性能计时 修改 `include/tools/Config.hpp`: ```cpp #define TIMING_MODE // 取消注释启用 ``` 重新编译后会显示各阶段耗时: ``` [TIMER] 模型加载 耗时 125.34 ms [TIMER] 预处理 耗时 8.21 ms [TIMER] BPU推理 耗时 15.67 ms [TIMER] 后处理 耗时 12.43 ms [TIMER] 总体检测 耗时 36.89 ms ``` ### 2. 调整预处理方式 ```cpp // 方式1:LetterBox(保持宽高比,推荐) detector.setPreprocessType(PreprocessType::LETTERBOX); // 方式2:Resize(直接拉伸,更快但可能变形) detector.setPreprocessType(PreprocessType::RESIZE); ``` ### 3. 优化检测阈值 ```cpp // 降低置信度 → 检测更多目标(可能有误检) auto results = detector.detect(image, 0.1f, 0.45f); // 提高置信度 → 减少误检(可能漏检) auto results = detector.detect(image, 0.5f, 0.45f); // 调整NMS → 控制重叠框 auto results = detector.detect(image, 0.25f, 0.3f); // 更严格 auto results = detector.detect(image, 0.25f, 0.7f); // 更宽松 ``` ### 4. 模型选择建议 | 模型 | 输入尺寸 | 推理时间 | 精度 | 适用场景 | |------|---------|---------|------|----------| | yolo11n | 320×320 | ~8ms | 中 | 实时视频流 | | yolo11n | 640×640 | ~15ms | 高 | 通用检测 | | yolo11s | 640×640 | ~25ms | 很高 | 高精度需求 | | yolo11m | 640×640 | ~45ms | 最高 | 离线分析 | --- ## ❓ 常见问题 ### Q1: 编译时找不到头文件 ```bash # 检查 BPU 库 ls /usr/include/dnn/hb_dnn.h # 如果没有,需要安装 RDK 开发环境 ``` ### Q2: 运行时找不到动态库 ```bash # 方法1:设置环境变量 export LD_LIBRARY_PATH=/usr/lib:$LD_LIBRARY_PATH # 方法2:拷贝到系统目录 sudo cp /path/to/libdnn.so /usr/lib/ sudo ldconfig ``` ### Q3: 模型加载失败 ```cpp // 检查模型文件 if (!std::ifstream("model.bin")) { std::cerr << "模型文件不存在" << std::endl; } // 检查文件权限 // chmod 644 model.bin ``` ### Q4: 检测结果为空 ```cpp // 1. 降低置信度阈值 auto results = detector.detect(image, 0.1f, 0.45f); // 2. 检查图像是否正确加载 if (image.empty()) { std::cerr << "图像加载失败" << std::endl; } // 3. 确认类别数量 std::cout << "类别数: " << detector.getNumClasses() << std::endl; ``` ### Q5: 如何切换不同YOLO版本? ```cpp // 只需更换 include // #include "det/YOLO5_RDK.hpp" // YOLOv5 // #include "det/YOLO8_RDK.hpp" // YOLOv8 #include "det/YOLO11_RDK.hpp" // YOLOv11 // 使用相同的API YOLO11Detector detector("model.bin", "labels.txt"); auto results = detector.detect(image); ``` --- ## 📝 开发计划 ### 当前版本:v1.0.0 - [x] 基础架构设计 - [x] ScopedTimer 工具 - [x] BaseDetector 抽象接口 - [x] YOLO11_RDK 完整实现(DFL后处理) - [x] YOLO8_RDK 完整实现(DFL后处理) - [x] YOLO5_RDK 完整实现(Anchor-based) - [x] 完整中文注释和文档 - [x] 示例程序和使用指南 ### 下一版本计划 - [ ] **RK3588 (NPU) 平台支持** - RKNN API 封装 - YOLO5/8/11 NPU 版本 - [ ] **性能基准测试** - FPS 测试工具 - 精度评估工具 - 内存占用分析 - [ ] **扩展功能** - 批处理推理 - 视频流检测 - 多线程支持 - [ ] **更多文档** - 视频教程 - API 参考手册 - 最佳实践指南 --- ## 🙏 致谢 本项目设计灵感和参考来源: ### 主要参考 1. **[YOLOs-CPP](https://github.com/Geekgineer/YOLOs-CPP)** ⭐ - 贡献:Header-only 设计理念、统一 API 接口、ScopedTimer 工具 - 作者:Abdalrahman M. Amer - 许可证:MIT ### 技术参考 2. **D-Robotics RDK Model Zoo** - 贡献:BPU 推理示例、libDNN API 使用方法 - 文档:[RDK 开发者文档](https://developer.d-robotics.cc) 3. **Rockchip RKNN Model Zoo** - 贡献:NPU 推理参考实现 - 文档:[RKNN Toolkit2](https://github.com/rockchip-linux/rknn-toolkit2) ### 特别感谢 - **Ultralytics** - YOLO 系列模型 - **OpenCV** - 图像处理库 - 所有开源社区贡献者 --- ## 📄 许可证 本项目采用 **MIT License** 开源协议。 ``` MIT License Copyright (c) 2025 FANKYT Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ``` 详见 [LICENSE_INFO.md](LICENSE_INFO.md) --- ## 👨‍💻 作者信息 - **作者**: FANKYT - **项目**: YOLOs-CPP-EdgePlatform - **版本**: v1.0.0 - **日期**: 2025-10-08 --- ## 📚 相关文档 - 📘 [快速上手指南](QUICKSTART.md) - 零基础入门教程 - 📗 [架构设计文档](ARCHITECTURE.md) - 深入了解设计原理 - 📙 [项目总结](PROJECT_SUMMARY.md) - 完整项目总结 - 📕 [版权信息](LICENSE_INFO.md) - 许可证和致谢 --- ## 📞 联系方式 如有问题或建议,欢迎: - 📧 提交 Issue - 💬 参与讨论 - 🔀 提交 Pull Request ---
**⭐ 如果这个项目对你有帮助,请给个 Star!** Made with ❤️ by FANKYT