本文将介绍如何获取到彩色图像的深度信息。
大家都知道我们可以从realsense 摄像头中获取到RGB数据,红外数据,以及图像的深度数据。至于图像的深度数据我的理解是realsense摄像投抓到的图像的相关距离信息,具体点 可以理解成摄像头距离每个像素点的距离。这个深度数据在某些场景下非常的有意义。本文从之前两篇文章的基础上介绍如何在QT + OpenCV的环境下获取到RGB图像并且拿到深度信息。
主要分以下三个部分
-* RealSense 摄像头操作类的封装*
-* OpenCV Mat与QImage 之间的转换*
-* Realsense 深度数据的获取*
RealSense 摄像头操作类的封装
我们使用一个c++类来封装对librealsense的操作:
#ifndef RSDEVICE_H
#define RSDEVICE_H
#include <librealsense/rs.hpp>
#include <QString>
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的深度信息是以米为最小单位,这个精度上会有点问题啊,还需要再确认下。