Intel RealSense depth camera D435i 数据获取时的一些坑(附,全套数据采集示例代码)

“示例代码——通过 Intel RealSense 设备获取2D图像、3D点云等原始数据”

先放github链接:https://github.com/denkywu/intel-realsense-camera-data-collection-demo

说明如下:

  •  基于Intel RealSense 设备(相机)获取2D图像、3D点云等原始数据。这里对原始数据的定义为:直接通过Intel RealSense SDK 2.0从设备中获取的数据,基本没有经过其他数据后处理。
  • 已经测试(使用)过的设备,如下:
    • Intel RealSense depth camera D435i
    • Intel RealSense depth camera D435
    • Intel RealSense depth camera D415
    • 理论上来说,只要支持Intel RealSense SDK 2.0的设备都可以通过该示例代码获取数据。只是要注意,某些设备可能拥有或没有某些接口。
  • 可以获取的原始数据如下:
    • color image,2D彩色图像
    • 点云 xyz
    • texture image,点云纹理彩色图像,与点云xyz(或者说深度图像)是对齐的
    • 点云 xyzrgb,将点云 xyz和texture image组合得到
    • ir left image,左侧ir灰度图像
    • ir right image,右侧ir灰度图像
    • 由于本人并不需要imu数据,所以这方面的内容目前没有涉及
  • 示例代码中,主要是实现了一个自定义类”class RealSenseData“(详见文件"realSenseData.h" 和"realSenseData.cpp"),使用该自定义类的demo(main函数)见文件"mainDemo.cpp"。
  • 示例代码中,通过配置文件"ConfigCameraRealSense.yaml"可对不同相机(比如color,depth)设置分辨率和帧率等。所以在生成了可执行文件后,需要将该文件拷贝至对应目录下,即可运行程序。
  • 数据采集自定义类class RealSenseData中的一些接口示例如下(详细内容请参见github):
public:
	// 设备状态
	bool devStart();// 设备启动
	bool devStop();// 设备关闭
	bool isDevConnected() const;// 设备是否连接
	bool isDevReady() const;// 设备是否准备好采集数据
	
	// 数据
	cv::Mat getColorImage_2dCamera();// 2D彩色相机获取的2D彩色图像
	cv::Mat getPointCloud_3dCamera();// 3D相机获取的点云xyz数据
	cv::Mat getTextureImage_3dCamera();// 3D相机获取的点云纹理彩色图像
	cv::Mat getIrLeftImage_3dCamera();// 3D相机获取的 IR left 图像
	cv::Mat getIrRightImage_3dCamera();// 3D相机获取的 IR right 图像
	
	// 相机内参和畸变参数
	// 2D相机
	cv::Matx33f getIntrinsics_2dCamera();// 2D相机-内参
	cv::Matx<float,5,1> getDistortion_2dCamera();// 2D相机-畸变参数
	// 3D相机
	cv::Matx33f getIntrinsics_3dCamera();// 3D相机-内参
	cv::Matx<float,5,1> getDistortion_3dCamera();// 3D相机-畸变参数

	// 外参, get Depth-to-Color Extrinsics
	cv::Matx33f getRotation();
	cv::Matx31f getTranslation();

  • 基于Intel RealSense depth camera D415设备,采集的一组数据示例如下:

1)2D彩色图像

2)点云xyzrgb,在CloudCompare中打开后的截图

3)点云纹理彩色图像(将2D彩色图像配准到3D点云上的结果,与深度图像是对齐的,即分辨率和点云相同)

4)IR left 灰度图像(图中暗纹就是D415在采集深度数据时发射的红外散斑

5)IR right 灰度图像(D415是基于双目视觉Stereo+红外散斑来获取深度图像或者说点云数据的。红外散斑的红外强度是可以调节和关闭的,在SDK 2.0中有相应接口,各位感兴趣的话可以试试。该right灰度图像和上面的left是配套的)

完。

 

-------------------------------------------  分割线 -------------------------------------------

