本文将介绍如何获取到彩色图像的深度信息。
大家都知道我们可以从realsense 摄像头中获取到RGB数据,红外数据,以及图像的深度数据。至于图像的深度数据我的理解是realsense摄像投抓到的图像的相关距离信息,具体点 可以理解成摄像头距离每个像素点的距离。这个深度数据在某些场景下非常的有意义。本文从之前两篇文章的基础上介绍如何在QT + OpenCV的环境下获取到RGB图像并且拿到深度信息。
主要分以下三个部分
-* RealSense 摄像头操作类的封装*
-* OpenCV Mat与QImage 之间的转换*
-* 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
上面一堆获取realsense camera 属性的函数,暂时可以忽略,最主要的是initRsDevice(),enableStream(),getFrameData(),getDistance(),四个函数。
初始化realsense 摄像头
void rsdevice::initRsDevice()
{
devCount = ctx.get_device_count();
dev = ctx.get_device(0);
.....................
.....................
}
开启摄像头数据流,在这里我们只开启两路数据,一路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();
}
获取到RGB彩色数据:
uchar * rsdevice::getFrameData(){
dev->wait_for_frames();
return (uchar *) dev->get_frame_data(rs::stream::color);
.................
获取位置的深度距离数据,传入(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;
}
我们设想的是之后从librealsense中拿到的数据需要通过OpenCV处理一遍,而从上面可得知从摄像头里取得的是uchar* 类型的指针,我们需要先转换成Open CV 中使用的Mat, 而后在QT中显示,需要再转换成QImage。
uchar* pRgb = dev->getFrameData();
Mat rgb_show;
Mat rgb(480, 640, CV_8UC3, pRgb);
由于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);
每次QT绘制消息过来的时候,从realsense中取一帧,做相应的转换,转成QImage对象,再刷出去。
从前面,我们已经拿到了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();
}
}
从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;
}
Demo 跑起来效果如下,不过貌似R200的深度信息是以米为最小单位,这个精度上会有点问题啊,还需要再确认下。