Skip to content

ruisv/bcdl

Repository files navigation

BCDL — BPU Computational Deep Learning

License C++ Python Platform Version

English | 简体中文

一个面向 D-Robotics RDK S100 / S100P / S600(BPU "Nash" 加速器)的 C++17 推理与多媒体库,并提供对 NumPy 友好的 Python 绑定。BCDL 是 CUDA/TensorRT 视觉栈 的 BPU 原生对应实现:加载一个已编译的 .hbm 模型,完成推理、前/后处理、硬件 编解码与取流——全部在板端运行,且默认在多媒体与计算单元之间零拷贝。

目录

效果展示

板端基准套件输出的标注结果(在 RDK S100P 上跑真实模型)。 可用 scripts/board_bench.py 复现;完整数据见 benchmarks/RESULTS.md

分类(top-k) 检测(YOLO26 LTRB) 检测 — DFL 头(YOLOv8)
旋转框(OBB) 多目标跟踪(ByteTrack) 姿态(17 关键点)
实例分割 语义分割 单目深度
双目深度(LAS2) OCR(PP-OCRv5) 硬件 JPEG 解码(JPU)

为什么选 BCDL

整个 S 系列的计算 + 多媒体栈统一在两个 hobot 原语之上:

  • hbUCPSysMem —— 唯一的共享内存缓冲(phyAddr + virAddr),被 BPU 张量、 JPU/VPU 编解码图像以及 VP 预处理单元共用。
  • hbUCPTaskHandle_t —— 唯一的任务/队列模型;BPU 推理、JPEG/H.264/H.265 编解码、resize/cvtColor 全部通过同一个 hbUCP 调度器提交与等待。

所以 JPU → VP → BPU → VPU 的零拷贝是默认行为,而非额外优化。 BCDL 是这套底层结构之上一层薄而 RAII 干净的 C++ 封装,外加可移植的后处理 (把 CUDA kernel 重写为 CPU/NEON)。

特性

  • 后端 —— Engine 封装 hbDNNhbDNNInferV2);自动处理缓存一致性 (推理前 clean、读取前 invalidate);零拷贝 / 反量化的输出读取器。
  • 任务(CPU/NEON 后处理,也提供无需 Engine 的纯 decode_* 函数):
    • 检测 —— anchor-free LTRB 多尺度 + DFL 头(YOLO26 / YOLOv8 / v5 / v11),分类别 NMS。
    • 分类、姿态(17 关键点)、实例分割(proto × mask-coef)、 旋转框(OBB,旋转 IoU NMS)、语义分割单目深度双目深度(双图视差)。
    • OCR —— 完整三段式 PP-OCRv5 流水线:DBNet 检测 → PP-LCNet 方向分类(0°/180°)→ CRNN/CTC 识别(18385 类字典)。
    • 多目标跟踪 —— ByteTrack(Kalman + 两阶段关联)。
  • 多媒体 —— 硬件 JPEG(JPU)与 H.264 / H.265(VPU)编解码。
  • 流水线 —— 同步、缓冲复用的 DetectionPipeline,多线程 AsyncDetectionPipeline(预处理 ‖ 推理 重叠)、TrackingPipelineStereoPipeline,以及视频文件 → 解码 → 检测的链路。
  • Python —— nanobind 绑定:NumPy 进/出,覆盖每个解码器 + 流水线,阻塞推理 期间释放 GIL。

架构

python/    nanobind 绑定(NumPy <-> 张量),推理时释放 GIL
tasks/     det · cls · pose · seg · obb · semseg · depth · ocr
tracks/    ByteTrack 多目标跟踪
pipeline/  同步 / 异步检测 · 跟踪 · 双目  (JPU -> VP -> BPU -> CPU/VPU)
media/     JpegCodec (JPU) · VideoCodec H.264/H.265 (VPU)
backend/   Engine、输出读取器             (libdnn  -> hbDNN*)
preproc/   CPU letterbox + BGR->NV12(OpenCV/OpenMP);VP 单元 (hb_vp)
core/      SysMem · Task · Status · MemPool (libhbucp -> hbUCP*)

各层状态与路线图见 docs/PLAN.md

