一. PCL中的特征点提取原则
1. 3D 特征,是基于局部描述子提取的。
3D feature,就是为了区分不同的表面几何特征而提取的特征值和测度值。
局部描述子,用于表现局部点所代表的表面几何特征。好的点特征描述子通常具备下面的特征:
1)转换不变性,也就是旋转、平移不会影响到特征向量的描述;
2) 采样密度变化不变性,即不同采样频率下的特征矢量基本一致;
3)噪声不变性,即,数据中不同噪声含量条件下不会影响到特征向量的相似性。
2. PCL的各种特征提取方法,都十分相似。只是在点选择和其邻域设置时可以进行不同设置
其中使用kd-tree的快速搜索方式。它也分为两种类型的搜索:
1)k个邻域点值的确定;
2)在半径为r的球半径内进行邻域搜索与计算。
3. PCL 如何选择哪部分点云数据被有来进行特征点的提取
1) 整个点云数据集为对象的过程,使用 setInputCloud。这时,每个点都被估计一个特征。
2) 可以取部分点云数据,通过setInputCloud 和 setIndices。这时,只有被分配了index的点才会被估计一个特征值。
3) 对于邻域的选择,可以用setSearchSurface设定。
4)于是,上述的三个函数:setInputCloud, setIndices, setSearchSurface组合后,就可以出现以下四种情况:
![_images/features_input_explained.png](https://i-blog.csdnimg.cn/blog_migrate/301638d31789c3bcfadefb127edaf997.png)
a) setIndices() =false, setSearchSurface()=false
此时,对点云中所有的点都进行特征统计。即,分别对每一点进行最邻近域的搜索与计算。
b) setIndices() =true, setSearchSurface()=false
只对有特定index的进行测算,其它的点不考虑,例如:只考虑p1点;而a图中的p2点因为没有index所以忽略;
c) setIndices() =false, setSearchSurface()=true
此时,所有的input点云中的点都要被作为被询问点;但是每个点的最近邻域要受限于Surface的定义,而不是全部的输入点云都要被作为最近邻域进行考虑。
d) setIndices() =true, setSearchSurface()=true
此时,输入点云中被询问的点和要搜索的邻域,分别受限于这两个函数的定义。
举例:
- 如果有一个点密度很高的点云数据,我们并不想对其中所有的点都进行特征估计,而是只希望对其中的key points 进行估计;或者是只考虑下采样后的点云的点的情况。
- 此时,只需要将key points 或者下采样的点云放入setInputCloud()函数中,将setSearchSurface()中放入原始数据就可以了。
二. PFH (Point Feature Histograms) 描述子
1. PFH描述子是基于XYZ的点云数据和表面法向量进行计算获得的。
PFH是通过局部特征的计算,再利用直方图统计出选定点云的全局特征的方法。
PFH是在一个目标点的k邻域内对它的几何特征进行编码。编码时,基于相关数值的多维直方图,提取围绕该点的平均曲率值。如下图所示,Pq是目标点,其周围的Pki即是选取的k邻域点。
![_images/pfh_diagram.png](https://i-blog.csdnimg.cn/blog_migrate/866127debec924fd6b4660592e4f1505.png)
n表示法线方向;Ps 和Pt是目标点与它的一个邻域点;
目标点与其邻域内选定的各点之间的法向量的差异,可以用三个角度特征进行描述:
其中,d是目标点Pq与其邻域某个Pki点之间的距离;α, θ, ø分别是两个法向量在三个方向的角度差。
附: pan angle - 水平方向左右摆动的角度θ(投影夹角-x方向);
tilt angle - 仰角,垂直方向上下移动的角度ø(Y);
yaw angle - 偏航角,法线方向的偏移角α (Z)。
2. 最终PFH的直方图描述,是基于上述四个数值统计而获得的。
这个四数值中的三个角度,很容易被规范化到三角函数的角度范围内(或者0~360度,-180~180度等等)。PCL中选择了三个角度作为特征值,而不考虑d(距离)值。
对于α, θ, ø每一个特征值,都将它们归纳到三角函数角度范围内连贯分割的bin(区间)内。每一个全角度范围被分解为5个区间,那么这三个特征值,就存在5 x 5 x5 =125种组合特征。
将每个目标点的邻域内的特征值计算出来,然后根据α, θ, ø的数值,分归到不同的bin中,对整个点云集进行统计的结果,即可表现为PFH的方式,如下图:
![](https://i-blog.csdnimg.cn/blog_migrate/92321500e67d4d9af96ccb35be14b9e7.png)
此图的横坐标表示bin,纵坐标是每个bin中所包含的点云个数。整个轴上的像素点分布,就是当前点云的特征描述。而这个Bin中的点云个数的表现,是通过假设的高斯分布,用均值和方差来表示的。
3. PFH直方图统计数据的来源
PFH统计的第一步,针对选中目标点的特征计算,是基于该目标点与其k邻域点之间组成了一个闭合的平面而进行PFH的计算 。 如图1,可以看到邻域点之间也被连接在一起。这说明,任两个Pk之间也需要进行特征值的计算。这样的计算量是很大的(如果本点云包含n个点,而每个点的选中邻域为k,则计算量就在 )。
PCL中的PFH,是基于125种某个目标点的α, θ, ø的角度值,对能包含到每个种类中的点个数的统计来确定的。 例如:当前有397个点,每个点针对其任一邻域的点,可以计算出α, θ, ø三个值,这三个值共同确实该点落在125个bin中的哪一个中。依次计算本目标点与所有需要处理的邻域点的α, θ, ø值,并落值于相应的bin中。
在点云中每一点都计算结束后,将397个点的每一个对应的bin值中的数据相加,即得到该点云的所有特征值的统计分布直方图。
三. FPFH (Fast Point Feature Histogram)描述子
FPFH采用了两种能够提高计算速度的方法:
1) 所有计算的特征值都存在cache(缓存)中,这样就可以在计算中对于重复的数值直接查找,而不需要再次计算;
2)降低直方图的计算量为( )
![_images/fpfh_diagram.png](https://i-blog.csdnimg.cn/blog_migrate/22eb7fe261b0e6b3253cc91707e51a1d.png)
如图2所示,每一个目标点(红)与其邻域点之间,只需要计算目标点与其邻域点的α, θ, ø,而不涉及其它各点之间,即仅考虑当前点与其邻域的关系。
针对当前目标点的特征直方图,称为SPFH(Simplified Point Feature Histogram)。 至于周围点对于当前点的影响,则添加一个带权重的附加量,
其中,k表示是邻域点个数, 是当前目标点与对应的k个邻域点之一的欧氏距离。这样,SPF的计算量大大降低。
四. VFH (Viewpoint Feature Histogram)描述子
VFH是为单个物体点云做姿态估计或是识别而设计的。所谓聚集态点云(Clustered Points 或者cluster of points)可以认为是只包含一个物体对象的点云。这个cluster 通常需要通过分割或检测方法而获得的。
VFH是一种帮助识别的特征提取,提取的结果是一些描述子,以及这个物体在空间中的6个姿态方向特征。所以,VFH也是基于局部最近邻域的估计问题。VFH描述子一般会通过下面的过程进行匹配实验:
1. 训练阶段
1)选取一个场景,其中包含容易分离出来的一个物体对象;以该物体对象为目标;
2)以相机为参考点,不断旋转或仰俯这个物体对象(pan angle 和tilt angle发生变化,水平摆角和仰角),然后拍摄每一个姿态下的场景点云;
3)为每一个姿态下的物体点云计算VFH描述子;
![](https://i-blog.csdnimg.cn/blog_migrate/b714ca8e90902d1d837ece3271dac144.png)
4)将各点云存储起来,并为它们建立kd-tree结构。
如果有好多个物体需要辨识,上述1)~4)的过程需要重复进行。
![_images/pan_tilt.jpg](https://i-blog.csdnimg.cn/blog_migrate/8c0becba8d1b18f5aa6b77c71a360762.jpeg)
2. 测试阶段
1)重新拍摄并抽取某个物体对象的点云;
2)对这个物体的点云,计算基于当前相机位置的VFH描述子;
3)在第一阶段训练过的kd-tree集中,用它进行匹配测试,找到最佳匹配的那一个。
五. 标识特征点的描述子 -NARF(Normal Aligned Radial Feature)
NARF - 法线对齐的径向特征描述子
1. 什么是深度图像(Range Image)?
Range Image , 指的是以从相机到场景中各点的距离为像素值的图像,通常的单位是mm。 它直接反映了景物可见表面的几何形状。通常的描述方式为
f(x,y)= Z
其中x,y是帧平面的坐标,Z表示的是深度信息。
![](https://i-blog.csdnimg.cn/blog_migrate/24d203f3128a2aa93b62b1bc67cf9ff2.jpeg)
2. Range Image的获得,需要有两个参数:点云和给定的相机位置
深度图像有两种:1)从点云创建深度图像;2)将创建的深度图像,以平面图像的形式展现出来。
1)从点云创建深度图像
pcl::RangeImage::Ptr range_image_ptr(new pcl::RangeImage);
pcl::RangeImage& range_image = *range_image_ptr;
range_image.createFromPointCloud(*cloud, angularResolution, maxAngleWidth, maxAngleHeight, sensorPose, coordinate_frame, noiseLevel, minRange, borderSize);
点云下的深度图像需要定义角度分辨率,即 angularResolution;相机左右旋转,以及上下俯仰的角度范围,即maxAngleWidth,maxAngleHeight;
sensor_pose设置深度相机的位姿是一个仿射变换矩阵,默认为4*4的单位矩阵变换,通常设置roll=yaw= pitch =0 度(roll绕Z轴旋转的角度,yaw是绕Y轴旋转的角,pitch是绕X轴旋转的角);
coordinate_frame定义按照坐标系统的习惯, 默认为CAMERA_FRAME;
noise_level获取深度图像深度时,近邻点对查询点距离值的影响程度,
miniRange表示的是相机能分辨率的点云之间的最小深度距离。如果minRange >0
,则点云之间深度小于这个距离的所有信息都被忽略看不见;这个定义类似于深度分辨率。
borderSize表示的是为这幅图的外围添加的空白区域的宽度。
- 创建的深度图像除了包含(x,y,z)坐标之外,还会有一个Range参数。而所有点云中的点会以三种形式存在:
- 有效点,并且range>0;
- 看不到的点,x=y=z=NAN, range = -INFINITY;
- 特别深的点, x=y=z=NAN, range = INFINITY;
2) 将创建的深度图像,以平面图像的形式展现出来。
float* ranges = range_image.getRangesArray();
unsigned char* rgb_image = pcl::visualization::FloatImageUtils::getVisualImage(ranges, range_image.width, range_image.height);
pcl::io::saveRgbPNGFile("RangeImage.png", rgb_image, range_image.width, range_image.height);
存储的平面图像,使用不同的颜色表示Range的大小。
3. 从Range Image中抽取轮廓
有三种点与轮廓相关:1)物体对象轮廓 Object borders;2)阴影区域轮廓 shadow borders;3)物体的阴影边缘点 veil points。
下图是实验处理后点云深度图上的轮廓点
其中,红色点veilpoint点,绿色点是 Object borders,青色是Shadow boders点。
4. NARF特征提取
NARF特征是在Range Image的轮廓点都提取出来后才可以获得的。所以,包含两个步骤:
1)从Range Image 的轮廓点中提取NARF特征点;
2)对特征点进行描述子的计算
1) 提取NARF特征点
- 特征点必须考虑轮廓点和表面结构;
- 特征点必须是无论从哪个视角看,都可以选择到的点;
- 这个点所在的位置位于稳定平面上,可以计算出法向量或者是描述子;
因为,点的稳定性需要从不同角度做检测时,该点位于的表面与周围邻域之间有比较明显的变化。这也就意味着位于这个区域的此平面有一个很明显的主方向。
所以,
- 在边缘点上查找的点的主方向与周围邻域方向的变化量是需要考虑的;
- 再执行特征点平滑,以及最大值抑制过程,从而发现最具NARF特征的点。
2)NARF描述子
特征描述子描述的是特征点周围区域的特征。NARF描述子满足:
- 能够区分占有和非占有空间,也就是可以描述点所在平面,也可以描述平面之外的形状
- 噪声无关;
- 能够用它抽取局部的坐标结构。
因此,要求:
1)计算该点沿法向量方向的Range值;
2)围绕这个点建立一个小平面块,并在其上覆盖一个星形图案,而这个星形的中心就位于该点上,共有n个星束。每一个星束对应最终描述子的一个计算值,这个值描述的是该点沿这个星束方向的变化情况。该值越大,表示变化越快。这n个星束组成了最终的描述子。
3)从这个描述子中抽取某个独特的方向,从而让该描述子偏转,以达到旋转不变性的特点。这个独特的方向与法线一同,定义了局部的6个DoF(6 Degree-of-Freedom) 坐标描述。
如图,这个星形图案有20个星束,用绿色描绘,其中两个与黑色箭头对应的描述子如图下方所示:
红色箭头就是抽取出来的主方向。所以,此描述子有20种描述分量,并且其中一个对应主方向数值。
注:6DoF 表示的是一个刚体在3D空间中运动的自由程度。
六. 基于惯性矩和偏心率的描述子(Moment of inertial and eccentricity based)
惯性矩是一个几何量,通常被用作描述截面抵抗弯曲的性质;
1. 先对点云进行协方差矩阵的计算,并提取其该矩阵的特征值和特征向量。最终的特征向量会做规范化处理,并且总是遵循右手坐标系统的原则(最大的特征向量表示X轴,最小的表示Z轴);
2. 对矩阵做迭代处理。每迭代一次,主轴特征向量绕其它特征向量旋转一次,绕着其它特征向量以不变顺序旋转一次,从而产生旋转不变性点云;
3. 当前旋转的主轴被称为当前轴。基于每一个当前轴,计算点云的惯性矩。同时,当前轴也被当作当前平面的法向量方向,然后输入点云向该平面投影,并计算该投影的偏心率。
4. 该过程还可以计算沿着特征向量的AABB (axis-aligned bounding box)和OBB(oriented bounding box)盒子。
AABB是沿着当前轴排列的矩形框,即盒体的每个面都和一条坐标轴垂直,这样一个基本信息就能减少转换盒体时操作的次数; OBB是根据物体本身的几何形状来决定盒子的大小和方向,盒子无须和坐标轴垂直。这样就可以选择最合适的最紧凑的包容盒子。OBB盒子的生成比较复杂。一般是考虑物体所有的顶点在空间的分布,通过一定的算法找到最好的方向(OBB盒子的几个轴)。
七. RoPs(Rotational Projection Statistics) 描述子
RoPs特征是基于mesh和提取的关键点来进行特征提取和描述的。首先,针对提取的关键点进行局部表面的剖分。 局部平面包含在指定半径范围内的关键点和三角面元。 对于给定的局部表面,需要计算LRF(局部参照坐标系),LRF由一个简单的三维矢量来表示。
有了这个三维矢量,我们就可以为点云提供旋转不变性。而这个旋转不变性的达成,是以当前的关键点为原点,来调整其它点的位置。LRF的三向坐标即为Ox,Oy和Oz轴。在此旋转过程后,即可开始执行特征的抽取。
对于Ox,Oy和Oz每个轴,将按下列步骤执行:
1)局部表面沿着给定的角度和当前轴进行旋转;
2)将旋转后的局部平面的点分别投影到XY,XZ和YZ平面上;
3)当每一个投影分布矩阵被建立后,矩阵只需要显示多少点落在了每一个规定的bin中即可。bin的数量代表矩阵的维数。bin的数量和支持半径的大小是算法中的参数;
4)针对每一个分布矩阵进行中心矩的计算,M11,M12,M21,M22,E. 其中E表示的是香农熵值;
5)被计算的值共同形成子特征。
上述的过程被迭代执行多次,迭代的次数由设定的旋转数决定。不同轴下的子特征共同形成最终的RoPs描述子。
注:这个特征提取过程,有两个需要提前准备的环节:
1)特征点的提取;
2)点云的三角面元化。
这两个过程可以调用任何支持的算法进行处理,分别得到两个.txt文件。txt文件中只可以包含相关的数据即可。下面两图分别是特征点文件和三角面元文件的示例。
3)在选择模型进行RoPs特征提取时,对特征点、三角面元和原始点云的匹配关系有一定的要求,否则可能会出现下标越界的问题。如果出现了这个问题,需要调整三角面元的生成参数。
八. GASD(Globally Aligned Spatial Distribution) 描述子
GASD主要用于物体识别与位姿估计
GASD基于全局点云进行其参考坐标的估计,然后将它与规定的坐标体系相统一,计算描述子。描述子的计算考虑的是3D点的空间分布。这样的描述子还可以用于3D点颜色分布的估计。因为需要进行坐标系对齐,所以也可以估计与当前点云的位姿信息。
GASD是全局描述子。其步骤如下:
1) 输入点云被看作是一个给定物体的某一个视角下的效果;
2)估计点云的参考坐标系,并与规定的坐标系对齐;
3)然后,基于3D点云的空间分布计算点云的形状分布和颜色分布描述子;
4)通过描述子的匹配查询与匹配训练后,进行物体识别。
<结束>