1、RealSense D435i的图像空间、相机空间的坐标系定义都与OpenCV一致,这里不再赘述(可参考我在这篇博客中对坐标系内容的描述,https://blog.csdn.net/denkywu/article/details/89850166)。

但是,我在使用其SDK中的函数 export_to_ply() 导出点云ply文件时发现了以下大坑,听我慢慢道来:

1)首先获取点云数据,以下是基本框架

rs2::pointcloud rs2_PointCloud;// Declare pointcloud object, for calculating pointclouds and texture mappings
rs2::points rs2_Points;

auto rs2_Frameset = pipe.wait_for_frames();// Set of time synchronized frames, one from each active stream
auto rs2_ColorFrame = rs2_Frameset.get_color_frame();// get video_frame - first found color frame. 
auto rs2_DepthFrame = rs2_Frameset.get_depth_frame();// get depth_frame - first found depth frame.

// ---------------------------------------------------------------------------------
rs2_PointCloud.map_to(rs2_ColorFrame);// Tell pointcloud object to map to this frame - as texture.
// 将RGB信息作为纹理与点云(深度图)匹配上
// ! 注意 !
// 要想将深度图(点云)和纹理 .map_to(),必须先进行这一步
// 然后才能进行下面的 .calculate() 计算 rs2::points
// 这是我经过实验发现的,如果将先后顺序反过来,会有问题
// ---------------------------------------------------------------------------------

// Generate the pointcloud and texture mappings
rs2_Points = rs2_PointCloud.calculate(rs2_DepthFrame);// 获取三维点云数据

2)在获取 rs2_Points 后,可直接通过方法 export_to_ply() 导出ply文件到本地路径,例如:

rs2_Points.export_to_ply("pointCloud.ply", rs2_ColorFrame);

下面代码是官方SDK中关于该方法的说明

/**
* Export current point cloud to PLY file
* \param[in] string fname - file name of the PLY to be saved
* \param[in] video_frame texture - the texture for the PLY.
*/
void export_to_ply(const std::string& fname, video_frame texture)
{
    rs2_frame* ptr = nullptr;
    std::swap(texture.frame_ref, ptr);
    rs2_error* e = nullptr;
    rs2_export_to_ply(get(), fname.c_str(), ptr, &e);
    error::handle(e);
}


/**
* When called on Points frame type, this method creates a ply file of the model with the given file name.
* \param[in] frame       Points frame
* \param[in] fname       The name for the ply file
* \param[in] texture     Texture frame
* \param[out] error      If non-null, receives any error that occurs during this call, otherwise, errors are ignored
*/
void rs2_export_to_ply(const rs2_frame* frame, const char* fname, rs2_frame* texture, rs2_error** error);

以上看起来没什么特别的,但是使用该方法导出ply文件并打开后,你会发现:任何一个点的z坐标(深度值)是负数!

经过验证后发现,官方SDK计算的深度图数据以及点云xyz信息都是没问题的(且坐标系定义和OpenCV一致)。如果自行将点云数据导出到ply文件也是没问题的。所以我认为:class points 的方法 export_to_ply() 在导出ply文件时,修改了点云xyz的坐标数值:x不变,y取反,z取反。这使得方法 export_to_ply()  导出的ply文件中点云xyz的数值在 y 和 z 坐标上与原始值相差了一个负号。

官方为何如此设置不得知,我猜测是为了ply文件打开后显示的更直观(比如在CloudCompare中打开,无需旋转,其视角就和“以相机照射方向向前看”是一致的),如果我们自行将点云数据存储并打开,是需要经过旋转才可以的。

这不是什么大问题,但是该函数并未进行说明,我认为挺坑的。一不小心,可能认为(我之前就误以为)RealSense的坐标系定义有某些特别之处。

 

2、RealSense内存泄漏问题

该问题我在github中找到了一模一样的叙述,“pointcloud processing block causing memory leak #2860”,网址https://github.com/IntelRealSense/librealsense/issues/2860

简单来说,就是把 rs2::pointcloud 放在循环中会导致内存泄漏(时间长了一定会发生。因为在每一次循环中该类生成的实例并未完全释放),解决方法就是将其放在循环以外。Mark

 

—— 后续再更新

评论 53
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值