运行环境要求

  • 一块 RDK S100 / S100P / S600 开发板(Ubuntu 22.04,aarch64),且板上已有 D-Robotics hobot SDK(/usr/include/hobot/usr/hobot/liblibdnnlibhbucplibhbvp)—— 或安装下文的 hobot-dnn / hobot-media conda 包。 BCDL 的源码在整个 S 系列上一致;而编译出的 .hbmmarch 相关的, 所以请运行为你目标板编译的模型(见模型)。
  • CMake ≥ 3.22、GCC 11、Ninja。
  • OpenCV 5(图像操作;由 BCDL_HAVE_OPENCV 守卫,并有手写回退实现)。
  • Python 模块所需:带 nanobind 的 Python 环境(以及 NumPy、OpenCV)。

安装

预编译的 linux-aarch64 包(Python 3.9–3.14)已发布到一个 conda 频道, 所以在板上你可以完全跳过源码构建:

conda install -c https://mirrors.ruis.ai/conda -c conda-forge bcdl
python -c "import bcdl; print(bcdl.__version__)"

想要一个干净、可复现的环境?新建一个并锁定版本:

conda create -n bcdl -c https://mirrors.ruis.ai/conda -c conda-forge \
    python=3.12 bcdl
conda activate bcdl
# 或锁定精确构建:   conda install ... "bcdl=0.1.0"

为了避免每次都带 -c,可以把该频道加进环境(它必须排在 conda-forge 上面,这样 hobot-* 包才会从这里解析):

conda config --env --add channels https://mirrors.ruis.ai/conda
conda config --env --add channels conda-forge

之后 conda install bcdl / conda update bcdl 就会直接从该频道解析。 端到端验证安装(打印版本号以及加载到的原生扩展路径):

python -c "import bcdl, bcdl_py; print('bcdl', bcdl.__version__); print(bcdl_py.__file__)"

这会把整个栈解析为四个包 —— Python 绑定、C++ 库,以及它们链接的、打包好的 D-Robotics hobot SDK:

内容
bcdl bcdl / bcdl_py Python 绑定(每个 Python 3.9–3.14 各一份构建)
libbcdl C++ 库 —— libbcdl.so、公共头文件,以及 find_package(bcdl) 的 CMake 配置
hobot-dnn BPU/DNN 运行时 SDK(libdnnlibhbucplibhbvp…)+ hobot/ 头文件
hobot-media 多媒体/编解码线(libffmedialibgdcbinlibmultimedia…)+ 多媒体开发头文件

如果只是 纯 C++ 的使用方,只装库即可,并用 find_package(bcdl) 来构建 (它会一并拉入 libbcdl + hobot-dnn + hobot-media):

conda install -c https://mirrors.ruis.ai/conda -c conda-forge libbcdl

打包的 hobot SDK 仍依赖板上的 设备平台库libbpulibhbmemlibaloglibvdsplibhbipcfhal),位于 /usr/hobot/lib —— 它们随 RDK 系统镜像一起提供,通过 ldconfig 解析, 出于设计目的不随包重新分发。

快速上手

Python —— 预处理 ‖ 推理 重叠的流式检测:

import bcdl

engine = bcdl.Engine("models/yolo26s_det_nashm_640x640_nv12.hbm")
cfg = bcdl.PipelineConfig(); cfg.detect.num_classes = 80
pipe = bcdl.AsyncDetectionPipeline(engine, cfg, depth=3)

for i, frame in enumerate(frames):          # frame: HxWx3 uint8 BGR
    pipe.submit(frame)                       # 队满则阻塞(背压)
    if i >= 3:
        for d in pipe.next():                # 按提交顺序返回结果
            print(d.class_id, d.score, d.x1, d.y1, d.x2, d.y2)
pipe.finish()
while (dets := pipe.next()) is not None:
    ...                                      # 排空最后在途的帧

纯函数解码器也对外暴露,用于纯 NumPy 路径 (bcdl.decodebcdl.decode_posebcdl.decode_obbbcdl.decode_ctc…)。

C++ —— examples/ 目录有可独立运行的程序:

./build/det_demo    models/yolo26s_det_nashm_640x640_nv12.hbm data/images/bus.jpg
./build/ocr_demo    data/images/ocr.jpg          # PP-OCRv5 det -> cls -> rec
./build/track_demo  models/yolo26s_det_nashm_640x640_nv12.hbm  # 检测 + ByteTrack
./build/video_det_demo  stream.h264 model.hbm    # VPU 解码 -> BPU 检测

完整的接口面 —— 每个类、配置和解码器,并附每个任务的用法片段 —— 见下文 API 参考

从源码构建

