vio_capture & srcampy 完整对比详解(D-Robotics RDK X3/X5)
前置基础
- VIO = Video Input/Output:地瓜 RDK 平台视频输入输出子系统,管理MIPI CSI ISP、图像缩放、数据流通路、HDMI 显示、硬件编码。
- 两者底层共用同一套内核 VIO 驱动;只是上层 Python 封装两套 API。
- 底层驱动模块名字就叫
vio_capture;这也是命名源头。
一、总体演进路线
plaintext
早期SDK:vio_capture(单纯采集接口) ↓ 新版SDK:libsrcampy(srcampy)【一体化多媒体套件】 底层不变:VIO驱动 + AMP多媒体流水线官方现状:
✅srcampy 作为新项目标准推荐(FCOS MIPI Demo 采用)
⚠️ vio_capture 仅做兼容保留,不再新增功能。
二、vio_capture 详解
1. 定位
轻量化单一功能采集接口,只负责从 MIPI CSI读取图像,无显示、无硬件 bind、无 OSD、无编码能力。 导入方式
python
运行
from hobot_vio import vio_capture2. 核心类:VioCapture
构造参数
python
运行
cap = vio_capture.VioCapture( video_index=0, # CSI0=0;CSI1=2 width=512, height=512, format="nv12" # 仅支持nv12 )常用方法
python
运行
frame = cap.read() # 获取 nv12 numpy数组,阻塞读取 cap.release() # 释放CSI、ISP资源3. 数据流模型
只能配置单路分辨率输出
plaintext
MIPI Sensor → ISP → 硬件缩放成 [w,h] NV12 → read()给到Python限制:同一路 CSI 只能输出一种尺寸图像。 如果你同时想要: 512×512(AI 推理)+ 1920×1080(HDMI 预览)vio_capture原生不支持硬件双通路。
4. 优点
- API 极简,上手快;
- 开销小,适合无屏幕、只做后端 AI 运算的设备;
5. 致命短板
- 不支持 ISP 硬件双路输出;
- 没有 HDMI 显示、硬件数据流绑定;
- 如果要预览画面:Python 必须持续读取大图,转发到 Display,占用带宽 + CPU,延迟高;
- 不支持 OSD 画框、文字叠加;
- 不支持硬件 H.264/H.265 编码。
6. 适用场景
- 无头设备(无 HDMI 显示器);
- 只需要单一分辨率图像做 AI 推理,不需要实时预览录像;
三、srcampy(libsrcampy)详解
全称释义回顾: src(图像源)+ amp(AMP 高级多媒体流水线)+ py(python 绑定)
python
运行
try: from hobot_vio import libsrcampy as srcampy except ImportError: from hobot_vio_rdkx5 import libsrcampy as srcampy1. 定位
一体化全栈多媒体SDK能力覆盖:MIPI 采集 + ISP 多路缩放 + HDMI 显示 + 硬件 DMA 数据流绑定 + OSD 图层绘图 +硬件音视频编码。
包含四大核心类:
srcampy.Camera():摄像头采集srcampy.Display():HDMI 输出、OSD 图层srcampy.Encoder():硬件 H264/H265 编码srcampy.Decoder():硬件码流解码
2. Camera 类核心接口
open_cam () 【最关键】
python
运行
cam.open_cam(video_index, fps, [w1,w2], [h1,h2], sensor_h, sensor_w)[w1,w2] [h1,h2]:ISP 硬件双通路同时输出两路不同分辨率 NV12 图像- 通路 1:小图(512×512)→ AI 推理
- 通路 2:原图(1920×1080)→ HDMI 预览 👉硬件同时生成两路,CPU 不参与缩放
get_img(fmt_id, w, h)
python
运行
img = cam.get_img(2, 512, 512)- fmt_id=2 代表 NV12;
- 指定读取哪一路分辨率的图像;
- 返回 bytes 裸 buffer,可直接
np.frombuffer送入 dnn.forward ()
close_cam()
释放 CSI 通道与 ISP 资源。
3. Display 类核心接口
python
运行
disp = srcampy.Display() disp.display(layer_id, w, h) # layer0:原始视频图层 # layer3:OSD透明叠加图层(画框、文字)OSD 绘图函数:
set_graph_rect()绘制矩形检测框set_graph_word()绘制文本标签
4. 全局超级接口:srcampy.bind ()
python
运行
srcampy.bind(cam, disp)硬件 DMA 直通绑定摄像头 ISP 输出大图,直接路由到 HDMI,图像数据完全不经过 Python 内存。 优势:极低延迟、几乎零 CPU 占用。
这是 srcampy 相比 vio_capture 最大的杀手锏。
5. srcampy 完整流水线(FCOS 代码)
plaintext
MIPI CSI0 → ISP ├─通路A:1920×1080 NV12 → bind硬件直通HDMI(原始画面) └─通路B:512×512 NV12 → cam.get_img读取 → BPU FCOS推理 ↳ 推理结果 → Display OSD图层叠加框6. srcampy 适用场景
- 需要 HDMI 实时预览 + AI 推理同时运行;
- 目标检测任务,需要硬件 OSD 绘制框;
- 需要多路分辨率、硬件编码录像;
- 对画面延迟敏感的机器人视觉项目。
四、vio_capture VS srcampy 横向对比总表
表格
| 对比项 | vio_capture | srcampy(libsrcampy) |
|---|---|---|
| 包 | hobot_vio.vio_capture | hobot_vio.libsrcampy |
| 产品定位 | 轻量化单纯采集 | 全功能多媒体套件 |
| ISP 双路硬件输出 | ❌不支持 | ✅原生支持 |
| 硬件 bind 直通 HDMI | ❌无 | ✅支持,极低延迟 |
| OSD 绘制矩形 / 文字 | ❌无 | ✅Display 图层接口 |
| 硬件 H264/H265 编码 | ❌无 | ✅Encoder 类支持 |
| 图像格式 | 仅 NV12 | 仅 NV12 |
| CSI 通道编号规则 | CSI0=0,CSI1=2 | CSI0=0,CSI1=2(规则完全一致) |
| 推荐新项目 | 不推荐(仅兼容) | ✅官方标准推荐 |
| 典型 demo 场景 | 无头设备纯 AI 运算 | MIPI+HDMI 目标检测(当前 FCOS 工程) |
五、高频工程坑点
1. 互斥占用
同一 CSI 通道,不能同时打开 vio_capture 和 srcampy.Camera,会抢占VIO 驱动,打开失败。
2. CSI1 通道极易踩错
无论两套 API:
CSI0 → index=0
CSI1 → index=2 不要写 1!
3. vio_capture 无法实现 “预览 + 推理并行”
如果用 vio_capture,想要同时预览,只能持续读取大图,Python 转发,CPU 负载上升、延迟明显变大。
4. 资源释放
程序异常退出不执行release()/close_cam(),ISP 锁死,需要重启开发板才能重新打开摄像头。
六、选型建议(直接套用)
项目需要HDMI 预览 / 检测框 OSD / 录像编码 / 双分辨率👉直接使用 srcampy(libsrcampy)
设备无显示器,只做后端 AI 识别,单一分辨率,追求代码极简 👉 可选 vio_capture
七、最简示例对照
vio_capture 极简模板
python
运行
from hobot_vio import vio_capture import numpy as np cap = vio_capture.VioCapture(0, 512, 512, "nv12") while True: frame = cap.read() # dnn forward(frame) cap.release()srcampy 极简模板
python
运行
from hobot_vio_rdkx5 import libsrcampy as srcampy import numpy as np sensor_w, sensor_h = 1920,1080 model_w, model_h = 512,512 preview_w, preview_h = 1920,1080 cam = srcampy.Camera() cam.open_cam(0, -1, [model_w, preview_w], [model_h, preview_h], sensor_h, sensor_w) disp = srcampy.Display() disp.display(0, preview_w, preview_h) srcampy.bind(cam, disp) disp.display(3, preview_w, preview_h) while True: nv12_buf = cam.get_img(2, model_w, model_h) img = np.frombuffer(nv12_buf, dtype=np.uint8) # dnn forward(img) cam.close_cam() disp.close()