一个开源的AI边缘计算平台:一个项目把算能、瑞芯微、x86的NPU全打通了

1.引言

1. 这套引擎解决什么问题?

把"能在电脑上跑的算法"变成"能在盒子上长期跑的应用",且换芯片不改业务代码。 一次接入、多平台复用,补上模型管理、编排、报警、事件这些"工程脏活"。

2. 它是怎么解决的?

上层一套流程编排,下层把解码、缩放、推理、后处理抽象成统一接口,按芯片各写一份实现;构建时只编入一个后端,模型随平台生成。

3. 跑起来是什么效果?

官方给了一份多平台 72 小时连续观测:前三款按 8 路 / 16 个任务绑定、RV1126B 按 4 路 / 8 个绑定配置,四款芯片平均 5.09~5.23 FPS/路 ,4320 个采样点保留 4316 个(99.91%),零丢弃、零严重事件;并发混合负载下算能 BM1688 跑到 16 路 / 32 个业务绑定,瑞芯微 RV1126B 为 4 路 / 8 个绑定。x86 上不需要任何 NPU,一条 docker compose 就能在浏览器里看到带框的实时检测结果:

图:x86 模式跑通的"未戴安全帽"检测任务,左侧实时画面带检测框与 OSD 叠加,右侧为算法结果列表。无需边缘硬件即可复现。

多平台 72 小时受控观测(每业务 5 FPS,本地回放输入):

平台 配置路数 任务绑定 采样点 最低 / 平均 / 最高 FPS 最大丢弃 峰值 CPU / 内存 / 磁盘 结论
算能 BM1688 8 16 4316 / 4320 4.68 / 5.086 / 5.49 0 30% / 44% / 96% PASS
算能 CV186X 8 16 4316 / 4320 4.54 / 5.085 / 5.29 0 43% / 44% / 96% PASS
瑞芯微 RK3576 8 16 4316 / 4320 5.00 / 5.098 / 5.17 0 46% / 30% / 15% PASS
瑞芯微 RV1126B 4 8 4316 / 4320 4.85 / 5.230 / 5.37 0 41% / 41% / 47% PASS

单任务容量矩阵(最后一列是"通过的最大路数",≥ 表示配置上限内都过了):

平台 任务 24 FPS 10 FPS 7 FPS 5 FPS
BM1688 人员检测 ≥8 ≥16 ≥16 ≥16
BM1688 未戴安全帽(检测+分类) ≥7* ≥14* ≥16 ≥16
CV186X 人员检测 ≥8* ≥15* ≥16 ≥16
CV186X 未戴安全帽 6 ≥13* ≥16 ≥16
RK3576 人员检测 6 12 ≥16 ≥8†
RK3576 未戴安全帽 6 10 12 ≥16
RV1126B 人员检测 2 ≥4 ≥4 ≥4
RV1126B 未戴安全帽 2 ≥4 ≥4 ≥4

压测总览卡片(49 个独立小模型用例 + 72 小时长跑 + VLM 验证):

2.项目拆解 & 分析

  1. 项目架构

图:从接入层到硬件层的六层结构。注意最底部那行字------一个二进制只含一个推理后端,这是理解整个项目的钥匙。

整个仓库 1500+ 个源文件(src/ 下),主体是 C++17,前端是 Vue 3。源码目录划分得很干净:

目录 干什么的 我的备注
src/nn 推理后端抽象 (core / node / device / pipeline / guard) 全项目最值钱的部分
src/media 解复用、解码、编码、帧处理、OSD 叠加 按平台各写一份,工厂选择
src/mem 设备上下文 + 定长块内存池 边缘端内存碎片是隐形杀手
src/infer 检测/分类/跟踪/识别/OCR/VLM 的统一封装 业务侧的门面
src/flow 通道、任务、动作链、报警、区域判断 编排层的执行体
src/service 服务注册与业务服务域(任务/模型/事件/系统...) 启动入口在这里
src/api HTTP/WebSocket 消息路由与处理器 40+ 个消息处理器
src/db SQLite DAO(人员、事件、审核、客流...) 端侧轻量持久化
src/network HTTP Server、MQTT 客户端 事件外发通道
src/platform 看门狗、网卡、重启、时间 7×24 运行的兜底

