RealSense D435i 数据获取时的一些坑

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

 

—— 后续再更新

你可能感兴趣的:(工作)