一.深度图简介
目前深度图像的获取方法有激光雷达深度成像法,计算机立体视觉成像,坐标测量机法,莫尔条纹法,结构光法等等,针对深度图像的研究重点主要集中在以下几个方面,
- 深度图像的分割技术
- 深度图像的边缘检测技术
- 基于不同视点的多幅深度图像的配准技术
- 基于深度数据的三维重建技术
- 基于三维深度图像的三维目标识别技术
- 深度图像的多分辨率建模和几何压缩技术等等
在PCL 中深度图像与点云最主要的区别在于其近邻的检索方式的不同,并且可以互相转换。
深度图像(Depth Images)也被称为距离影像(Range Image),是指将从图像采集器到场景中各点的距离值作为像素值的图像,它直接反应了景物可见表面的几何形状,利用它可以很方便的解决3D目标描述中的许多问题,深度图像经过点云变换可以计算为点云数据,有规则及有必要信息的点云数据可以反算为深度图像数据。
从数学模型上看,深度图像可以看做是标量函数j:I2→Rj:I2→R在集合K上的离散采样,得到ri=j(ui)ri=j(ui),其中ui∈I2ui∈I2为二维网格(矩阵)的索引,ri∈R,i=1,...,kri∈R,i=1,...,k,以下为从不同视角获得的深度图像过程示意:
二. 如何从点云创建深度图
2.1 深度图Class介绍:
->类名: pcl::RangeImage
->继承关系:RangeImage类继承于PointCloud,主要功能是实现一个特定视点得到一个三维场景的深度图像。其继承关系如下:
2.2 通过点云创建深度图:
->语句:createFromPointCloud(pointCloud, angularResolution, maxAngleWidth, maxAngleHeight, sensorPose, coordinate_frame, noiseLevel, minRange, borderSize)
->输入参数:
- pointCloud:被检测点云
- angularResolution=1:邻近的像素点所对应的每个光束之间相差 1°
- maxAngleWidth=360:进行模拟的距离传感器对周围的环境拥有一个完整的360°视角,无论任何数据集都推荐使用此设置,因为最终获取的深度图像将被裁剪到有空间物体存在的区域范围
- maxAngleHeight=180: 当传感器后面没有可以观测的点时,设置一个水平视角为180°的激光扫描仪即可,因为需要观察距离传感器前面就可以了。
- sensorPose: 定义了模拟深度图像获取传感器的6DOF(6自由度)位置,其原始值为横滚角roll、俯仰角 pitch、偏航角 yaw 都为 0
- coordinate_frame: 设置为CAMERA_FRAME说明系统的X轴是向右的、Y轴是向下的、Z轴是向前的,另外参数值是LASER_FRAME,其X轴向前、Y轴向左、Z轴向上
- noiseLevel=0: 是指使用一个归一化的 Z缓存区来创建深度图像,如果想让邻近点集都落在同一个像素单元,可以设置一个较高的值,例如 noiseLevel = 0.05 可以理解为深度距离值是通过查询点半径为 5cm 的圆内包含的点用来平均计算而得到的 。
- minRange=0:如果设置>0则所有模拟器所在位置半径 minRange 内的邻近点都将被忽略,即为盲区。
- borderSize=1:如果设置>0 ,在裁剪图像时,将在图像周围留下当前视点不可见点的边界 。
三. C++代码实现(主要内容已经添加了注释)
主要过程为:
- 创建PointCloud点云,或者从PCD文件中读取点云;
- 创建pcl::RangeImage深度图对象,并设定相关参数
- 将点云转化为深度图
- 创建pcl viewer,并在其中显示出来深度图
/**This .cpp file is uesd to create a range image from a
* Point cloud, the code creates an example point cloud data of a
* rectangle floating in front of the observer and then, converting it into
* range image**/
#include <pcl/range_image/range_image.h>
#include <pcl/point_types.h> //定义了所有点云类型
#include <pcl/io/pcd_io.h> //点云文件输入输出
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/visualization/range_image_visualizer.h>
int main(int argc, char** argv){
//Step1 创建模拟点云数据
pcl::PointCloud<pcl::PointXYZ>::Ptr pointCloudPtr(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ>& pointCloud = *pointCloudPtr; //这个对象相当于是一个点集,存放着类型为pcl::PointXYZ的点
for(float y=-0.5f;y<= 0.5f; y+=0.01f){
for (float z=-0.5f;z<=0.5f;z+=0.01f){
pcl::PointXYZ point; //依次创建若干点,并保存到点云点集中
point.x =2.0f -y;
point.y =y;
point.z =z;
pointCloud.points.push_back(point);
}
}
//Step2. 设置点云的宽和高(将此点云设置为无序点云)
//无序点云!!! 宽度为size,高度为1
pointCloud.width = (uint32_t) pointCloud.points.size();
pointCloud.height = 1;
/**Step3!! 使用上边创建好的点云生成对应的深度图**/
/** 以下为从点云生成深度图的重要参数:
* -pointCloud:被检测点云
-angularResolution=1:邻近的像素点所对应的每个光束之间相差 1°
-maxAngleWidth=360:进行模拟的距离传感器对周围的环境拥有一个完整的360°视角,无论任何数据集都推荐使用此设置,因为最终获取的深度图像将被裁剪到有空间物体存在的区域范围
-maxAngleHeight=180: 当传感器后面没有可以观测的点时,设置一个水平视角为180°的激光扫描仪即可,因为需要观察距离传感器前面就可以了。
-sensorPose: 定义了模拟深度图像获取传感器的6DOF(6自由度)位置,其原始值为横滚角roll、俯仰角 pitch、偏航角 yaw 都为 0
-coordinate_frame: 设置为CAMERA_FRAME说明系统的X轴是向右的、Y轴是向下的、Z轴是向前的,另外参数值是LASER_FRAME,其X轴向前、Y轴向左、Z轴向上
-noiseLevel=0: 是指使用一个归一化的 Z缓存区来创建深度图像,如果想让邻近点集都落在同一个像素单元,可以设置一个较高的值,例如 noiseLevel = 0.05 可以理解为深度距离值是通过查询点半径为 5cm 的圆内包含的点用来平均计算而得到的 。
-minRange=0:如果设置>0则所有模拟器所在位置半径 minRange 内的邻近点都将被忽略,即为盲区。
-borderSize=1:如果设置>0 ,在裁剪图像时,将在图像周围留下当前视点不可见点的边界 。
*
* **/
float angularResolution = (float)(1.0f *(M_PI/180.0f)); //角分辨率
float maxAngleWidth = (float)(360.0f *(M_PI/180.0f)); //传感器视角360度
float maxAngleHeight = (float) (180.0f * (M_PI/180.0f)); // 180.0 degree in radians
Eigen::Affine3f sensorPose = (Eigen::Affine3f)Eigen::Translation3f(0.0f, 0.0f, 0.0f);
pcl::RangeImage::CoordinateFrame coordinate_frame = pcl::RangeImage::CAMERA_FRAME; //!!!
float noiseLevel=0.00;
float minRange = 0.0f;
int borderSize = 1;
boost::shared_ptr<pcl::RangeImage> range_image_ptr(new pcl::RangeImage);
pcl::RangeImage& rangeImage = *range_image_ptr;
rangeImage.createFromPointCloud(pointCloud, angularResolution, maxAngleWidth, maxAngleHeight,
sensorPose, coordinate_frame, noiseLevel, minRange, borderSize);
std::cout << rangeImage << "\n";
// --------------------------------------------
// -----在3D 视窗中 添加显示点云-----
// --------------------------------------------
pcl::visualization::PCLVisualizer viewer("3D viewer"); //创建一个3D可视化界面
viewer.setBackgroundColor (1,1,1); //设置视窗背景颜色rgb111
// 添加深度图点云
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointWithRange> range_image_color_handler (range_image_ptr, 0, 0, 0);
viewer.addPointCloud (range_image_ptr, range_image_color_handler, "range image");
viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 4, "range image");
// 添加原始点云
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> org_image_color_handler (pointCloudPtr, 255, 100, 0);
viewer.addPointCloud (pointCloudPtr, org_image_color_handler, "orginal image");
viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "orginal image");
viewer.initCameraParameters();
viewer.addCoordinateSystem(1.0);
while(!viewer.wasStopped()){
viewer.spinOnce();
pcl_sleep(0.01);
}
return 0;
}
四.程序运行效果
其中黑色的点是深度图的点,橙色的点是原始点云。