本书概要
《点云库PCL学习教程》的出版日期 2012.10
库版本:PCL 1.51
PCL官网
PCL官方文档
PCL官方教程
PCL1.7.2文档
本书框架
部分 | 章节 | 内容 | 备注 |
---|---|---|---|
第1部分 | 第1~3章 | PCL概述、入门、基础 | 基础篇 |
第2部分 | 第4~7章 | PCL基础功能模块:输入/输出、kd-tree、八叉树、可视化 | 模块篇 |
第2部分 | 第8~15章 | PCL高级处理功能模块:点云滤波、深度图像、关键点、采样一致性、点云特征描述与提取、点云配准、点云分割、点云曲面重建 | 模块篇 |
第3部分 | 第16章 | 综合应用:对齐对象模板到点云、基于VFH描述子的聚类识别与6自由度位姿估计 | 综合应用篇 |
实例索引
主题 | 内容 | 备注 |
---|---|---|
输入/输出 | 从PCD文件中读取点云数据 | |
输入/输出 | 向PCD文件写入点云数据 | |
输入/输出 | 连接两个点云中的字段形成新点云 连接两个点云中的数据形成新点云 |
连接字段 连接点云 |
输入/输出 | PCL中的OpenNI点云获取框架 | |
kd-tree | 某一点的k近邻搜索 某一点的半径r内近邻搜索 |
|
八叉树 | 点云压缩 | 单个点云 点云数据流 |
八叉树 | 基于octree的空间划分及近邻搜索 | 体素内近邻搜索 K近邻搜索 半径内近邻搜索 |
八叉树 | 无序点云数据集的空间变化检测 | 只能探测在cloudA上增加的点集,而不能探测在cloudA上减少的点集 |
可视化 | 点云视窗类CloudViewer | |
可视化 | 可视化深度图 | 在3D视窗中以点云形式可视化 将深度值映射为颜色,从而以颜色图像方式可视化 |
可视化 | 可视化类PCLVisualizer | 没跑通,报错“pcl::visualization::PCLVisualizer::addCoordinateSystem”: 对重载函数的调用不明确 |
点云滤波 | 使用直通滤波器对点云进行滤波处理 | pcl::PassThrough 对指定的某一维度过滤掉指定范围内部(或外部)的点 |
点云滤波 | 使用VoxelGrid滤波器对点云进行下采样 | pcl::VoxelGrid 减少点的数量,并同时保持点云的形状特征 |
点云滤波 | 使用StatisticalOutlierRemoval滤波器移除离群点 | pcl::StatisticalOutlierRemoval 使用统计分析技术,从点云数据集中移除测量噪声点(即离群点) |
点云滤波 | 使用参数化模型投影点云 | pcl::ProjectInliers 将点投影到一个参数化模型(平面或球等)上 |
点云滤波 | 从点云中提取索引 | pcl::ExtractIndices 基于某一分割算法提取点云中的一个子集 |
点云滤波 | 使用ConditionalRemoval或RadiusOutlierRemoval移除离群点 | pcl::RadiusOutlierRemoval 删除在输入的点云一定范围内没有至少达到足够多近邻的所有数据点,适合去除单个的离群点 pcl::ConditionalRemoval 一次删除满足对输入的点云设定的一个或多个条件指标的所有数据点,比较灵活 |
深度图像 | 从点云创建深度图像 | 给定点云和传感器位置 |
深度图像 | 从深度图像中提取边界 | 边界:从前景跨越到背景的位置 |
关键点 | 从深度图像中提取NARF关键点 | |
采样一致性 | 使用采样一致性算法获得点云的拟合平面模型 | |
点云特征描述与提取 | 法线估计 | |
点云特征描述与提取 | 使用积分图进行法线估计 | 只适用于有序点云 |
点云特征描述与提取 | 从深度图像中提取NARF特征 | |
点云特征描述与提取 | 特征描述子算法基准化分析 | 报错 |
点云配准 | 使用迭代最近点算法 | ICP |
点云配准 | 逐步匹配多幅点云 | 可视化迭代过程 |
点云配准 | 使用正态分布变换进行配准 | |
点云分割 | 平面模型分割 | 基于RANSAC的分割算法 |
点云分割 | 圆柱体模型分割 | 基于RANSAC的分割算法,先加直通滤波 |
点云分割 | 欧式聚类提取 | 聚类分割算法 |
点云曲面重建 | 基于多项式拟合的法线估计、点云平滑、数据重采样 | |
点云曲面重建 | 在平面模型上提取凹(凸)多边形 | |
点云曲面重建 | 无序点云的快速三角化 | |
对齐对象模板到点云 | ||
基于VFH描述子的聚类识别与6自由度位姿估计 |
基础篇
PCL概述
PCL(Point Cloud Library)是跨平台开源C++编程库。
PCL架构图
PCL中处理惯导的基本接口程序:
- 创建处理对象(例如过滤、特征估计、分割等)
- 使用setInputCloud通过输入点云数据,处理模块
- 设置算法相关参数
- 调用计算(或过滤、分割等)得到输出
PCL的模块化
libpcl filters
libpcl features
libpcl I/O
libpcl segmentations
libpcl surface
libpcl register
libpcl keypoints
libpcl range
PCL入门
Windows下安装PCL
从预编译包搭建开发环境(All in one安装包)
用第三方预编译包从源码搭建开发环境
从源码搭建开发环境Ubuntu下安装PCL
预编译包搭建1
2
3sudo add-apt-repository ppa:v-launchpad-jochen-sprickerhof-de/pcl
sudo apt-get update
sudo apt-get install libpcl-all从源代码安装
用CMake建立PCL应用程序
PCL基础
1.PCL C++编程规范
命名规范 | 条目 | 举例 |
---|---|---|
文件命名 | 单词之间用下划线隔开 | unordered_map.hpp |
文件命名 | 头文件的扩展名 | .h |
文件命名 | 模板类实现文件的扩展名 | .hpp |
文件命名 | 源文件的扩展名 | .cpp |
目录命名 | ||
Include语句 | 文件在同一目录下 | |
Include语句 | 其他情况下 | |
宏定义命名 | 名称从include下目录开始,为头文件定义的宏最后要加上下划线 | |
命名空间命名 | 单词之间用下划线隔开 | namespace pcl_io{…} |
类/结构命名 | 驼峰命名(CamelCased) | class ExampleClass; |
函数/成员函数命名 | 首个单词首字母小写,其他单词首字母大写(camelCased) 参数用下划线隔开,最好采用动词 |
int applyExample(int example_arg); |
变量命名 | 单词之间用下划线隔开 | int my_variable; |
变量命名 | 迭代自变量:反应出迭代的对象 | std::list |
变量命名 | 常量:全大写 | const static int MY_CONSTANT = 1000; |
变量命名 | 成员变量:单词之间用下划线隔开,并以下划线结尾 | int example_int_; |
Return语句 | 在圆括号中设定返回值 | return(0); |
2.编写新的PCL类
建立文件结构、填写类的内容
3.点索引机制
方法 | 作用 |
---|---|
setInputCloud() | 传递点云数据的标准方法 |
setIndices() | 传递ROI或点云集 |
4.PCL已有点类型介绍(25种)、增加自定义的点类型
5.异常处理机制
模块篇
输入/输出
OpenNI开源框架
OpenNI提供一组基于传感器设备实现的API和另一组由中间件组件实现的API,可以保证编写应用程序的时候,不用考虑传感器或中间件供应商的相关细节。
OpenNI框架应用概念分为三层
- 应用层
基于OpenNI实现的自然交互应用软件 - 中间件接口层
代表OpenNI本身,提供了传感器和中间件组件之间的交互接口 - 硬件设备层
列出了捕捉视觉和音频数据的多种硬件设备
OpenNI兼容设备:Primesense Reference Design、Microsoft Kinect、Asus XtionPro
I/O模块
21个类、28个函数
获取、读入、存储
PCD、PLY
OBJ、VTK、PNG
点云数据格式PCD(Point Cloud Data)
PCL中PCD文件格式的正式发布是0.7版本(PCD_V7)
其他描述点云的格式:PLY、STL、OBJ、X3D
PCD文件头格式 P88
KD树
点云特点
通过雷达、激光扫描、立体相机等三维测量设备获取的点云数据
- 特点:数据量大、分布不均匀
- 表征:目标表面的海量点集合
点云数据处理中最为核心的问题:建立离散点间的拓扑关系,实现基于邻域关系的快速查找
k维树
kd-tree是一种带有其他约束条件的二分查找树,用来组织表示k维空间中点集合,对于区间和近邻搜索十分有用
通常只在三个维度中进行处理,因此所有的kd-tree都将是三维kd-tree
如上图,kd-tree的每一级在指定维度上分开所有的子节点
kd-tree模块
3个类、2个函数
PCL中kd-tree库提供了kd-tree数据结构,基于FLANN进行快速最近邻检索
最近邻检索在匹配、特征描述子计算、邻域特征提取中是非常基础的核心操作
八叉树
octree概述
建立空间索引,一般是自顶向下逐级划分空间的各种空间索引结构,其中KD树、八叉树在3D点云数据组织中应用广泛
点云空间索引方法octree
八叉树结构通过对三维空间的几何实体进行体元剖析,每个体元具有相同的时间和空间复杂度,通过循环递归的划分方法对大小为2n×2n×2n的三维空间的几何对象进行剖分,从而构成一个具有根节点的方向图。
octree模块
16个类
PCL中octree库提供了octree数据结构,基于FLANN进行快速邻域检索
邻域检索在匹配、特征描述子计算、邻域特征提取中是非常基础的核心操作
octree是一种用于管理稀疏3D数据的树状数据结构,每个内部节点都正好有8个子节点
把边界框内的点云分配给octree:defineBoundingBox
OctreePointCloudChangeDetector类继承自Octree2BufBase类,Octree2BufBase类允许同时在内存中保存和管理两个octree。
通过访问”octree.switchBuffers()”,重置了八叉树octree对象的缓冲区,但把之前的octree数据仍保留在内存中。
可视化
visualization类模块
28个类
PCL中pcl_visualization库提供了可视化相关的数据结构和组件,其主要是为了可视化其他模块的算法处理后的结果,可直观的反馈给用户
点云视窗类CloudViewer不能应用于多线程应用程序中
PCLVisualizer是CloudViewer的后端
PCLVisualizer可视化类:
- 可视化单个点云
- 可视化点云颜色特征
- 可视化点云自定义颜色特征
- 可视化点云法线和其他特征
- 绘制普通形状
- 多视口显示
- 自定义交互
点云滤波
PCL中点云滤波方案
几种需要进行点云滤波的情况:
- 点云数据密度不规则需要平滑
- 因为遮挡等问题造成离群点需要去除
- 大量数据需要进行下采样(Downsample)
- 噪声数据需要去除
对应的方法:
- 按具体给定的规则限制过滤去除点
- 通过常用滤波算法修改点的部分属性
- 对数据进行下采样
滤波算法:双边滤波、高斯滤波、条件滤波、直通滤波、基于随机采样一致性滤波
滤波处理:点云处理流程中预处理的第一步
filters模块
32个类、5个函数
类 | 功能 |
---|---|
class pcl::ApproximateVoxelGrid <PointT> | 根据给定的点云形成三维体素栅格,并利用所有体素的中心点近似体素中包含的点集,这样完成下采样得到滤波结果 适合对海量点云数据在处理前进行数据压缩,特别是在特征提取等处理中选择合适的体素大小等尺度相关参数,可以提高算法效率 |
class pcl::BilateralFilter<PointT> | 双边滤波 点云类型中必须有强度字段 |
class pcl::BoxClipper3D<PointT> | 实现用一个以原点为中心、XYZ各个方向尺寸为2、经过用户指定仿射变换的立方体进行空间剪裁,通过设置一个仿射变换矩阵先对立方体进行变换处理,之后输出仿射变换后落在该立方体内的点集 |
class pcl::ConditionalRemoval<PointT> | 过滤满足一定条件的点云数据 可由用户设置滤波条件 |
class pcl::filters::Convolution<PointIn, PointOut> | 实现卷积滤波的功能,通过设定不同的卷积核对点云进行卷积滤波处理 |
class pcl::filters::GaussionKernel<PointIn, PointOut> | 基于高斯核的卷积滤波实现 高斯滤波器相当于一个具有平滑性能的低通滤波器,通过该类处理后的点云,通常比较平滑 |
class pcl::filters::GaussionKernelRGB<PointIn, PointOut> | 附加RGB通道基于高斯核的卷积滤波实现 在滤波处理时不仅考虑空间XYZ信息,而且考虑RGB可见光信息 |
class pcl::CropBox<PointT> | 过滤掉给定立方体内的点云数据 |
class pcl::CropHull<PointT> | 过滤掉给定三维封闭曲面(ConvexHull)或二维封闭多边形(ConcaveHull)内部或外部的点云数据 |
class pcl::ExtractIndices<PointT> | 从点云中提取索引 |
class pcl::NormalSpaceSampling<PointT, NormalT> | 计算输入点云的每个点的法线,通过对法线方向的采样来对点云进行重采样 |
class pcl::PassThrough<PointT> | 用户给定点云某个字段的限定,对点云进行简单的基本过滤 如限制过滤掉点云中所有X字段不在某个范围内的点 |
class pcl::PlaneClipperD<PointT> | 在三维空间实现平面裁剪 |
class pcl::ProjectInliers<PointT> | 使用一个模型和一组内点的索引,将内点投影到模型形成新的一个独立点云 |
class pcl::RadiusOutlierRemoval<PointT> | 实现删除离群点的简单的滤波功能 如果一个点在给定搜索半径范围内邻近点数量小于给定阈值K,则判定为离群点并删除 |
class pcl::RandomSample<PointT> | 实现对点云的均匀概率随机抽样 |
class pcl::StatisticalOutlierRemoval<PointT> | 通过对查询点与邻域点集之间的距离统计判定来过滤离群点 对每个点的邻域进行统计分析,并修剪掉不符合一定标准的点 稀疏离群点移除方法基于在输入数据中对点到邻近点的距离分布的计算。对每个点,计算它到它的所有邻近点的平均距离。假设得到的结果是一个高斯分布,其形状由均值和标准差决定,平均距离在标准范围(由全局距离平均值和方差定义)之外的点,可被定义为离群点,并可从数据集中去除掉 |
class pcl::VoxelGrid<PointT> | 根据给定的点云构造一个三维体素栅格并进行下采样达到滤波的效果 通过输入的点云数据创建一个三维体素栅格,然后将每个体素内所有的点都用该体素内的点集的重心来近似,这样就大大减少了数据量,常用于对大数据量的下采样处理,提高程序速度 PS:体素重心比体素中心慢,但采样点对应曲边的表示更准确 |
深度图像
Range Images
深度图像(Depth Images)也被称为距离影像(Range Images),是指将从图像采集器到场景中各点的距离(深度)值作为像素值的图像,它直接反映了景物可见表面的几何形状,利用它可以很方便的解决3D目标描述中的许多问题。
深度图像经过坐标转换可以计算为点云数据,有规则及必要信息的点云数据也可以反算为深度图像数据。
从数学模型上看,深度图像可以看做是标量函数在集合K上的离散采样,得到,其中为二维网格(矩阵)的索引,
深度图像的获取方法:
- 激光雷达深度成像法
- 计算机立体视觉成像
- 坐标测量机法
- 莫尔条纹法
- 结构光法
针对深度图像的研究重点:
- 深度图像的分割技术
- 深度图像的边缘检测技术
- 基于不同视点的多幅深度图像的配准技术
- 基于深度数据的三维重建技术
- 基于深度图像的三维目标识别技术
- 深度数据的多分辨率建模和几何压缩技术
PCL中深度图像与点云最主要的区别:近邻的检索方式不同,并且可以互相转换
RangeImage模块
深度图像(或距离图像)的像素值代表从传感器到物体的距离或者深度。
深度图像是物体的三维表达形式,一般通过立体相机或ToF相机获取。如果具备相机的内标定参数,就可以将深度图像转化为点云
深度图像中的边界:从前景跨越到背景的位置
我们对3种类型的点集感兴趣:
点集类型 | 含义 |
---|---|
物体边界(object borders) | 物体最外层和阴影边界的可见点集 (object borders, which are the outermost visible points still belonging to an object) |
阴影边界(shadow borders) | 毗连于遮挡的背景上的点集 (shadow borders, which are points in the background that adjoin occlusions) |
Veil点集(veil points) | 在被遮挡物边界和阴影边界之间的内插点 (veil points, interpolated points between the obstacle border and the shadow border, which are a typical phenomenon in 3D range data obtained by lidars) |
关键点
关键点
关键点也称为兴趣点,是2D图像或3D点云或曲面模型上,可以通过定义检测标准来获取的具有稳定性、区别性的点集。
从技术上来说,关键点的数量相比于原始点云或图像的数据量减小很多,与局部特征描述子结合一起,组成关键点描述子常用来形成原始数据的紧凑表示,而且不失代表性与描述性,从而加快后续识别、追踪等对数据的处理速度。
NARF(Normal Aligned Radial Reature)关键点
keypoints模块
7个类
类 | 功能 |
---|---|
class pcl::HarrisKeypoint2D<PointInT, PointOutT, IntensityT> | 实现基于点云的强度字段的harris关键点检测子 |
class pcl::HarrisKeypoint3D<PointInT, PointOutT, IntensityT> | 与HarrisKeypoint2D类似,利用点云的3D空间的信息表面法线向量来进行关键点检测 |
class pcl::HarrisKeypoint6D<PointInT, PointOutT, IntensityT> | 与HarrisKeypoint2D类似,利用点云的欧式空间域XYZ或者强度域来确定候选关键点,或者前两者的交集,即同时满足XYZ域和强度域的关键点为候选关键点 |
pcl::NarfKeypoint | 实现提取NARF关键点 输入为一幅深度图像,输入出为NARF关键点 |
pcl::SIFTKeypoint< PointInT, PointOutT > | 将二维图像中的SIFT算子调整后移植到3D空间的SIFT算子的实现 输入为带有XYZ坐标值和强度的点云,输出为点云中的SIFT关键点 |
采样一致性
采样一致性参数估计算法
采样一致性参数估计算法常用于排除错误样本,应用:
- 点云分割(根据设定不同的几何模型,估计对应的几何模型的参数,在一定允许误差范围内分割出在模型上的点云)
- 点云配准(点云的配准对的剔除)
PCL中以随机采样一致性算法(RANSAC)为核心,同时实现了5种随机参数估计算法,均符合一致性准则:
变量名 | 算法英文名 | 备注 |
---|---|---|
SAC_RANSAC | RANdom SAmple Consensus | 随机采样一致性估计 对所有样本同等对待从整个样本集中取样 |
SAC_LMEDS | Least Median of Squares | 最小中值方差一致性估计 LMedS算法稳健性很好,可以处理有50%以上局外点的随机采样一致性模型估计,并且不需要设置阈值 |
SAC_MSAC | M-Estimator SAmple Consensus | M-采样一致性估计 基本思想是减小每个异常数据点对其相应的残差的影响 实验结果表明当数据中的异常数据是不精确的定位时,用M-estimators方法得到的结果非常好,但当数据中有错误匹配时,结果不够理想,因为该算法依赖于最初的由最小二乘法得到的初值(缺点) |
SAC_RRANSAC | Randomized RANSAC | 在RANSAC中加入了Td-d测试,比RANSAC快 适用于处理数据点中局内点所占比例较大的情况,可快速进行局外点剔除 |
SAC_RMSAC | Randomized MSAC | 在MSAC中加入了Td-d测试,比RANSAC快 适用于处理数据点中局内点所占比例较大的情况,可快速进行局外点剔除 |
SAC_MLESAC | Maximum LikeLihood Estimation SAmple Consensus | 最大似然一致性估计 适用于处理数据点中局内点的比例较大的情况,可快速剔除局外点 |
SAC_PROSAC | PROgressive SAmple Consensus | 从通过相似度排序的样本中取排名前N个样本,比RANSAC快很多,常用于伪配准对的剔除问题 |
PCL中支持的几何模型
变量名 | 几何模型 | 备注 |
---|---|---|
SACMODEL_LINE | 平面模型 | 4个参数:[normal_x normal_y normal_z d] |
SACMODEL_PLANE | 直线模型 | 6个参数:[point_on_line.x point_on_line.y point_on_line.z line_direction.x line_direction.y line_direction.z] |
SACMODEL_CIRCLE2D | 二维圆的圆周模型 | 3个参数:[center.x center.y radius] |
SACMODEL_CIRCLE3D | 三维圆的圆周模型 | 7个参数:[center.x center.y center.z radius normal.x normal.y normal.z] |
SACMODEL_SPHERE | 三维球体模型 | 4个参数:[center.x center.y center.z radius] |
SACMODEL_CYLINDER | 圆柱体模型 | 7个参数:[point_on_axis.x point_on_axis.y point_on_axis.z axis_direction.x axis_direction.y axis_direction.z radius] |
SACMODEL_CONE | 圆锥模型 | 7个参数:[apex.x apex.y apex.z axis_direction.x axis_direction.y axis_direction.z opening_angle] |
SACMODEL_TORUS | 圆环面模型 | 尚未实现 |
SACMODEL_PARALLEL_LINE | 有条件限制的直线模型 | 在规定的最大角度偏差限制下,直线模型与给定轴线平行,参数参见SACMODEL_LINE |
SACMODEL_PARALLEL_LINES | 有条件限制的直线s模型 | 尚未实现 |
SACMODEL_PERPENDICULAR_PLANE | 有条件限制的平面模型 | 在规定的最大角度偏差限制下,平面模型与给定轴线垂直,参数参见SACMODEL_PLANE |
SACMODEL_NORMAL_PLANE | 有条件限制的平面模型 | 在规定的最大角度偏差限制下,每一个局内点的法线必须与估计的平面模型的法线平行,参数参见SACMODEL_PLANE |
SACMODEL_PARALLEL_PLANE | 有条件限制的平面模型 | 在规定的最大角度偏差限制下,平面模型与给定的轴线平行,参数参见SACMODEL_PLANE |
SACMODEL_NORMAL_PARALLEL_PLANE | 有条件限制的平面模型 | 在法线约束下,三维平面模型必须与用户设定的轴线平行,参数参见SACMODEL_PLANE |
Sample_consensus模块
23个类
用不同的估计算法和不同的几何模型自由结合估算点云中隐含的具体几何模型的系数,实现对点云中所处的几何模型的分割
- 平面模型经常被应用到常见的室内平面分割提取中,比如墙、地板、桌面
- 其他模型常应用到根据几何结构检测识别和分割物体中,如用一个圆柱体模型分割出一个杯子
点云特征描述与提取
3D点云特征描述与提取:点云信息处理中最基础、最关键的一部分。点云的识别、分割、重采样、配准、曲面重建等大部分算法,都严重依赖特征描述与提取的结果。
从尺度上来分:
- 局部特征描述:局部的法线等几何形状特征的描述
- 全局特征描述:全局的拓扑特征描述
3D形状内容描述子(3D shape contexts)
采用一个向量描述曲面上指定点及其邻域的形状特征,通过匹配向量的值来建立不同曲面间点的对应关系,此向量即为指定点的描述子
3D形状内容描述子构造简单,辨别力强,且对噪声不敏感
构造方法:在以指定点p为中心的球形支撑域内,沿径向、方向角、俯仰角3个坐标方向划分成网格,统计落入网格内的点数,构造向量V。V的每个元素与支撑域内的一个网格对应,元素的值为对应网格中的点数,向量V即为点p的描述子。
旋转图像(spin image)
用于:3D场景中的曲面匹配和模型识别
在模型表面上,存在顶点p和其法向量n定义的二维基、切平面P
假设模型上任意顶点x
现定义α为x在平面P上投影点与p点的距离,规定其值取大于0的实数
β为x与其在平面P上投影点之间的距离,按照向上或向下规定其有正负之分
点p的旋转图像为:将除p点外其他模型上的顶点在P上的投影。其中i表示顶点的一维索引,将统计得到二维直方图即为点p的旋转图像,图像的坐标由α和β而定,强度为落在同一统计区间的点的统计个数
下图为模型表面三个点的旋转图像
三维特征描述子
不适定问题(ill-posed problem):在笛卡尔坐标系下两个点p1、p2,在时间t1、t2捕获,有着相同的坐标。对这两个点做比较是不适定问题。虽然相当于一些距离测度(欧几里得度量)它们是相等的。但它们取样于完全不同的表面,因此当把它们和邻近的其他环境中的点放在一起时,它们表达着完全不同的信息。
用局部描述子(local descriptor)取代单一实体的三维点概念和笛卡尔坐标系
又称为点特征表示(point feature representations):通过包括周围的邻域,特征描述子能够表征采样表面的几何性质,有助于解决不适定的对比问题
理想情况下,相同或相似表面上的点的特征值将非常相似(相对特定度量准则),而不同表面上的点的特征描述子将有明显差异。
下面几个条件,通过能否获得相同的局部表面特征值,可以判定点特征表示方式的优劣:
- 刚体变换(rigid transformations):三维旋转和三维平移变化不会影响特征向量F估计,即特征向量具有平移旋转不变性
- 改变采样密度(varing sampling density):原则上,一个局部表面小块的采样密度无论是大还是小,都应该有相同的特征向量值,即特征向量具有抗密度干扰性
- 噪声(noise):数据中有轻微噪声的情况下,点特征表示在它的特征向量中必须保持相同或者极其相似的值,即特征向量对点云噪声具有稳健性
PCL中特征向量利用快速kd-tree查询,使用近似法来计算查询点的最近邻元素,有两种常用的查询类型:
- k-搜索:决定一个查询点的k邻域元素
- 半径-搜索:在半径r的范围内,确定一个查询点的所有邻域元素
输入点云调用习惯
- setInputCloud(PointCloudConstPtr &) 指定完整的点云数据集
- setIndices(IndicesConstPtr &) 指定输入点云中的索引
- setSearchSurface(PointCloudConstPtr &) 指定搜索时使用的点邻域集合
假设有两个点云,,
总是需要setInputCloud(),故有4种情况:
indices | surface | 说明 |
---|---|---|
false | false | 只需输入单一的点云数据集,为点云中的所有点估计特征向量 图示:估计的最近邻元素、的最近邻元素,以此类推,直到估计完P中的所有点 |
true | false | 只计算已给索引的点的特征 图示:假设的索引不在已给的索引向量中,因此在点处,没有估计邻元素或者特征向量 |
false | true | 为点云中的所有点估计特征向量,但在setSearchSurface()中给出的采样面点云将用来为输入点获取最近邻元素,而不是输入点云本身 图示:如果作为输入,是不同于P的另一个给出的点云,P是Q的搜索表面,那么将从P中计算两个点和的近邻 |
true | true | 用setSearchSurface()中给出的搜索点云,只对中的子集进行特征向量估计 图示:假设的索引没有在Q的已给索引向量中,因此在q2点处,没有估计其邻元素或者特征 |
案例:当有一个非常密集的输入点云数据集时,不想对它的所有点进行特征估计,而是希望在找到的一些关键点处(使用pcl_keypoints中的方法进行估计),或者在点云的下采样版本中(使用pcl::VoxelGrid
通过setInputCloud()把下采样后的点云/关键点传递给特征估计算法
通过setSearchSurface()把原始数据设置为搜索集合
从而提高程序运行效率
估计点云的表面法线
- 使用曲面重建技术,从获取的点云数据集中得到采样点对应的曲面,然后从曲面模型中计算表面法线
- 直接从点云数据集中近似推断表面法线(一般采用)
最简单的法线估计方法:确定表面一点法线的问题近似于估计表面的一个相切面法线的问题,即最小二乘法平面拟合估计问题
通常没有数学方法能解决法线的正负向问题,如果实际知道视点,那么这个问题的解决是非常简单的,对所有法线定向只需要使它们一致朝向视点方向,满足下面的方程式:
注意:如果数据集是从多个捕获视点中配准后集成的,那么上述法线的一致性定向方法就不适用了
选择合适的尺度
可粗略假设,以应用程序所需的细节需求为参考,选择确定点的邻域所用的尺度。
简言之,如果杯子手柄和圆柱体部分之间边缘的曲率是重要的,那么需要足够小的尺度来捕获这些细节信息,而在其他不需要细节信息的应用中可选择大的尺度。
使用OpenMP加速法线估计
头文件 | 函数名 |
---|---|
使用积分图进行法线估计
使用积分图(integral images)计算一个有序点云的法线
PFH、FPFH、VFH
点特征直方图(Point Feature Histograms,PFH)不仅与坐标轴三维数据有关,还与表面法线有关。
快速点特征直方图(Fast Point Feature Histograms,FPFH)是PFH的简化形式
计算复杂度:
算法 | 复杂度 |
---|---|
PFH | |
FPFH |
视点特征直方图(Viewpoint Feature Histograms,VFH)用于点云聚类识别和六自由度位姿估计
从深度图像中提取NARF特征
特征描述子算法基准化分析
feature_evaluation_framework.h下载
Feature Correspondence Test Source Code
pcl_features模块
48个类
描述子 | 说明 | PCL中函数 |
---|---|---|
3D shape context descriptor (3D形状内容描述子) |
三维模型的识别、检索 | pcl::ShapeContext3DEstimation< PointInT, PointNT, PointOutT > |
局部坐标系估计方法 | 估计局部坐标系时对处理点云边缘或有孔洞处有特殊的处理方式 | pcl::BOARDLocalReferenceFrameEstimation< PointInT, PointNT, PointOutT > |
估计一组点集是否处于指定点的投影区域的边缘位置 | pcl::BoundaryEstimation< PointInT, PointNT, PointOutT > | |
BRISK-descriptor | 书中没有 | pcl::BRISK2DEstimation< PointInT, PointOutT, KeypointT, IntensityT > |
CRH(Camera Roll Histogram/旋转直方图描述子) | 进行刚体对象的位姿估计 | pcl::CRHEstimation< PointInT, PointNT, PointOutT > |
CVFH(Clustered Viewpoint Feature Histogram/聚类视点直方图描述子) | 针对解决有残缺的点云识别问题 | pcl::CVFHEstimation< PointInT, PointNT, PointOutT > |
Difference of Normals (DoN) scale filter | 书中没有 | pcl::DifferenceOfNormalsEstimation< PointInT, PointNT, PointOutT > |
ESF(Ensemble of Shape Function) | 实时对三维场景中的点云模型进行分类 | pcl::ESFEstimation< PointInT, PointOutT > |
the Fast LocAl Reference framE algorithm for local reference frame | 书中没有 | pcl::FLARELocalReferenceFrameEstimation< PointInT, PointNT, PointOutT, SignedDistanceT > |
FPFH(Fast Point Feature Histogram) | 局部点特征描述子,针对点云配准中求对应点 | pcl::FPFHEstimation< PointInT, PointNT, PointOutT > |
the Globally Aligned Spatial Distribution (GASD) descriptor | 书中没有 | pcl::GASDEstimation< PointInT, PointOutT > |
GFPFH(Global Fast Point Feature Histogram) | 全局尺度描述子,针对三维场景中模型对象的分类 | |
the Global Radius-based Surface Descriptor (GRSD) | 书中没有 | pcl::GRSDEstimation< PointInT, PointNT, PointOutT > |
强度梯度计算 | 强度梯度的方向是指向强度下降最快的方向,其二阶矩表征下降的速率 | pcl::IntensityGradientEstimation< PointInT, PointNT, PointOutT, IntensitySelectorT > |
在强度域的旋转图像的计算 | pcl::IntensitySpinEstimation< PointInT, PointOutT > | |
对点云中每个点的不变矩的估计 | pcl::MomentInvariantsEstimation< PointInT, PointOutT > | |
NARF(Normal Aligned Radial Feature/归一化对齐径向特征) | 针对三维场景中对象的识别 | pcl::NarfDescriptor |
对点云的法线进行估计 | pcl::NormalEstimation< PointInT, PointOutT > | |
the Oriented, Unique and Repetable Clustered Viewpoint Feature Histogram (CVFH) descriptor | pcl::OURCVFHEstimation< PointInT, PointNT, PointOutT > | |
PFH(Point Feature Histogram/点特征直方图) | 针对点云对齐配准 | pcl::PFHEstimation< PointInT, PointNT, PointOutT > |
对主曲率的估计 | pcl::PrincipalCurvaturesEstimation< PointInT, PointNT, PointOutT > | |
对深度图像边缘的提取 | 该边缘表征此处是前景和背景分界处 | pcl::RangeImageBorderExtractor |
RIFT(Rotation Invariant Feature Transform) | 为描述局部完整外观而提出,用于图像分类与检索,是SIFT的一般化,具有旋转不变性 | pcl::RIFTEstimation< PointInT, GradientT, PointOutT > |
RSD(Radius-based Surface Descriptor) | 计算速度快于FPFH的局部描述子 | pcl::RSDEstimation< PointInT, PointNT, PointOutT > |
SHOT(Signature of Histogram of OrienTations) | 局部描述子,用于曲面模型匹配 | pcl::SHOTEstimation< PointInT, PointNT, PointOutT, PointRFT > |
在计算SHOT算子时所需的局部参考坐标系的估计 | pcl::SHOTLocalReferenceFrameEstimation< PointInT, PointOutT > | |
Spin image(旋转图像)描述子 | 用于曲面匹配及3D对象识别 | pcl::SpinImageEstimation< PointInT, PointNT, PointOutT > |
Unique Shape Context(唯一形状内容) | 针对3D模型的检索,用于分类与识别 | pcl::UniqueShapeContext< PointInT, PointOutT, PointRFT > |
VFH(Viewpoint Feature Histogram) | 全局描述子,用于3D场景中对象的识别 | pcl::VFHEstimation< PointInT, PointNT, PointOutT > |
需注意的算子:PFH、FPFH、VFH、CVFH、RIFT
普通版本及OpenMP版本:
pcl::FPFHEstimation< PointInT, PointNT, PointOutT >
pcl::FPFHEstimationOMP< PointInT, PointNT, PointOutT >
pcl::NormalEstimation< PointInT, PointOutT >
pcl::NormalEstimationOMP< PointInT, PointOutT >
pcl::SHOTEstimation< PointInT, PointNT, PointOutT, PointRFT >
pcl::SHOTEstimationOMP< PointInT, PointNT, PointOutT, PointRFT >
pcl::SHOTLocalReferenceFrameEstimation< PointInT, PointOutT >
pcl::SHOTLocalReferenceFrameEstimationOMP< PointInT, PointOutT >
点云配准
点云配准实质:把在不同的坐标系中测量得到的数据点云进行坐标变换,以得到整体的数据模型。
问题的关键:如何求得坐标变换参数R(旋转矩阵)和T(平移向量),使得两视角下测得的三维数据经坐标变换后的距离最小。
配准算法按照实现过程分为:
- 整体配准
- 局部配准
配准算法按照精度分为:
- 粗配准(初始的变换矩阵的粗略估计)
- 精配准(类似ICP的精确的变换矩阵估计)
配准的关键技术:关键点选取、特征描述与提取
两两配准(pairwise registration)
两两配准:一对点云数据集的配准问题
通常通过应用一个估计得到的表示平移和旋转的4×4刚体变换矩阵来使一个点云数据集(source)精确地与另一个点云数据集(target/model)进行完美配准
具体实现步骤:
- 从两个数据集中按照同样的关键点选取标准,提取关键点
- 对选择的所有关键点分别计算其特征描述子
- 结合特征描述子在两个数据集中的坐标的位置,以两者之间特征和位置的相似度为基础,来估算它们的对应关系,初步估计对应点对
- 假定数据是有噪声的,除去对配准有影响的错误的对应点对
- 利用剩余的正确对应关系来估算刚体变换,完成配准
对应估计(correspondences estimation)
假设已经得到由两次扫描的点云数据获得的两组特征向量,在此基础上,必须找到相似特征再确定数据的重叠部分,然后才进行配准。
根据特征的类型,PCL使用不同方法来搜索特征之间的对应关系。
进行点匹配(使用点的xyz三维坐标作为特征值)时,针对有序点云数据和无序点云数据有不同的处理策略:
- 穷举配准(brute force matching)
- kd-tree最近邻查询(FLANN)
- 在有序点云数据的图像空间中查找
- 在无序点云数据的索引空间中查找
进行特征匹配(不使用点的坐标,而是某些由查询点邻域确定的特征,如法向量、局部或全局形状直方图等)时,有以下几种方法:
- 穷举配准
- kd-tree最近邻查询
除了查询之外,对应估计也分为两种类型:
- 直接(Direct)对应估计(默认):为点云A中的每一个点,搜索点云B中的对应点,确认最终对应点对
- “相互”(Reciprocal)对应估计:首先为点云A中的点到点云B搜索对应点,然后又从点云B到点云A搜索对应点,最后只取交集作为对应点对
对应关系去除(correspondences rejection)
由于噪声的影响,通常并不是所有估计的对应关系都是正确的。
由于错误的对应关系对于最终的刚体变换矩阵的估算会产生负面的影响,所以必须去除它们,可以使用随机采样一致性(RANSAC)估计或者其他方法剔除错误对应关系,最终使用的对应关系数量只使用一定比例的对应关系,这样既能提高变换矩阵的估计精度,也能提高配准速度
遇到有一对多对应关系的特例情况,即目标模型中的一个点对应源中的若干个点与之对应。可以通过只取与其距离最近的对应点或者检查附近的其他匹配的滤波方法过滤掉其他伪对应关系。
变换矩阵估计(transformation estimation)
估算变换矩阵的步骤:
- 在对应关系的基础上评估一些错误的度量标准
- 在摄像机位姿(运动估算)和最小化错误度量标准下估算一个(刚体)变换
- 优化点的结构(SVD、Levenberg-Marquardt)
- 使用刚体变换把源旋转/平移到与目标所在的同一坐标系下,用所有点、点的一个子集或者关键点运行一个内部ICP循环
- 进行迭代,直到符合收敛性判断标准为止
迭代最近点算法(Iterative Closest Point,简称ICP算法)
ICP算法对待拼接的2片点云,首先根据一定的准则确立对应点集P与Q,其中对应点对的个数为n。
然后通过最小二乘法迭代计算最优的坐标变换,即旋转矩阵R和平移矢量t,使得误差函数最小。
ICP算法计算简单直观,且可使拼接具有较好的精度。但是算法的运行速度、向全局最优的收敛性在很大程度上依赖于给定的初始变换估计,以及在迭代过程中对应关系的确立。
各种粗拼接技术可为ICP算法提供较好的初始位置,所以迭代过程中确立正确对应点集,以避免迭代陷入局部极值成为各种改进算法的关键,决定了算法的收敛速度与最终的拼接精度。
ICP处理流程的主要步骤:
- 对原始点云数据进行采样
- 确定初始对应点集
- 去除错误对应点对
- 坐标变换的求解
采样一致性初始配准算法(简称SAC-IA算法)
对于初始的变换矩阵粗略估计,贪婪的初始配准方法工作量很大,它使用了点云数据旋转不变的特性。(故一般先对点云进行下采样处理)
但计算复杂度较高,因为在合并的步骤需要查看所有可能的对应关系。此外,因为是贪婪算法,有可能只能得到局部最优解。
因此采用采样一致性方法,试图保持相同的对应关系的几何关系,而不必尝试了解有限个对应关系的所有组合。
相反,从候选对应关系中进行大量的采样并通过以下步骤对它们中的每一个进行排名:
- 从P中选择s个样本点,同时确定它们的配对距离大于用户设定的最小值
- 对于每个样本点,在Q中找到相似FPFH特征的点存入一个列表中。从这些点中随机选择一些代表采样点的对应关系
- 计算通过采样点定义的刚体变换和其对应关系,计算点云的度量错误来评价转换的质量
我们计划通过查看非常大量的对应关系,快速找到一个好的变换
重复这3个步骤直至取得储存了最佳度量错误,并使用暴力配置部分数据。最后使用一个Levenberg-Marquardt算法进行非线性局部优化。
registration模块
26个类、9个结构体
包含:配准相关的基础数据结构、经典配准算法(如ICP)、配准过程中的对应点估计、错误对应点去除等
能够进行ICP算法的点云需要粗略的预匹配(如在一个机器人的量距内或在地图框架内),并且一个点云与另一个点云需要有重叠部分
使用正态分布变换(Normal Distributions Transform)算法来确定两个大型点云(都超过100000个点)之间的刚体变换
正态分布变换是一个配准算法,应用于三维点的统计模型,使用标准最优化技术来确定两个点云间的最优匹配,因为其在配准过程中不利用对应点的特征计算和匹配,所以时间比其他方法快
使用体素网格过滤器过滤输入点云(减少其数据量到原先的10%左右,为了缩短匹配时间),而目标点云不需要滤波处理,因为NDT算法中在目标点云对应的体素网格数据结构的统计计算不使用单个点,而是使用包含在每个体素单元格中的点的统计数据
欧式适合度评分(Euclidean fitness score):计算输出点云到最近目标点云对应点对的距离平方和
点云分割
点云分割:根据空间、几何、纹理等特征对点云进行划分,使得同一划分内的点云拥有相似的特征
比较 | 聚类分割算法 | 基于RANSAC的分割算法 |
---|---|---|
用处 | 将由多个空间分布独立的区域组成的点云分割成各自独立的点云子集 | 提取出特定的模型的点云数据 |
要点 | 设定参数化的的几何模型 | 设置合适的聚类搜索半径 设置合适的点数目 |
函数 |
聚类分割算法
在聚类方法中的每个点都与一个特征向量相关联,特征向量又包含了若干个几何或者辐射度量值。
然后,在特征空间中通过聚类的方法(如K-means法、最大似然法、模糊聚类法)分割点云数据。
聚类分割的基本原理:
考察m个数据点,在m维空间内定义点与点之间某种性质的亲疏聚类,
设m个数据点组成n类,然后将具有最小距离的两类合二为一,并重新计算类与类之间的距离,
迭代直到任意两类之间的距离大于指定的阈值,或者类的个数小于指定的数目,完成分割。
基于随机采样一致性(RANSAC)的分割算法
基于RANSAC的分割是通过随机取样剔除局外点,构建一个仅由局内点数据组成的基本子集的过程。
基本思想:
在进行参数估计时,不是不加区分地对待所有可能的输入数据,
而是首先针对具体问题设计出一个判断准则模型,利用此判断准则迭代地剔除那些与所估计的参数不一致的输入数据,然后通过正确的输入数据来估计模型参数。
分割过程:
首先从输入的点云数据集中随机选择一些点,并计算用户给定模型的参数,
对数据集中的所有点设置距离阈值,如果点到模型的距离在距离阈值范围内,则将该点归为局内点,否则为局外点,
然后统计所有局内点的个数,判断是否大于设定的阈值,
如果是,则用内点重新估计模型,作为模型输出,存储所有内点作为分割结果,
如果不是,则与当前最大的局内点个数对比,如果大于则取代当前最大局内点个数,并存储当前的模型系数,
然后进行迭代计算,直到分割出用户满意的模型
segmentation模块
9个类、12个函数
点云曲面重建
插值法、逼近法
参数曲面重建、隐式曲面重建、变形曲面重建、细分曲面重建、分片线性曲面重建
综合应用篇
参考
参考内容 | 参考方面 |
---|---|
《点云库PCL学习教程》 | 主体内容 |