关键点检测往往需要和特征提取联合在一起,关键点检测的一个重要性质就是旋转不变性,也就是说,物体旋转后还能够检测出对应的关键点。不过说实话我觉的这个要求对机器人视觉来说是比较鸡肋的。因为机器人采集到的三维点云并不是一个完整的物体,没哪个相机有透视功能。机器人采集到的点云也只是一层薄薄的蒙皮。所谓的特征点又往往在变化剧烈的曲面区域,那么从不同的视角来看,变化剧烈的曲面区域很难提取到同样的关键点。想象一下一个人的面部,正面的时候鼻尖可以作为关键点,但是侧面的时候呢?会有一部分面部在阴影中,模型和之前可能就完全不一样了。
也就是说现在这些关键点检测算法针对场景中较远的物体,也就是物体旋转带来的影响被距离减弱的情况下,是好用的。一旦距离近了,旋转往往造成捕获的仅有模型的侧面,关键点检测算法就有可能失效。
1.ISS算法
ISS算法的全程是Intrinsic Shape Signatures,第一个词叫做内部,这个词挺有讲究。说内部,那必然要有个范围,具体是什么东西的范围还暂定。如果说要描述一个点周围的局部特征,而且这个物体在全局坐标下还可能移动,那么有一个好方法就是在这个点周围建立一个局部坐标。只要保证这个局部坐标系也随着物体旋转就好。
方法1.基于协方差矩阵
协方差矩阵的思想其实很简单,实际上它是一种耦合,把两个步骤耦合在了一起
1.把pi和周围点pj的坐标相减:本质上这生成了许多从pi->pj的向量,理想情况下pi的法线应该是垂直于这些向量的
2.利用奇异值分解求这些向量的0空间,拟合出一个尽可能垂直的向量,作为法线的估计
协方差矩阵本质是啥?就是奇异值分解中的一个步骤。。。。奇异值分解是需要矩阵乘以自身的转置从而得到对称矩阵的。
当然,用协方差计算的好处是可以给不同距离的点附上不同的权重。
方法2.基于齐次坐标
1.把点的坐标转为齐次坐标
2.对其次坐标进行奇异值分解
3.最小奇异值对应的向量就是拟合平面的方程
4.方程的系数就是法线的方向。
显然,这种方法更加简单粗暴,省去了权重的概念,但是换来了运算速度,不需要反复做减法。其实本来也不需要反复做减法,做一个点之间向量的检索表就好。。。
但是我要声明PCL的实现是利用反复减法的。
不管使用了哪种方法,都会有三个相互垂直的向量,一个是法线方向,另外两个方向与之构成了在某点的局部坐标系。在此局部坐标系内进行建模,就可以达到点云特征旋转不变的目的了。
ISS特征点检测的思想也甚是简单:
1.利用方法1建立模型
2.其利用特征值之间关系来形容该点的特征程度。
显然这种情况下的特征值是有几何意义的,特征值的大小实际上是椭球轴的长度。椭球的的形态则是对邻近点分布状态的抽象总结。试想,如果临近点沿某个方向分布致密则该方向会作为椭球的第一主方向,稀疏的方向则是第二主方向,法线方向当然是极度稀疏(只有一层),那么则作为第三主方向。
如果某个点恰好处于角点,则第一主特征值,第二主特征值,第三主特征值大小相差不会太大。
如果点云沿着某方向致密,而垂直方向系数则有可能是边界。
总而言之,这种局部坐标系建模分析的方法是基于特征值分析的特征点提取。
最后补充,Intrisic指的就是这个椭球的内部。
PCL实现
pcl::PointCloud<pcl::PointXYZRGBA>::Ptr model (new pcl::PointCloud<pcl::PointXYZRGBA> ());; pcl::PointCloud<pcl::PointXYZRGBA>::Ptr model_keypoints (new pcl::PointCloud<pcl::PointXYZRGBA> ()); pcl::search::KdTree<pcl::PointXYZRGBA>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZRGBA> ()); // Fill in the model cloud double model_resolution; // Compute model_resolution pcl::ISSKeypoint3D<pcl::PointXYZRGBA, pcl::PointXYZRGBA> iss_detector; iss_detector.setSearchMethod (tree); iss_detector.setSalientRadius (6 * model_resolution); iss_detector.setNonMaxRadius (4 * model_resolution); iss_detector.setThreshold21 (0.975); iss_detector.setThreshold32 (0.975); iss_detector.setMinNeighbors (5); iss_detector.setNumberOfThreads (4); iss_detector.setInputCloud (model); iss_detector.compute (*model_keypoints);
2.Trajkovic关键点检测算法
角点的一个重要特征就是法线方向和周围的点存在不同,而本算法的思想就是和相邻点的法线方向进行对比,判定法线方向差异的阈值,最终决定某点是否是角点。并且需要注意的是,本方法所针对的点云应该只是有序点云。
本方法的优点是快,缺点是对噪声敏感。
手头没有有序点云,不做测试了。