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) |
![]() |
![]() |
![]() |
整个 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封装hbDNN(hbDNNInferV2);自动处理缓存一致性 (推理前 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(预处理 ‖ 推理 重叠)、TrackingPipeline、StereoPipeline,以及视频文件 → 解码 → 检测的链路。 - 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/lib:libdnn、libhbucp、libhbvp)—— 或安装下文的hobot-dnn/hobot-mediaconda 包。 BCDL 的源码在整个 S 系列上一致;而编译出的.hbm是 march 相关的, 所以请运行为你目标板编译的模型(见模型)。 - 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(libdnn、libhbucp、libhbvp…)+ hobot/ 头文件 |
| hobot-media | 多媒体/编解码线(libffmedia、libgdcbin、libmultimedia…)+ 多媒体开发头文件 |
如果只是 纯 C++ 的使用方,只装库即可,并用 find_package(bcdl) 来构建
(它会一并拉入 libbcdl + hobot-dnn + hobot-media):
conda install -c https://mirrors.ruis.ai/conda -c conda-forge libbcdl打包的 hobot SDK 仍依赖板上的 设备平台库 (
libbpu、libhbmem、libalog、libvdsp、libhbipcfhal),位于/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.decode、bcdl.decode_pose、bcdl.decode_obb、bcdl.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/prefixfind_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_detection、test_classification、test_pose、test_obb、test_instance_seg、test_depth_seg(+_py)、test_ocr、test_stereo_py、test_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_py、test_video_decode_py |
11 | 是 |
| 流水线(ByteTrack、异步检测) | test_tracking_py、test_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(
hbDNN、hbUCP、hb_vp、多媒体/编解码),BCDL 构建于其上,以及rdk_model_zoo参考模型。 - nanobind —— Python 绑定层。
- OpenCV —— 预处理路径上的图像操作。
- BCDL 重新实现了其后处理的上游模型作者 —— PaddleOCR / PaddlePaddle (PP-OCRv5、PP-LCNet)、Ultralytics(YOLO 系列)、Depth-Anything-V2 与 DeepLabV3+。其许可证见模型;BCDL 不打包这些权重中的任何一个。
BCDL 以 Apache License 2.0 授权 —— 见 LICENSE。
这只覆盖 BCDL 自身的源码。你拉取到 models/ 的第三方模型权重受其各自上游
许可证约束(见模型)—— 尤其 Ultralytics YOLO 权重为 AGPL-3.0;
BCDL 既不打包也不重新分发其中任何一个。











