PCL深度图像
转载自:https://www.cnblogs.com/li-yao7758258/p/6474699.html
目前深度图像的获取方法有激光雷达深度成像法,计算机立体视觉成像,坐标测量机法,莫尔条纹法,结构光法等等,针对深度图像的研究重点主要集中在以下几个方面,深度图像的分割技术 ,深度图像的边缘检测技术 ,基于不同视点的多幅深度图像的配准技术,基于深度数据的三维重建技术,基于三维深度图像的三维目标识别技术,深度图像的多分辨率建模和几何压缩技术等等,在PCL 中深度图像与点云最主要的区别在于 其近邻的检索方式的不同,并且可以互相转换。
(这一章是我认为非常重要的)
模块RangeImage相关概念以及算法的介绍
深度图像(Depth Images)也被称为距离影像(Range Image),是指将从图像采集器到场景中各点的距离值作为像素值的图像,它直接反应了景物可见表面的几何形状,利用它可以很方便的解决3D目标描述中的许多问题,深度图像经过点云变换可以计算为点云数据,有规则及有必要信息的点云数据可以反算为深度图像数据
不同视角获得深度图像的过程:
(1)PCL中的模块RangeImage相关类的介绍
pcl_range_image库中包含两个表达深度图像和对深度图像进行操作的类,其依赖于pcl::common模块,深度图像(距离图像)的像素值代表从传感器到物体的距离以及深度, 深度图像是物体的三维表示形式,一般通过立体照相机或者ToF照相机获取,如果具备照相机的内标定参数,就可以将深度图像转换为点云
1.class pcl::RangeImage
RangeImage类继承于PointCloud,主要功能是实现一个特定视点得到一个三维场景的深度图像。其继承关系如下:
类RangeImage的成员有:
Public Member Functions |
|
template<typename PointCloudType > | |
void | createFromPointCloud (const PointCloudType &point_cloud, float angular_resolution=pcl::deg2rad(0.5f), float max_angle_width=pcl::deg2rad(360.0f), float max_angle_height=pcl::deg2rad(180.0f), const Eigen::Affine3f &sensor_pose=Eigen::Affine3f::Identity(), CoordinateFrame coordinate_frame=CAMERA_FRAME, float noise_level=0.0f, float min_range=0.0f, int border_size=0) |
从点云创建深度图像,point_cloud为指向创建深度图像所需要的点云的引用,angular_resolution为模拟的深度传感器的角度分辨率,即深度图像中一个像素对应的角度大小,max_angle_width为模拟的深度传感器的水平最大采样角度,max_angle_height为模拟传感器的垂直方向最大采样角度,sensor_pose设置模拟的深度传感器的位姿是一个仿射变换矩阵,默认为4*4的单位矩阵变换,coordinate_frame定义按照那种坐标系统的习惯默认为CAMERA_FRAME,noise_level获取深度图像深度时,近邻点对查询点距离值的影响水平,min_range设置最小的获取距离,小于最小获取距离的位置为传感器的盲区,border_size获得深度图像的边缘的宽度 默认为0 该函数中涉及的角度的单位都是弧度 | |
template<typename PointCloudType > | |
void | createFromPointCloudWithKnownSize (const PointCloudType &point_cloud, float angular_resolution, const Eigen::Vector3f &point_cloud_center, float point_cloud_radius, const Eigen::Affine3f &sensor_pose=Eigen::Affine3f::Identity(), CoordinateFrame coordinate_frame=CAMERA_FRAME, float noise_level=0.0f, float min_range=0.0f, int border_size=0) |
从点云创建深度图像,其中参数中有关场景大小的提示,提高了获取深度图像时的计算速度。point_cloud为指向创建深度图像所需要的点云的引用,angular_resolution为模拟的深度传感器的角度分辨率,弧度表示,point_cloud_center为点云外接球体的中心,默认为(0,0,0)point_cloud_radius为点云外接球体的半径,sensor_pose设置模拟的深度传感器的位姿是一个仿射变换矩阵,默认为4*4的单位矩阵变换,coordinate_frame定义按照那种坐标系统的习惯默认为CAMERA_FRAME,noise_level获取深度图像深度时,近邻点对查询点距离值的影响距离,以米为单位,min_range设置最小的获取距离,小于最小获取距离的位置为传感器的盲区,border_size获得深度图像的边缘的宽度 默认为0 该函数中涉及的角度的单位都是弧度 |
|
template<typename PointCloudTypeWithViewpoints > | |
void | createFromPointCloudWithViewpoints (const PointCloudTypeWithViewpoints &point_cloud, float angular_resolution, float max_angle_width, float max_angle_height, CoordinateFrame coordinate_frame=CAMERA_FRAME, float noise_level=0.0f, float min_range=0.0f, int border_size=0) |
从点云创建深度图像,点云中包含深度信息,其中,point_cloud为指向创建深度图像所需要的点云的引用,angular_resolution为模拟的深度传感器的角度分辨率,即深度图像中一个像素对应的角度大小,max_angle_width为模拟的深度传感器的水平最大采样角度,max_angle_height为模拟传感器的垂直方向最大采样角度,sensor_pose设置模拟的深度传感器的位姿是一个仿射变换矩阵,默认为4*4的单位矩阵变换,coordinate_frame定义按照那种坐标系统的习惯默认为CAMERA_FRAME,noise_level获取深度图像深度时,近邻点对查询点距离值的影响水平,如果该值比较小,则常用Z-缓冲区中深度平均值作为查询点的深度,min_range设置最小的可视深度,小于最小获取距离的位置为传感器的盲区,border_size获得深度图像的边缘的宽度 默认为0 该函数中涉及的角度的单位都是弧度 | |
void | createEmpty (float angular_resolution, const Eigen::Affine3f &sensor_pose=Eigen::Affine3f::Identity(), RangeImage::CoordinateFrame coordinate_frame=CAMERA_FRAME, float angle_width=pcl::deg2rad(360.0f), float angle_height=pcl::deg2rad(180.0f)) |
创建一个空的深度图像,以当前视点不可见点填充,其中,angle_width为模拟的深度传感器的水平采样角度,默认为PI*2(360);angle_height垂直方向的采样角度默认为PI(180)*****其他参数同上 | |
template<typename PointCloudType > | |
void | integrateFarRanges (const PointCloudType &far_ranges) |
将已有的远距离测量结果融合到深度图像中, | |
PCL_EXPORTS void | cropImage (int border_size=0, int top=-1, int right=-1, int bottom=-1, int left=-1) |
裁剪深度图像到最小尺寸,使这个最小尺寸包含所有点云,其中,board_size设置裁剪后深度图像的边界尺寸, top为裁剪框的边界***********默认都为-1 | |
void | setTransformationToRangeImageSystem (const Eigen::Affine3f &to_range_image_system) |
设置从深度图像坐标系(传感器的坐标系)转换到世界坐标系的变换矩阵 | |
float | getAngularResolution () const |
获得深度图像X和Y方向的角分辨率 弧度表示 | |
void | setAngularResolution (float angular_resolution) |
设置深度图像在X方向和Y方向的新的角分辨率,angular_resolution即每个像素所对应的弧度 | |
void | calculate3DPoint (float image_x, float image_y, float range, PointWithRange &point) const |
根据深度图像点(X Y)和距离(range)计算返回场景中的3D点的point | |
void | calculate3DPoint (float image_x, float image_y, PointWithRange &point) const |
根据给定的深度图像点和离该点最近像素上的距离值计算返回场景中的3D 点point |
(详细的解释请官网查看)
(2)class pcl::RangeImagePlanner
RangeImagePlanner 来源于最原始的深度图像,但又区别于原始的深度图像,因为该类不使用球类投影方式,而是通过一个平面投影方式进行投影(相机一一般采用这种投影方式),因此对于已有的利用深度传感器获取的深度图像来说比较实用,类的继承关系如下:
Public Member Functions |
|
PCL_EXPORTS void | setDisparityImage (const float *disparity_image, int di_width, int di_height, float focal_length, float base_line, float desired_angular_resolution=-1) |
从给定的视差图像中创建图像,其中disparity_image是输入的视差图像,di_width视差图像的宽度di_height视差图像的高度focal_length, 产生视差图像的照相机的焦距,base_line是用于产生视差图像的立体相对的基线长度,desired_angular_resolution预设的角分辨率 每个像素对应的弧度,该值不能大于点云的密度, | |
PCL_EXPORTS void | setDepthImage (const float *depth_image, int di_width, int di_height, float di_center_x, float di_center_y, float di_focal_length_x, float di_focal_length_y, float desired_angular_resolution=-1) |
从已存在的深度影像中创建深度图像,其中,depth_image是输入的浮点形的深度图像,di_width,深度图像的宽度,di_height图像的高度,di_center_x di_center_y 是照相机投影中心XY的坐标。di_focal_length_x di_focal_length_y是照相机水平 垂直方向上的焦距,desired_angular_resolution预设的角分辨率 每个像素对应的弧度,该值不能大于点云的密度, | |
template<typename PointCloudType > | |
void | createFromPointCloudWithFixedSize (const PointCloudType &point_cloud, int di_width, int di_height, float di_center_x, float di_center_y, float di_focal_length_x, float di_focal_length_y, const Eigen::Affine3f &sensor_pose, CoordinateFrame coordinate_frame=CAMERA_FRAME, float noise_level=0.0f, float min_range=0.0f) |
从已存在的点云中创建图像,point_cloud为指向创建深度图像所需要的点云对象的引用,di_width视差图像的宽度di_height视差图像的高度 di_center_x di_center_y 是照相机投影中心XY的坐标 di_focal_length_x di_focal_length_y是照相机水平 垂直方向上的焦距 sensor_pose是模拟深度照相机的位姿 coordinate_frame为点云所使用的坐标系 noise_level传感器的水平噪声, | |
virtual void | calculate3DPoint (float image_x, float image_y, float range, Eigen::Vector3f &point) const |
根据给定图像点和深度图创建3D点,其中image_x iamge_y range 分别为XY 坐标和深度,point为生成的3D点 | |
virtual void | getImagePoint (const Eigen::Vector3f &point, float &image_x, float &image_y, float &range) const |
从给定的3D点point中计算图像点(X Y)和深度值 |
等等具体看官网
(3)应用实例
如何从点云创建深度图,如何从点云和给定的传感器的位置来创建深度图像,此程序是生成一个矩形的点云,然后基于该点云创建深度图像
新建文件range_image_creation.cpp:
#include <pcl/range_image/range_image.h> //深度图像的头文件 int main (int argc, char** argv) { pcl::PointCloud<pcl::PointXYZ> pointCloud; //定义点云的对象 // 循环产生点云的数据 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); //循环添加点数据到点云对象 } } pointCloud.width = (uint32_t) pointCloud.points.size(); pointCloud.height = 1; //设置点云对象的头信息 //实现一个呈矩形形状的点云 // We now want to create a range image from the above point cloud, with a 1deg angular resolution //angular_resolution为模拟的深度传感器的角度分辨率,即深度图像中一个像素对应的角度大小 float angularResolution = (float) ( 1.0f * (M_PI/180.0f)); // 1.0 degree in radians //max_angle_width为模拟的深度传感器的水平最大采样角度, float maxAngleWidth = (float) (360.0f * (M_PI/180.0f)); // 360.0 degree in radians //max_angle_height为模拟传感器的垂直方向最大采样角度 都转为弧度 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; //noise_level获取深度图像深度时,近邻点对查询点距离值的影响水平 float minRange = 0.0f; //min_range设置最小的获取距离,小于最小获取距离的位置为传感器的盲区 int borderSize = 1; //border_size获得深度图像的边缘的宽度 pcl::RangeImage rangeImage; rangeImage.createFromPointCloud(pointCloud, angularResolution, maxAngleWidth, maxAngleHeight, sensorPose, coordinate_frame, noiseLevel, minRange, borderSize); std::cout << rangeImage << "\n"; }
显示结果
微信公众号号可扫描二维码一起共同学习交流
每一个不曾起舞的日子,都是对生命的辜负。
But it is the same with man as with the tree. The more he seeks to rise into the height and light, the more vigorously do his roots struggle earthward, downward, into the dark, the deep - into evil.
其实人跟树是一样的,越是向往高处的阳光,它的根就越要伸向黑暗的地底。----尼采