Range_Image深度图-1 PCL学习记录-9 Range_Image深度图原理,以及如何通过点云生成深度图

一.深度图简介

目前深度图像的获取方法有激光雷达深度成像法,计算机立体视觉成像,坐标测量机法,莫尔条纹法,结构光法等等,针对深度图像的研究重点主要集中在以下几个方面,

  • 深度图像的分割技术
  • 深度图像的边缘检测技术
  • 基于不同视点的多幅深度图像的配准技术
  • 基于深度数据的三维重建技术
  • 基于三维深度图像的三维目标识别技术
  • 深度图像的多分辨率建模和几何压缩技术等等

在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,以下为从不同视角获得的深度图像过程示意:img

img 

二. 如何从点云创建深度图

2.1 深度图Class介绍:

->类名: pcl::RangeImage

->继承关系:RangeImage类继承于PointCloud,主要功能是实现一个特定视点得到一个三维场景的深度图像。其继承关系如下:

img

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;
}

四.程序运行效果

其中黑色的点是深度图的点,橙色的点是原始点云。

 

猜你喜欢

转载自blog.csdn.net/weixin_42503785/article/details/112460758