在板上、在你的 Python/conda 环境里构建(需要 hobot SDK —— 来自上文的 hobot-dnn / hobot-media conda 包,或系统镜像里的 /usr/include/hobot + /usr/hobot/lib):

cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release
cmake --build build -j

这会构建 bcdl 库、C++ 示例,以及 bcdl_py Python 模块。

从 CMake 安装并使用 —— 支持 find_package(bcdl)

cmake --install build --prefix /your/prefix
find_package(bcdl CONFIG REQUIRED)
target_link_libraries(your_target PRIVATE bcdl::bcdl)   # 一并带入头文件 + hobot 依赖

安装 Python 模块 —— 一个可 pip 安装的 wheel(scikit-build-core); 请在板上构建(C++ 构建需要 hobot SDK):

pip install .          # 或: pip wheel . -w dist/
python -c "import bcdl; print(bcdl.__version__)"

模型

编译好的 BPU 模型(.hbm纳入版本库(体积大),且 BCDL 重新分发 任何模型权重 —— 请自行放到 models/ 下(见 models/README.md)。模型转换(ONNX → .hbm、PTQ 校准) 是在 x86 主机上用 D-Robotics OpenExplorer 工具链 离线 完成的;BCDL 只 消费成品二进制。每个 .hbm 都为特定 BPU march 编译,所以请用为你的板子 编译的那一份(S100 / S100P 共用 Nash march;S600 为其自身编译)—— BCDL 运行时 本身在整个 S 系列上一致。

示例/基准用到的模型来自第三方,遵循各自的许可证 —— 在重新分发或商用前请逐一核对:

模型 用于 上游许可证
PP-OCRv5 det/rec、PP-LCNet cls OCR Apache-2.0(PaddleOCR / PaddlePaddle)
YOLO26 / YOLOv8 det · cls · pose · seg · obb AGPL-3.0(Ultralytics)—— 著佐权;商用需其 Enterprise 授权
Depth-Anything-V2 depth Apache-2.0(Small)/ CC-BY-NC-4.0(Base+)—— 请核对具体变体
DeepLabV3+ 语义分割 来自 D-Robotics rdk_model_zoo(请核对其条款)

BCDL 自身的代码(本仓库)与这些无关 —— 它是一个能加载任意 .hbm 的通用运行时。 上述许可证只约束 你自行获取的权重,不约束 BCDL。

文档

文档 涵盖内容
docs/API.md Python API 参考 —— 每个类、配置和 decode_* 函数,附每个任务的用法片段。
docs/CPP_API.md C++ API 参考 —— namespace bcdl 下的同一接口面,对应到各头文件。
docs/PLAN.md 路线图与各层状态(已验证的 hobot API 映射)。
benchmarks/RESULTS.md 完整板端基准数据 + 效果展示中的标注校验图。
CONTRIBUTING.md 如何搭建、构建(在板上)、测试并提交改动。
CHANGELOG.md 发布说明(Keep a Changelog / SemVer)。

公共头文件在 include/bcdl/;可运行程序在 examples/

性能基准

RDK S100P(sw 4.0.5)上测得。infer 仅为 BPU 推理;decode 加上 BCDL 的后处理;model.hbm 在磁盘上的大小。每一行的标注输出见 效果展示

任务 模型 输入 infer ms infer FPS decode ms model MB
cls yolo26n 224² 0.45 2235 0.45 3.9
det yolo26n (LTRB) 640² 1.16 860 1.99 7.8
det_dfl yolov8 (DFL 头) 640² 1.54 647 9.60 3.7
pose yolo26n 640² 1.31 761 1.52 7.7
seg yolo26n 640² 1.64 612 11.4 9.9
obb yolo26n 640² 1.15 872 1.65 5.8
semseg deeplabv3plus 2048×1024 49.6 20 58.0 39.1
depth depth-anything-v2 686×518 113 9 117 121.8
stereo las2-m (crop) 640×480 14.2 71 21.8 40.7
ocr PP-OCRv5 (det→cls→rec) 960² / 48×320 20.2 50 137 35.3

yolo26s @1280×720 的流式吞吐:同步 216 FPS,异步重叠 334 FPS(1.55×)。 硬件 JPEG 解码(JPU)在样例图上比 cv2/libjpeg 快 ≈3.6–5.3×,并卸载 CPU(零拷贝 NV12→BPU)。

在板上复现:

PYTHONPATH=build:python python scripts/board_bench.py

测试

已安装 bcdl 的情况下(用上文的 conda 频道,或一个 pip wheel),直接对 已安装模块跑测试套件 —— 无需设置 PYTHONPATH

pip install pytest          # 同时需检出本仓库以获取测试文件
pytest tests/               # 完整套件;缺模型的板端测试会跳过

如果是 源码构建,则让 pytest 指向源码树内的模块:

# (1) 无需 Engine 的 numpy 解码测试 —— 不需要板子 / 不需要模型:
PYTHONPATH=build:python pytest tests/test_detection.py tests/test_pose.py \
    tests/test_obb.py tests/test_instance_seg.py tests/test_depth_seg.py \
    tests/test_depth_seg_py.py tests/test_classification.py tests/test_ocr.py

# (2) 板端、真实模型端到端 —— 需要填充好 models/;每个任务在其模型/图像缺失时
#     都会干净地跳过:
PYTHONPATH=build:python pytest tests/

两层:后处理数学由 确定性 NumPy 测试 通过无需 Engine 的 decode_* 绑定 钉死(任何地方都能跑),随后 板端套件 在真实模型上验证完整的 BPU/编解码路径。 在 RDK S100P 上,对 conda 包bcdl + libbcdl + hobot-dnn + hobot-media)端到端:96 通过、1 跳过(共收集 97 个;该跳过项需要显式 --hbm)。

