Intel RealSense学习之图像及图像深度数据获取

本文将介绍如何获取到彩色图像的深度信息。
大家都知道我们可以从realsense 摄像头中获取到RGB数据,红外数据,以及图像的深度数据。至于图像的深度数据我的理解是realsense摄像投抓到的图像的相关距离信息,具体点 可以理解成摄像头距离每个像素点的距离。这个深度数据在某些场景下非常的有意义。本文从之前两篇文章的基础上介绍如何在QT + OpenCV的环境下获取到RGB图像并且拿到深度信息。

主要分以下三个部分
-* RealSense 摄像头操作类的封装*
-* OpenCV Mat与QImage 之间的转换*
-* Realsense 深度数据的获取*

RealSense 摄像头操作类的封装

我们使用一个c++类来封装对librealsense的操作:

#ifndef RSDEVICE_H
#define RSDEVICE_H
#include 
#include 

class rsdevice
{
public:
    rs::context ctx;
    rs::device * dev;
    int devCount;
    QString devName;
    QString devSerial;
    QString devFwVersion;
    QString devCamType;
    QString devIspFwVersion;
    bool streamEnable;

public:
    QString getDevName(){
        return devName;
    }

    QString getDevSerial(){
        return devSerial;
    }

    QString getDevFwVersion(){
        return devFwVersion;
    }

    QString getCamType(){
        return devCamType;
    }

    QString getIspFwVersion(){
        return devIspFwVersion;
    }

public:
    rsdevice();
    ~rsdevice();
    void initRsDevice();
    void enableStream();
    uchar * getFrameData();
    bool isSteamEnable();
    float getDistance(int x,int y);
};

#endif // RSDEVICE_H
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51

上面一堆获取realsense camera 属性的函数,暂时可以忽略,最主要的是initRsDevice(),enableStream(),getFrameData(),getDistance(),四个函数。

初始化realsense 摄像头

void rsdevice::initRsDevice()
{
 devCount = ctx.get_device_count();

 dev = ctx.get_device(0);
.....................
.....................
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

开启摄像头数据流,在这里我们只开启两路数据,一路RGB彩色数据,一路深度摄像头数据:

void rsdevice::enableStream(){
    streamEnable = true;
    dev->enable_stream(rs::stream::color, 640, 480, rs::format::rgb8, 60);
    dev->enable_stream(rs::stream::depth,640,480, rs::format::z16, 60);
    dev->start();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

获取到RGB彩色数据:

uchar * rsdevice::getFrameData(){
    dev->wait_for_frames();
    return (uchar *) dev->get_frame_data(rs::stream::color);
 .................
  • 1
  • 2
  • 3
  • 4

获取位置的深度距离数据,传入(x,y)点的坐标信息,获取到该点的距离。

float rsdevice::getDistance(int x, int y){
    uint16_t *depthImage = (uint16_t *) dev->get_frame_data(rs::stream::depth);
    float scale = dev->get_depth_scale();
    rs::intrinsics depthIntrin = dev->get_stream_intrinsics(rs::stream::depth);
    uint16_t depthValue = depthImage[y * depthIntrin.width + x];
    float depthInMeters = depthValue * scale;
    return depthInMeters;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

OpenCV Mat与QImage 之间的转换

我们设想的是之后从librealsense中拿到的数据需要通过OpenCV处理一遍,而从上面可得知从摄像头里取得的是uchar* 类型的指针,我们需要先转换成Open CV 中使用的Mat, 而后在QT中显示,需要再转换成QImage。

uchar* —> Mat

      uchar* pRgb = dev->getFrameData();
      Mat rgb_show;
      Mat rgb(480, 640, CV_8UC3, pRgb);
  • 1
  • 2
  • 3

Mat —> QImage

由于Mat 默认是BGR,需要先转成RGB

 cvtColor(rgb, rgb_show, CV_BGR2RGB);
 QImage img = QImage((const unsigned char *)(image.data), image.cols, image.rows,
                image.cols*image.channels(), QImage::Format_RGB888);
  • 1
  • 2
  • 3

每次QT绘制消息过来的时候,从realsense中取一帧,做相应的转换,转成QImage对象,再刷出去。

Realsense 深度数据的获取

从前面,我们已经拿到了RGB数据,并且显示出去了,现在我们需要去尝试拿到图像上的某一个点的深度信息。

转换坐标

QT中重写mousePressEvent函数,并且将坐标信息映射到图像当中:

void MainWindow::mousePressEvent(QMouseEvent *e){
    QPoint p = e->globalPos();
    p = picLabel->mapFromGlobal(p);
    int depth = dev->getDistance(p.x(),p.y());
    if(disInfoLabel != NULL){
        QString strLocation;
        strLocation.sprintf("The distance is %d",depth);
        disInfoLabel->setText(strLocation);
        disInfoLabel->move(e->x(),e->y());
        disInfoLabel->setFixedWidth(400);
        disInfoLabel->show();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

从realsense摄像头中计算出该像素点的距离信息:

float rsdevice::getDistance(int x, int y){
    uint16_t *depthImage = (uint16_t *) dev->get_frame_data(rs::stream::depth);
    float scale = dev->get_depth_scale();
    rs::intrinsics depthIntrin = dev->get_stream_intrinsics(rs::stream::depth);
    uint16_t depthValue = depthImage[y * depthIntrin.width + x];
    float depthInMeters = depthValue * scale;
    return depthInMeters;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

Demo 跑起来效果如下,不过貌似R200的深度信息是以米为最小单位,这个精度上会有点问题啊,还需要再确认下。

你可能感兴趣的:(OpenCV学习)