01 打开相机
任务目标
把"事件数据从哪里来"这件事讲清楚。事件相机有两种典型入口,选对入口是后续所有处理的前提:
| 入口 | 适用场景 | 涉及类 |
|---|---|---|
| 实时相机(USB / MIPI / Ethernet) | 实时采集 | Shimeta::hv::Camera + Shimeta::hv::DeviceConfig |
| 录像文件 | 离线分析、无硬件调试 | Shimeta::io::EventReader |
v2.0 三后端(USB / MIPI / Ethernet)统一为同一套
CameraAPI,后端由DeviceConfig.backend选择,不再有独立的 USB / MIPI 相机类。
入口一:实时相机
统一生命周期:构造 Camera → 填 DeviceConfig → Init(cfg) → StartStream() → 取帧 / 回调 → StopStream() → Destroy()。Init 不阻塞打开硬件,实际连接发生在 StartStream。
USB 相机(x86_64)
USB 后端用 VID/PID 选设备:
#include <shimetapi/hv/camera.h>
#include <shimetapi/hv/device_config.h>
#include <iostream>
int main() {
Shimeta::hv::Camera cam;
Shimeta::hv::DeviceConfig cfg;
cfg.backend = Shimeta::hv::Backend::Usb;
cfg.vendor_id = 0x1d6b; // 替换为你设备的实际 VID/PID
cfg.product_id = 0x0105;
cfg.event_fmt = Shimeta::hv::EventFormat::Evt2;
cam.Init(cfg);
if (!cam.StartStream()) {
std::cerr << "打开相机失败,请检查 USB 连接与权限。" << std::endl;
return 1;
}
std::cout << "相机已就绪" << std::endl;
// 此处 GetFrame 取帧 / 注册回调,见指引 02
Shimeta::Frame f;
while (cam.GetFrame(f, 1000)) { /* f.evs / f.aps */ }
cam.StopStream();
cam.Destroy();
return 0;
}USB 权限
首次运行若报 Cannot open device: LIBUSB_ERROR_ACCESS,推荐 udev 规则(免 sudo,持久):
echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="1d6b", ATTR{idProduct}=="0105", MODE="0666"' \
| sudo tee /etc/udev/rules.d/99-hv-camera.rules
sudo udevadm control --reload-rules && sudo udevadm trigger完整排查(no match devices found、VID/PID 确认等)见 Toolkit — 故障排除。
MIPI 相机(ARM64 / RDK)
MIPI 不是 USB 设备:不传 VID/PID,而用传感器索引、设备节点与 I2C 总线打开。后端选 Backend::Mipi(仅 EVS 事件)或 Backend::MipiHvs(双 VC:VC0 事件 + VC1 APS):
#include <shimetapi/hv/camera.h>
#include <shimetapi/hv/device_config.h>
int main() {
Shimeta::hv::Camera cam;
Shimeta::hv::DeviceConfig cfg;
cfg.backend = Shimeta::hv::Backend::MipiHvs; // 或 Backend::Mipi(仅事件)
cfg.device_node = "/dev/video0";
cfg.sensor_index = 9; // S100 当前 apx003cc 配置;X5 使用其 SDK 配置的索引(当前样例为 49)
cfg.i2c_bus = 1; // 安全芯片认证 I2C 总线
cfg.evs_fps = 0; // 0=默认 240;可选 120/240/300/500/750/1000
cam.Init(cfg);
if (!cam.StartStream()) return 1;
// 取帧见指引 02 / 07;注意 MipiHvs 的 Frame.evs 为 RAW8 子帧流,
// 需用 MipiRaw8Decoder 解码(见指引 02 / MIPI API)
cam.StopStream();
cam.Destroy();
return 0;
}sensor_index / i2c_bus 必须与载板和传感器匹配,不能照搬 USB 示例中的数值。MIPI 后端为 ARM-only,需 RDK sysroot 交叉编译(构建见 Toolkit — 快速开始),不适用 USB 权限和 lsusb 排查;还应确保没有其他进程占用该传感器。完整 MIPI 差异见 Toolkit C++ API — MIPI。
| 平台 | 发布库 | MIPI HVS 事件 | MIPI HVS APS | 构建目标 |
|---|---|---|---|---|
| S100 | lib/s100 | RAW8,MipiRaw8Decoder | NV12 | ./run.sh build s100 |
| X5 | lib/x5 | RAW8,MipiRaw8Decoder | Gray8 | ./run.sh build x5 |
两个平台共用 API,但必须使用对应架构的预编译库和 SDK/sysroot;不要把 S100 的库或传感器索引拷贝到 X5。
最小可运行示例对应仓库 samples/cpp/get_started:./hv_sample_get_started(USB,默认 0x1d6b:0x0105)或 ./hv_sample_get_started --mipi(MIPI)。
Ethernet 相机(DVS1 协议)
Ethernet 后端用 IP + 端口连接(POSIX TCP,无额外依赖):
Shimeta::hv::Camera cam;
Shimeta::hv::DeviceConfig cfg;
cfg.backend = Shimeta::hv::Backend::Ethernet;
cfg.ip = "192.168.1.100"; // 相机 IP
// data_port=8000 / ctrl_port=8001 为默认;相机作服务端时改用 listen_port / bind_ip
cam.Init(cfg);
cam.StartStream();入口二:录像文件
离线场景用 Shimeta::io::EventReader 打开 RAW 文件,按文件头 ev_version 自动识别 EVT2/EVT3,先查分辨率与格式:
#include <shimetapi/io/event_reader.h>
#include <iostream>
int main() {
Shimeta::io::EventReader reader;
if (!reader.open("events.raw")) {
std::cerr << "打开事件文件失败" << std::endl;
return 1;
}
auto [width, height] = reader.imageSize();
std::cout << "格式: " << static_cast<int>(reader.format()) << "\n" // 0=Evt2, 1=Evt3
<< "分辨率: " << width << " x " << height << std::endl;
// 读取并解码事件见指引 02,回放见指引 03
reader.close();
return 0;
}文件格式(EVT2 / RAW8 / CSV)与转换见 数据格式;示例录像见 下载。
进阶
- 完整 API:Toolkit C++ API
- 读到的数据怎么用:指引 02 读取事件
- 不写代码先看预览:MultiVision Studio
关于 Metavision / OpenEB 生态
v2.0 工具包已与第三方事件 SDK 完全解耦,不再随包提供 Metavision HAL 插件(旧版的 libhal_camera_hal.so 复制到 Metavision 插件目录的用法已失效)。若需在 Metavision 生态中使用,参见 Hybrid Vision Algo。
