# YOLOs-CPP-EdgePlatform **Repository Path**: FANKYT/yolos-cpp-edgeplatform ## Basic Information - **Project Name**: YOLOs-CPP-EdgePlatform - **Description**: 专为边缘AI平台打造的 Header-Only YOLO 推理库 - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 16 - **Forks**: 6 - **Created**: 2025-10-08 - **Last Updated**: 2025-10-10 ## Categories & Tags **Categories**: cv **Tags**: YOLOs-CPP ## 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/许可证-Apache%202.0-orange)](LICENSE) [![语言](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**)进行了深度优化。 **支持平台**: - ✅ **D-Robotics RDKx5** - BPU 硬件加速(libDNN API) - ✅ **Rockchip RK3588** - NPU 硬件加速(RKNN API) ### 为什么选择 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 优化 ### 🎨 完整性 **目标检测 (Detection)** - ✅ **YOLOv5** - Anchor-based 检测(支持 RDK BPU + RK3588 NPU) - ✅ **YOLOv8** - Anchor-free + DFL 检测(RDK BPU + RK3588 NPU) - ✅ **YOLOv11** - 最新架构,精度最高(RDK BPU + RK3588 NPU) **姿态估计 (Pose Estimation)** - ✅ **YOLO11-Pose** - 17个COCO关键点,人体姿态检测 **实例分割 (Instance Segmentation)** - ✅ **YOLOv8-Seg** - 实例分割 + 目标检测 - ✅ **YOLO11-Seg** - 最新分割架构 **输入格式支持** - ✅ **自动检测适配** - 智能识别模型输入格式 - ✅ **RGB 格式** - NCHW布局,int8量化(u8-128) - ✅ **NV12 格式** - YUV420SP,硬件解码友好 ### 🛠️ 工程化 - ✅ **RAII 资源管理** - 自动内存管理 - ✅ **ScopedTimer 计时** - 性能分析工具 - ✅ **异常安全** - 完善的错误处理 - ✅ **详细文档** - README、快速指南、架构文档 --- ## 📁 项目结构 ``` YOLOs-CPP-EdgePlatform/ ├── include/ # 头文件目录 │ ├── det/ # 目标检测器实现 │ │ ├── BaseDetector.hpp # 抽象基类(统一接口) │ │ ├── YOLO5_RDK.hpp # YOLOv5 RDK BPU 实现(Anchor-based,支持RGB/NV12) │ │ ├── YOLO5_RKNN.hpp # YOLOv5 RK3588 NPU 实现(RKNN API) │ │ ├── YOLO8_RDK.hpp # YOLOv8 RDK BPU 实现(DFL,支持RGB/NV12) │ │ ├── YOLO8_RKNN.hpp # YOLOv8 RK3588 NPU 实现(RKNN API) │ │ ├── YOLO11_RDK.hpp # YOLOv11 RDK BPU 实现(最新,支持RGB/NV12) │ │ └── YOLO11_RKNN.hpp # YOLOv11 RK3588 NPU 实现(RKNN API) │ ├── pose/ # 姿态检测器实现 │ │ ├── BasePoseDetector.hpp # 姿态检测抽象基类 │ │ └── YOLO11_POSE_RDK.hpp # YOLO11-Pose 实现(17关键点,支持RGB/NV12) │ ├── seg/ # 实例分割器实现 │ │ ├── BaseSegDetector.hpp # 分割检测抽象基类 │ │ ├── YOLO8_SEG_RDK.hpp # YOLOv8-Seg 实现(支持RGB/NV12) │ │ └── YOLO11_SEG_RDK.hpp # YOLO11-Seg 实现(支持RGB/NV12) │ └── tools/ # 工具类 │ ├── Config.hpp # 编译配置宏 │ ├── ScopedTimer.hpp # RAII 计时器 │ └── Common.hpp # 通用数据结构 ├── examples/ # 示例程序 │ └── yolo11_detection_example.cpp ├── models/ # 模型文件目录 │ └── coco.names # COCO 80类标签 ├── README.md # 项目文档(本文件) ├── QUICKSTART.md # 快速上手指南 ├── ARCHITECTURE.md # 架构设计文档 ├── LICENSE_INFO.md # 版权信息 ├── build.sh # 一键编译脚本 └── CMakeLists.txt # CMake 配置 ``` **核心文件统计:** | 模块 | 文件数 | 功能 | 作者 | |------|--------|------|------| | **Detection** | 8个 | 目标检测基类+7个版本实现(RDK×4 + RKNN×3) | FANKYT | | **Pose** | 2个 | 姿态检测基类+YOLO11实现 | FANKYT | | **Segmentation** | 3个 | 分割基类+2个版本实现 | FANKYT | | **Tools** | 3个 | 工具类、数据结构、配置 | FANKYT | | **总计** | **16个头文件** | 完整的YOLO推理生态 | - | --- ## 🚀 快速开始 ### 1️⃣ 环境要求 #### 硬件平台 - ✅ **D-Robotics RDKx5** (BPU) - 支持 YOLOv5/v8/v11 检测、姿态、分割 - ✅ **Rockchip RK3588** (NPU) - 支持 YOLOv5/v8/v11 检测 #### 软件依赖 **RDKx5 平台(BPU):** ```bash # 安装 OpenCV sudo apt update sudo apt install -y libopencv-dev # 确认 BPU 库已安装 ls /usr/include/dnn/hb_dnn.h ls /usr/lib/libdnn.so ``` **RK3588 平台(NPU):** ```bash # 安装 OpenCV sudo apt update sudo apt install -y libopencv-dev # 确认 RKNN 库已安装 ls /usr/include/rknn_api.h ls /usr/lib/librknnrt.so ``` **通用开发环境:** - 工具链:gcc 7.5+ / g++ 7.5+ - CMake:3.10+ --- ### 2️⃣ 使用示例 #### 目标检测 - 最简示例(3行代码) **RDKx5 平台(BPU):** ```cpp #include "det/YOLO11_RDK.hpp" using namespace yolos_edgeplatform; int main() { YOLO11Detector detector("yolo11n.bin", "coco.names"); cv::Mat image = cv::imread("test.jpg"); auto results = detector.detect(image); // 自动适配RGB/NV12格式! std::cout << "检测到 " << results.size() << " 个目标" << std::endl; return 0; } ``` **RK3588 平台(NPU):** ```cpp #include "det/YOLO8_RKNN.hpp" // 或 YOLO5_RKNN.hpp, YOLO11_RKNN.hpp using namespace yolos_edgeplatform; int main() { YOLO8RKNNDetector detector("yolov8s.rknn", "coco.names"); cv::Mat image = cv::imread("test.jpg"); auto results = detector.detect(image); // LetterBox 预处理 + NPU 推理! std::cout << "检测到 " << results.size() << " 个目标" << std::endl; return 0; } ``` #### 姿态检测示例 ```cpp #include "pose/YOLO11_POSE_RDK.hpp" using namespace yolos_edgeplatform; int main() { YOLO11PoseDetector detector("yolo11n_pose.bin", "person.names"); cv::Mat image = cv::imread("person.jpg"); auto poses = detector.detect(image, 0.25f, 0.45f, 0.5f); // 绘制关键点和骨架 for (const auto& pose : poses) { // 绘制17个关键点 for (const auto& kpt : pose.keypoints) { if (kpt.confidence > 0.5) { cv::circle(image, cv::Point(kpt.x, kpt.y), 3, cv::Scalar(0, 255, 0), -1); } } // 绘制骨架连接 for (const auto& [i, j] : COCO_POSE_SKELETON) { if (pose.keypoints[i].confidence > 0.5 && pose.keypoints[j].confidence > 0.5) { cv::line(image, cv::Point(pose.keypoints[i].x, pose.keypoints[i].y), cv::Point(pose.keypoints[j].x, pose.keypoints[j].y), cv::Scalar(255, 0, 0), 2); } } } cv::imwrite("pose_result.jpg", image); return 0; } ``` #### 实例分割示例 ```cpp #include "seg/YOLO11_SEG_RDK.hpp" using namespace yolos_edgeplatform; int main() { YOLO11SegDetector detector("yolo11n_seg.bin", "coco.names"); cv::Mat image = cv::imread("scene.jpg"); auto segments = detector.detect(image, 0.25f, 0.7f, 0.5f); // 生成彩色分割掩码 cv::Mat overlay = image.clone(); for (size_t i = 0; i < segments.size(); i++) { const auto& seg = segments[i]; // 随机颜色 cv::Scalar color(rand() % 255, rand() % 255, rand() % 255); // 应用掩码到overlay overlay.setTo(color, seg.mask); } // 混合原图和分割结果 cv::addWeighted(image, 0.6, overlay, 0.4, 0, image); cv::imwrite("seg_result.jpg", image); 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 文档 ### 目标检测 API #### BaseDetector (抽象基类) ```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 / YOLO8Detector / YOLO5Detector (RDK BPU) ```cpp // 构造函数 YOLO11Detector( const std::string &modelPath, // .bin 模型文件路径 const std::string &labelsPath, // 类别标签文件路径 int numClasses = 80, // 类别数量(COCO默认80) int reg = 16 // DFL bins(默认16) ); // 检测方法 std::vector detect( const cv::Mat &image, // BGR图像,自动适配RGB/NV12! float confThreshold = 0.25f, // 置信度阈值 float nmsThreshold = 0.45f // NMS IoU阈值 ); ``` #### YOLO5RKNNDetector / YOLO8RKNNDetector / YOLO11RKNNDetector (RK3588 NPU) ```cpp // 构造函数 YOLO8RKNNDetector( const std::string &modelPath, // .rknn 模型文件路径 const std::string &labelsPath, // 类别标签文件路径 int numClasses = 80, // 类别数量(COCO默认80) int dflLen = 16 // DFL bins(YOLOv8/11 专用,默认16) ); // 检测方法 std::vector detect( const cv::Mat &image, // BGR图像,自动LetterBox预处理! float confThreshold = 0.25f, // 置信度阈值 float nmsThreshold = 0.45f // NMS IoU阈值 ); ``` ### 姿态检测 API #### BasePoseDetector (抽象基类) ```cpp class BasePoseDetector { public: virtual std::vector detect( const cv::Mat &image, float confThreshold = 0.25f, float nmsThreshold = 0.45f, float kptThreshold = 0.5f) = 0; }; ``` #### YOLO11PoseDetector ```cpp // 构造函数 YOLO11PoseDetector( const std::string &modelPath, const std::string &labelsPath, int numClasses = 1, // 默认只检测person int numKeypoints = 17, // COCO 17个关键点 int kptEncode = 3, // x,y,visibility int reg = 16 ); // 检测方法 std::vector detect( const cv::Mat &image, float confThreshold = 0.25f, float nmsThreshold = 0.45f, float kptThreshold = 0.5f // 关键点置信度阈值 ); ``` ### 实例分割 API #### BaseSegDetector (抽象基类) ```cpp class BaseSegDetector { public: virtual std::vector detect( const cv::Mat &image, float confThreshold = 0.25f, float nmsThreshold = 0.7f, // Seg推荐0.7 float maskThreshold = 0.5f) = 0; }; ``` #### YOLO11SegDetector / YOLO8SegDetector ```cpp // 构造函数 YOLO11SegDetector( const std::string &modelPath, const std::string &labelsPath, int numClasses = 80, int reg = 16, int maskCoeffs = 32 // Mask系数维度 ); // 检测方法 std::vector detect( const cv::Mat &image, float confThreshold = 0.25f, float nmsThreshold = 0.7f, float maskThreshold = 0.5f // Mask二值化阈值 ); ``` ### 数据结构 ```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 }; // 关键点 struct KeyPoint { float x, y; // 坐标 float confidence; // 置信度/可见性 }; // 姿态检测结果 struct PoseDetection { BoundingBox box; // 人体边界框 float conf; // 检测置信度 int classId; // 类别ID (通常是person) std::vector keypoints; // 17个COCO关键点 }; // 实例分割结果 struct Segmentation { BoundingBox box; // 对象边界框 float conf; // 检测置信度 int classId; // 类别ID cv::Mat mask; // 分割掩码 (单通道,与原图同尺寸) }; // COCO 17个关键点索引 // 0: 鼻子, 1-2: 眼睛, 3-4: 耳朵 // 5-6: 肩膀, 7-8: 肘部, 9-10: 手腕 // 11-12: 髋部, 13-14: 膝盖, 15-16: 脚踝 // COCO 骨架连接 const std::vector> COCO_POSE_SKELETON = { {0,1}, {0,2}, {1,3}, {2,4}, // 面部 {3,5}, {4,6}, // 头到肩 {5,7}, {7,9}, {6,8}, {8,10}, // 手臂 {5,6}, {5,11}, {6,12}, {11,12}, // 躯干 {11,13}, {13,15}, {12,14}, {14,16} // 腿部 }; ``` ### 使用示例 **RDKx5 平台:** ```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; } ``` **RK3588 平台:** ```cpp // 初始化 YOLO5RKNNDetector detector("yolov5s.rknn", "coco.names"); // 执行检测(自动 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; } ``` --- ## 🔧 模型准备 ### RDKx5 平台模型要求(BPU) #### 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) ``` ### RK3588 平台模型要求(NPU) #### YOLOv5 模型输入格式 ``` Tensor Type: RKNN_TENSOR_UINT8 Layout: NHWC Shape: (1, H, W, 3) 例如 (1, 640, 640, 3) Data Type: uint8 ``` #### YOLOv5 输出格式(3个张量) ``` # stride=8 小目标 output[0]: (1, H/8, W/8, 3*(5+CLASSES)) - [x,y,w,h,conf,cls...] # stride=16 中目标 output[1]: (1, H/16, W/16, 3*(5+CLASSES)) # stride=32 大目标 output[2]: (1, H/32, W/32, 3*(5+CLASSES)) ``` #### YOLOv8/11 模型输入格式 ``` Tensor Type: RKNN_TENSOR_UINT8 Layout: NHWC Shape: (1, H, W, 3) 例如 (1, 640, 640, 3) Data Type: uint8 ``` #### YOLOv8/11 输出格式(6-9个张量) ``` # stride=8 小目标 output[0]: (1, dfl_len*4, H/8, W/8) - bbox DFL 张量 output[1]: (1, CLASSES, H/8, W/8) - 分类分数 [output[2]: (1, 1, H/8, W/8)] - score_sum (可选) # stride=16 中目标 output[3/4]: bbox + score (+ score_sum) # stride=32 大目标 output[6/7]: bbox + score (+ score_sum) ``` ### 模型导出 **RDKx5 平台(BPU):** 参考 [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` **RK3588 平台(NPU):** 参考 [Rockchip RKNN Model Zoo](https://github.com/airockchip/rknn_model_zoo) 官方文档进行模型转换。 **推荐工具链:** 1. PyTorch/Ultralytics 训练模型 2. 导出为 ONNX 格式 3. 使用 `RKNN Toolkit2` 转换为 `.rknn` --- ## 🎯 版本对比 ### 三个 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] 示例程序和使用指南 ### 下一版本计划 - [x] **RK3588 (NPU) 平台支持** - ✅ RKNN API 封装 - ✅ YOLOv5 NPU 版本 - ✅ YOLOv8 NPU 版本(DFL 后处理) - ✅ YOLOv11 NPU 版本(DFL 后处理) - 🔜 姿态/分割 NPU 版本 - [ ] **性能基准测试** - FPS 测试工具 - 精度评估工具 - 内存占用分析 - BPU vs NPU 性能对比 - [ ] **扩展功能** - 批处理推理 - 视频流检测 - 多线程支持 - [ ] **更多文档** - 视频教程 - 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 API 使用方法 - 文档:[RKNN Toolkit2](https://github.com/airockchip/rknn_model_zoo) ### 特别感谢 - **Ultralytics** - YOLO 系列模型 - **OpenCV** - 图像处理库 - 所有开源社区贡献者 --- ## 📄 许可证 本项目采用 **Apache License 2.0** 开源协议。 ``` Apache License 2.0 Copyright 2025 FANKYT Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ``` **主要条款**: - ✅ **商业使用** - 允许商业使用 - ✅ **修改** - 允许修改代码 - ✅ **分发** - 允许分发 - ✅ **专利授权** - 提供明确的专利授权 - ⚠️ **声明变更** - 修改后需声明变更 - ⚠️ **保留版权** - 需保留原始版权和许可证声明 - ⚠️ **免责** - 软件"按原样"提供,不提供任何担保 详见完整许可证文件: [LICENSE](LICENSE) --- ## 👨‍💻 作者信息 - **作者**: 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