DvsenseDriver  1.1.3
The SDK for dvsense products.
载入中...
搜索中...
未找到
融合相机使用教程

该部分介绍了如何通过 API 接口使用融合相机。

打开相机

获取融合数据

时间对齐

空间对齐

获取异步数据

保存数据

具体的代码例程可以在sdk安装目录下的Sample中找到

打开相机

在 DvsenseDriver 中,所有相机使用 dvsense::DvsCameraManager 类进行统一管理。

查找相机

// find all cameras
std::vector<dvsense::CameraDescription> cameraDescs = cameraManager.getCameraDescs();
相机管理器类
定义 DvsCameraManager.hpp:35
std::vector< CameraDescription > getCameraDescs()
获取相机描述符向量

dvsense::CameraDescription 中包含相机的制造商、产品型号、序列号等信息。

可以通过产品型号来区分事件相机或融合相机。

打开融合相机

dvsense.DvsCameraManager.openFusionCamera接口可以使用序列号打开指定的融合相机

// Open the first camera found
dvsense::FusionCameraDevice fusion_camera = cameraManager.openFusionCamera(serial);
FusionCameraDevice openFusionCamera(Serial serial)
DVSENSE_API std::shared_ptr< FusionCamera > FusionCameraDevice
定义 DvsCameraManager.hpp:29

dvsense::FusionCameraDevice 是对 dvsense.FusionCamera的易用性封装 typedef std::shared_ptr<FusionCamera> FusionCameraDevice

开始和停止取流

打开相机后,相机默认是不进行取流的,需要手动开启。

注意!! 在取流开始之前,请参照下面的 获取并处理事件 注册 异步处理事件 的回调函数。

fusion_camera->start(); // 开始取流
fusion_camera->stop(); // 停止取流

start跟stop 函数可以指定流模式dvsense::STREAM_TYPE来控制自己想获取的数据,当前流模式有 DVS_STREAM, APS_STREAM, FUSION_STREAM(Alpha版本仅支持获取融合流)

获取并处理融合数据

由于RGB图像跟事件流为两个不同的数据流,需要对这两个数据进行时间对齐与空间对齐。

我们提供融合示例代码,请参考 DvsenseDriver\include\DvsenseDriver\DataProcess\DvsApsFusionProccessor.hpp 及 Samples\DvsenseSyncViewerSample\DVSyncViewer.cpp 文件

使用方式如下:

//从机器中读取标定文件并加载到标定类中
dvsense::Calibrator calibrator
if(camera->readCalibrationParam(cali_param))
{
dvsense::paramToJsonFile(cali_param, "./calibration.json");
calibrator_.loadCalibrationParam(cali_param);
}
dvsense::DvsApsFusionProccessor fusion_processor; //实例化融合相机处理功能
// 注册融合功能的回调函数,在有融合数据时会自动触发此回调函数
fusion_processor.addFusionDataCallback([&sync_displayer](dvsense::ApsFrame &frame, const dvsense::Event2D *begin, const dvsense::Event2D *end)
{
//先使用标定类对获取到的aps进行映射,将其映射到dvs尺寸
dvsense::ApsFrame aps_to_dvs_frame = calibrator.mapApsToDvs(frame);
sync_displayer.processApsFrame(aps_to_dvs_frame);
sync_displayer.fusionDvsToAps(begin, end); });
//注册aps数据的回调函数,通过proccessor来进行时间对齐处理
camera->addApsFrameCallback([&fusion_processor](const dvsense::ApsFrame &frame)
{ fusion_processor.addApsData(frame); });
//注册dvs数据回调函数,通过proccessor来进行时间对齐
camera->addEventsStreamHandleCallback([&fusion_processor](const dvsense::Event2D *begin, const dvsense::Event2D *end)
{ fusion_processor.addDvsData(begin, end); });
// 注册trigger in回调函数,通过trigger in来对dvs数据做打包处理
camera->addTriggerInCallback([&fusion_processor](const dvsense::EventTriggerIn &trigger_in)
{ fusion_processor.addTriggerInData(trigger_in); });
定义 DvsApsFusionProccessor.hpp:17
void addFusionDataCallback(DsFusionDataCallback cb)
添加融合数据回调函数
定义 DvsApsFusionProccessor.hpp:53
void addApsData(const ApsFrame &frame)
添加aps数据用于融合
定义 DvsApsFusionProccessor.hpp:79
void addDvsData(const Event2D *begin, const Event2D *end)
添加dvs数据用于融合
定义 DvsApsFusionProccessor.hpp:70
定义 TypeUtils.hpp:34

时间对齐

​ 我们提供了dvsense::DvsApsFusionProccessor 类来做时间对齐,在使用时仅需要将事件流、视频流、以及trigger同步信号这三个回调函数注册为dvsense::DvsApsFusionProccessor数据接口中,dvsense::DvsApsFusionProccessor类会自动进行时间同步同步好之后通过addFusionDataCallback回调的方式来供客户接收数据。