启动时序也很有工程味:ServiceRegistry 分四步------注册基础设施服务 → 注册业务服务 → 初始化 → 启动运行时服务(MQTT / HTTP / WebSocket / 设备发现 / 存储清理 / 看门狗)。看门狗和存储清理被当成一等公民,说明这玩意儿是冲着"装在现场无人值守"去的,不是 demo。

  1. 项目实现流程

把上面的架构落到"一帧视频从进来到报警出去",就是下面这条链路(右列是模型导入的离线链路):

图:左列是运行时主链路,右列是模型导入与图装配。两条线在"推理"这一步汇合------这也是理解"换模型不改代码"的关键。

1 运行时主链路:一帧要走完的 11 步

① 视频接入。 支持本地文件、RTSP、USB 摄像头(V4L2),新版本还加了 ONVIF 发现与鉴权取流、GB28181 的信令与 TCP/UDP 取流。解复用层用策略模式拆成 FileDemuxStrategy / NetworkDemuxStrategy / RtspDemuxStrategy / UsbDemuxStrategy,统一交给 VideoDemuxer 调度。

② 解复用。 FFmpeg 拉流,产出 H.264/H.265 码流包。

③ 解码。 三家分叉最狠的一步:VideoDecoderCreateSophon.cc(走 VPU 硬解)、VideoDecoderCreateRockchip.cc(走 MPP)、VideoDecoderCreateCpu.cc(FFmpeg 软解)。工厂函数签名一致,编译期选一个实现编进去。瑞芯微那个解码器实现有 3.3 万字节------可见平台差异的脏活全在这层。

④ 帧分发 + 按任务抽帧。 前面讲过的 AlgDataQueueDistributor:一路帧按 channelId/taskId 复制到多个任务队列,每个队列用自己的 FpsCtrl 控帧率。比如相机是 24 FPS,但"人员检测"任务只要 5 FPS,那就 5 FPS 采样,剩下 19 帧直接不进推理。

⑤ 预处理。 缩放、裁剪、仿射变换、归一化。能上 NPU 就上 NPU(SophonCropResizeNode 等),不能就 CPU(HostNodeFactory)。

⑥ 神经网络推理。 真正的前向。权重格式 .bmodel / .rknn / .onnx,运行时 BMRT / RKNN / ONNX Runtime。

⑦ 后处理。 解码头 → 框/类别/分数 → NMS。可在 NPU(NODE_YOLO_NPU_DECODE)或 CPU(yolov8_decode_node)。输出统一成 ObjectInfoV1 这类结构:{box, classId, score, mask?, corners?(旋转框)}。

⑧ 跟踪 + 规则过滤。 跟踪这块源码很扎实:src/nn/utils/tracker/ 下有匈牙利算法匹配(hungarian.cc,1.4 万字节)+ 卡尔曼滤波(eigen_kalman_filter.cc、eigen_kalman_tracker.cc),也有轻量版 default_tracker。过滤则包括类别过滤、最小尺寸过滤、ROI 区域过滤。

⑨ 二级分类 / 大模型复核。 检测到人体后裁一块小图送去分类(比如"戴帽/没戴帽"),或者调用视觉语言模型做复核。后者见 TaskAlarmLlmReview.cc------先把疑似目标筛出来,再让大模型看一眼,而不是每帧都跑大模型,这个成本控制思路很务实(VLM 的实测能力只有 0.1 FPS/路量级,必须这么省着用)。

⑩ 报警判定 · 灵敏度 · 抑制。 这块代码量惊人(TaskAlarmEventBuilder.cc 3.1 万字节、AreaAlarm.cc 1.2 万字节、TaskAlarmSuppression.cc 6 千字节)。灵敏度有两种常见形态:计时型 (连续命中 N 秒才报)和计数型(命中次数达到阈值才报)。抑制则负责去重------同一个目标在短时间内不重复刷屏。