分组 文件 测试数 需要板子?
解码数学(det/cls/pose/obb/实例分割/depth/seg/ocr/stereo)+ 内存安全 test_detectiontest_classificationtest_posetest_obbtest_instance_segtest_depth_seg(+_py)、test_ocrtest_stereo_pytest_memory_safety 66
真实模型上的任务(cls·det·det_dfl·pose·seg·obb·semseg·depth·OCR 三段) test_board_models 11
双目深度(真实 LAS2 .hbm test_stereo_board_py 3
多媒体编解码(VPImage · JPEG/JPU · H.264/H.265/VPU) test_codec_pytest_video_decode_py 11
流水线(ByteTrack、异步检测) test_tracking_pytest_async_detection_py 5

参与贡献

欢迎贡献 —— issue 与 pull request 皆可。完整指南见 CONTRIBUTING.md;要点如下:

  • 在任意机器开发,在板上构建与运行。 hobot SDK 只存在于 RDK 硬件上,所以 C++ 库和板端测试套件必须在 S100 / S100P / S600 板上构建并执行。无需 Engine 的 NumPy decode_* 测试可在任意主机上运行(见测试)。
  • 约定 —— 头文件用 .h,实现用 .cc;命名空间 bcdl;错误通过 BCDL_CHECK(...)bcdl::Error。与周围代码的风格和结构保持一致。
  • 测试 —— 任何行为变更都要新增或更新测试。用一个通过 decode_* 绑定的 确定性 NumPy 测试钉死后处理数学(任意地方可跑),并在涉及模型时补一个板端 端到端测试,且其模型缺失时能干净跳过。
  • 提交 —— 保持聚焦;遵循日志中已有的 Conventional Commits 风格。
  • Changelog —— 在 CHANGELOG.md[Unreleased] 下记录 对用户可见的变更。

致谢

  • D-Robotics —— RDK S100 / S100P / S600 平台与 hobot SDK(hbDNNhbUCPhb_vp、多媒体/编解码),BCDL 构建于其上,以及 rdk_model_zoo 参考模型。
  • nanobind —— Python 绑定层。
  • OpenCV —— 预处理路径上的图像操作。
  • BCDL 重新实现了其后处理的上游模型作者 —— PaddleOCR / PaddlePaddle (PP-OCRv5、PP-LCNet)、Ultralytics(YOLO 系列)、Depth-Anything-V2DeepLabV3+。其许可证见模型;BCDL 不打包这些权重中的任何一个。

许可证

BCDL 以 Apache License 2.0 授权 —— 见 LICENSE

这只覆盖 BCDL 自身的源码。你拉取到 models/ 的第三方模型权重受其各自上游 许可证约束(见模型)—— 尤其 Ultralytics YOLO 权重为 AGPL-3.0; BCDL 既不打包也不重新分发其中任何一个。

About

BPU-native vision stack for RDK S100/S100P/S600: zero-copy inference pipelines, hardware-accelerated codec, and Python/C++ SDK.

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors