在 Librealsense SDK 中将 OpenCV Mat 转换为 Realsense 的帧类型

Posted

技术标签:

【中文标题】在 Librealsense SDK 中将 OpenCV Mat 转换为 Realsense 的帧类型【英文标题】:Convert OpenCV Mat to Frame type of Realsense in Librealsense SDK 【发布时间】:2018-10-01 06:52:23 【问题描述】:

我有 RGB 数据作为 rs2::frame,我将其转换为 cv::Mat 并通过 TCP 连接发送,在服务器(接收器)端我将缓冲区存储到 cv::Mat 中。我的问题是如何在接收端将 cv::Mat 转换为 rs2::frame,以便使用支持 rs2::frame 类型的 SDK 函数?

【问题讨论】:

【参考方案1】:

您需要模拟软件设备才能拥有 rs2::frame。

在this example 之后,您可以编写自己的类来创建合成流,从 cv::Mat 实例中获取数据。

例如,这是我为解决问题所做的一些事情。


rsImageConverter.h

#include <librealsense2/rs.hpp>
#include <librealsense2/hpp/rs_internal.hpp>

class rsImageConverter

public:
    rsImageConverter(int w, int h, int bpp);

    bool convertFrame(uint8_t* depth_data, uint8_t*  color_data);

    rs2::frame getDepth() const;
    rs2::frame getColor() const;

private:
    int w = 640;
    int h = 480;
    int bpp = 2;

    rs2::software_device dev;
    rs2::software_sensor depth_sensor;
    rs2::software_sensor color_sensor;
    rs2::stream_profile depth_stream;
    rs2::stream_profile color_stream;
    rs2::syncer syncer;

    rs2::frame depth;
    rs2::frame color;

    int ind = 0;
;

rsImageConverter.cpp

#include "rsimageconverter.h"

rsImageConverter::rsImageConverter(int w, int h, int bpp) :
    w(w),
    h(h),
    bpp(bpp),
    depth_sensor(dev.add_sensor("Depth")), // initializing depth sensor
    color_sensor(dev.add_sensor("Color")) // initializing color sensor

    rs2_intrinsics depth_intrinsics w, h, (float)(w / 2), (float)(h / 2), (float) w , (float) h , RS2_DISTORTION_BROWN_CONRADY , 0,0,0,0,0  ;
    depth_stream = depth_sensor.add_video_stream(  RS2_STREAM_DEPTH, 0, 0,
                                w, h, 60, bpp,
                                RS2_FORMAT_Z16, depth_intrinsics );
    depth_sensor.add_read_only_option(RS2_OPTION_DEPTH_UNITS, 0.001f); // setting depth units option to the virtual sensor

    rs2_intrinsics color_intrinsics =  w, h,
            (float)w / 2, (float)h / 2,
            (float)w / 2, (float)h / 2,
            RS2_DISTORTION_BROWN_CONRADY , 0,0,0,0,0  ;
    color_stream = color_sensor.add_video_stream( RS2_STREAM_COLOR, 0, 1, w,
                                    h, 60, bpp,
                                    RS2_FORMAT_RGB8, color_intrinsics );


    dev.create_matcher(RS2_MATCHER_DLR_C); // create the matcher with the RGB frame

    depth_sensor.open(depth_stream);
    color_sensor.open(color_stream);

    depth_sensor.start(syncer);
    color_sensor.start(syncer);

    depth_stream.register_extrinsics_to(color_stream,   1,0,0,0,1,0,0,0,1 , 0,0,0  );


bool rsImageConverter::convertFrame(uint8_t*  depth_data, uint8_t*  color_data)

    depth_sensor.on_video_frame( depth_data, // Frame pixels
                                      [](void*) , // Custom deleter (if required)
                                      w*bpp, bpp, // Stride and Bytes-per-pixel
                                      (rs2_time_t)ind * 16, RS2_TIMESTAMP_DOMAIN_HARDWARE_CLOCK, ind, // Timestamp, Frame# for potential sync services
                                      depth_stream );
    color_sensor.on_video_frame( color_data, // Frame pixels from capture API
        [](void*) , // Custom deleter (if required)
        w*bpp, bpp, // Stride and Bytes-per-pixel
        (rs2_time_t)ind * 16, RS2_TIMESTAMP_DOMAIN_HARDWARE_CLOCK, ind, // Timestamp, Frame# for potential sync services
        color_stream );

    ind++;

    rs2::frameset fset = syncer.wait_for_frames();
    depth = fset.first_or_default(RS2_STREAM_DEPTH);
    color = fset.first_or_default(RS2_STREAM_COLOR);

    return (depth && color); // return true if everything went good


rs2::frame rsImageConverter::getDepth() const

    return depth;


rs2::frame rsImageConverter::getColor() const

    return color;


然后你可以这样使用它(假设depth和rgb为两个cv::Mat,其中depth在CV_16U中转换,rgb是CV_8UC3,从BGR到RGB的转换):

rsImageConverter* converter = new rsImageConverter(640, 480, 2);

...

if(converter->convertFrame(depth.data, rgb.data)) 

    rs2::frame rs2depth = converter->getDepth();
    rs2::frame rs2rgb = converter->getColor();

    ... // Here you use these frames

顺便说一句,我设计这个类时同时使用了深度和 RGB。要仅转换其中一个,您只需将空框架传递给另一个参数,或更改类。

【讨论】:

以上是关于在 Librealsense SDK 中将 OpenCV Mat 转换为 Realsense 的帧类型的主要内容,如果未能解决你的问题,请参考以下文章

在 ubuntu 中使用 librealsense 的 C++ 构建错误

缓慢构建 librealsense libusb

c_cpp librealsense2手动从差异变换到深度,反之亦然

如何在 iphone sdk 中将 NSArray/NSMutableArray 转换为 NSFetchedResultsController?

在 Android 中将 SDK 版本更新为 24.3 后,所有库都显示错误

在 Ionic 中将 Android 和 iOS 原生代码 SDK 暴露给 Javascript