⑪ 事件上报。 结构化事件 + 最佳抓拍帧(AiDetectBestEl 里存了最优质量分和对应帧)+ 可选录像片段,落 SQLite,同时通过 REST / WebSocket / MQTT / HTTP Webhook 外发。

2 离线链路:一个模型是怎么被"翻译"成执行图的

右列那 8 步,是从"训练好的模型"到"能被引擎加载"的过程:

  1. 训练产出:自有数据训练或第三方开源模型(ONNX 等);
  2. 平台转换:算能转.bmodel、瑞芯微转.rknn、x86 直接用.onnx;
  3. 打包:config.json(模型类型、输入输出 shape、归一化参数、标签、阈值)+ 权重 + MD5;
  4. 上传与校验:这里有个我喜欢的安全细节------ArchiveListingValidator专门做解压清单校验(防 zip slip 这类路径穿越);
  1. 解析为元信息:CombinedModelInfo(shape、dtype、预处理参数、解码类型、max_batch);
  2. 装配计算图:预处理链 → Net 节点 → 后处理链,多模型可串联;
  3. 加载权重 + 预分配:LoadWeight()→InferTopDesc()推导每个节点输出 shape →AllocaAllBlobs()一次性分配;
  4. 实例池预热:按任务数准备 N 份推理实例。

3.运行结果

控制台:可视化编排长什么样

真正让我觉得"这不只是个推理库"的,是它的编排画布。任务不是代码写死的,而是在浏览器里把节点拖成一条链:

图:编排画布。内置模板的节点顺序是:视频解码 → 目标检测 → 追踪 → 类别过滤 → 目标分类 → 目标判断 → 灵敏度计算 → 事件上报。

编排时文档里给了四条很实在的原则,我 paraphrase 一下:

  1. 先产生数据,再应用规则------没解码就不能推理,没有目标就不能做区域判断;
  2. 尽早过滤------在昂贵的分类/大模型节点之前,先把无关类别和过小目标滤掉;
  3. 一个节点只干一件事------重复插同类过滤会让结果无法解释;
  4. 先跑通最小链路,再逐项加------先解解码 + 检测,再加跟踪、区域、事件。

社区里还有个 x86 上跑 YOLOv8 猫狗检测的实录,实时结果页是这样的:

另一张官方教程里的结果页截图,可以看到事件列表与抓拍图:

联系我们

有课设/论文指导需求或图像算法开发、商务合作,欢迎联系并注明来意。

相关推荐
可涵不会debug36 分钟前
从“会动”到“会干”:2026年机器人开发者生态观察
人工智能·机器人·启元机器人
人工智能AI技术38 分钟前
腾讯开源Octop源码拆解:单进程自托管多用户AI助手架构
人工智能
星核0penstarry42 分钟前
宕机那天 API 还能用,所以模型是假的?
运维·服务器·人工智能·大模型·ai编程·模型指纹
小oo呆43 分钟前
【学习心得】Python函数参数中的两个特殊分隔符
开发语言·python
几何心凉1 小时前
端到端具身交互智能正式上线:让 AI 通过屏幕和机器人,真正走进现实世界
前端·人工智能·实时互动·机器人·交互
JAVA_AI人工智能项目实战1 小时前
强化学习与大模型对齐_学习笔记
人工智能·语言模型·自然语言处理
SEO_juper1 小时前
AI 爬虫 robots.txt 检查工具:你的站是不是把 AI 挡在门外了
开发语言·人工智能·爬虫·python·外贸独立站
涛思数据(TDengine)1 小时前
TDengine TSDB 3.4.3.3 上线:流计算分层闭环、虚拟表跨层引用,查询关联一次写完
数据库·人工智能·数据分析·时序数据库·tdengine·工业
碧海银沙音频科技研究院1 小时前
基于ATS308X的无线语音交互对话功能实现
人工智能·嵌入式硬件·深度学习·算法