​ 如果您有需求也可以DIY自己的dvsense::DvsApsFusionProccessor类来进行时间同步以及回调函数的处理。

‍具体的时间对齐代码可以参考 DvsApsFusionProccessor

空间对齐

由于融合相机内部结构及光路影响,RGB图像与事件数据(DVS)在空间上会存在偏差。因此,我们将在生产过程中对此偏差进行校准,并将校准结果保存于设备内部。

**标定补偿映射**: 我们用Calibrator类用来进行标定补偿映射,并提供APS和DVS双向映射的接口,完成DVS和RGB相机的空间对齐。

  • 加载标定参数
    camera = cameraManager.openFusionCamer(open_camera_serial);//获取相机句柄
    dvsense::Calibrator calibrator_;//标定补偿类
    dvsense::CalibratorParameters cali_param;//标定参数
    camera->readCalibrationParam(cali_param)//读取标定参数(参数预设在相机中,需要手动读取)
    calibrator_.loadCalibrationParam(cali_param);//加载标定参数
  • APS映射到DVS

    dvsense::ApsFrame aps_to_dvs_frame = calibrator_.mapApsToDvs(aps_frame);//APS到DVS的映射
  • DVS映射到APS
    cv::Mat dvs_to_aps_frame = calibrator_.mapDvsToAps(dvs_frame);//DVS到APS的映射

可参考我们提供的样例程序:Samples/DvsenseSyncViewerSample/DVSyncViewer.cpp

获取异步数据

融合相机当前仅支持异步获取数据。

异步处理DVS事件

相机提供了 dvsense::FusionCamera::addEventsStreamHandleCallback 接口,这个接口可以实时访问事件流。每当一小包事件完成传输和解码后,注册进入的回调函数就会被调用。

以下是一个使用示例,该示例中,对一张空白图片 img 中发生了事件的位置赋予颜色,以进行后续的可视化:

camera->addEventsStreamHandleCallback([&img](const dvsense::Event2D* begin, const dvsense::Event2D* end) {
// 执行某些操作或仅复制数据
for (auto it = begin; it != end; ++it) {
img.at<cv::Vec3b>(it->y, it->x) = (it->polarity) ? color_on : color_off;
}
});

‍警告:在使用回调函数接口时,必须尽可能减少回调函数的执行时间,否则会导致数据累积并导致程序崩溃。

您可以使用 dvsense::FusionCamera::addEventsStreamHandleCallback 函数添加多个回调函数,当事件流可用时,这些回调函数将按照注册顺序依次执行。您也可以记录回调函数的ID号,使用 dvsense::FusionCamera::addEventsStreamHandleCallback 的返回值,然后通过 dvsense::FusionCamera::removeEventsStreamHandleCallback 函数删除不再需要的回调函数。

auto cb_id = camera->addEventsStreamHandleCallback([](const dvsense::Event2D* begin, const dvsense::Event2D* end) {
// 执行某些操作或仅复制数据
});
camera->removeEventsStreamHandleCallback(cb_id);

异步处理RGB图像

相机提供了dvsense::FusionCamera::addApsFrameCallback 接口,这个接口可以实时访问事件流。每当一帧RGB图像完成传输和解码后,注册的回调函数就会被调用。

以下是一个使用示例,该示例中,对一张空白图片 aps_image_ 进行赋值,以进行后续的可视化:

aps_image_ = cv::Mat(aps_height_, aps_width_, CV_8UC3);
camera->addFrameCallback([&aps_image_](dvsense::ApsFrame &aps_frame) {
std::memcpy(aps_image_.data, aps_frame.data(), aps_frame.getDataSize());
});

‍警告:在使用回调函数接口时,必须尽可能减少回调函数的执行时间,否则会导致数据累积并导致程序崩溃。

您可以使用 dvsense::FusionCamera::addApsFrameCallback 函数添加多个回调函数,当事件流可用时,这些回调函数将按照注册顺序依次执行。您也可以记录回调函数的ID号,使用 dvsense::FusionCamera::addApsFrameCallback 的返回值,然后通过 dvsense::FusionCamera::removeApsFrameCallback 函数删除不再需要的回调函数。

auto cb_id = camera->addApsFrameCallback([](dvsense::ApsFrame &) {
// 执行某些操作或仅复制数据
});
camera->removeApsFrameCallback(cb_id);

保存数据

在相机开始取流之后,可以使用 dvsense::FusionCamera::startRecordingdvsense::FusionCamera::stopRecording 将融合相机的事件流保存为 raw 文件,视频流保存为mp4文件,以便后续回放和处理。

camera->startRecording(out_file_path, filename); // 开始录制, 在输入文件名时无需输入文件尾缀
camera->stopRecording(); // 停止录制

下一节