今天对FPFH的算法进行详细研究,然而发现该算法的入口为点云和该点云的法线估计,然而看到别人把法线估计和FPFH的入口点云设置为同一点云,然而这种各个点都计算特征描述子的方法必然会耗费大量时间,而且没必要。
我的想法就是FPFH的入口仅仅是对点云获取到的关键点,而发现估计则是对关键点的法线估计。这样做的好处是可以计算量大大减少,同时节约很多时间。可是问题来了,发现估计如果入口是关键点集的话,则对关键点进行法线估计的时候则是对该关键点周围的关键点进行的法线估计,这样做肯定是不准确的,而且不稳定。然而如果发现估计是原始点云的话,那么就是对所有的原始点云里面的点进行法线估计,这样做毫无意义。
针对这个问题,解决方法应该是入口依然是原始点云,但是同时把关键点的索引送给法线估计,这样对关键点周围的所有的原始点云进行法线估计才是最准确的,可是关键点的索引怎么获取呢?
SIFT关键点搜索的输出是关键点的点集,不像NARF关键点搜索完成之后的输出是点的索引,因此获取关键点索引的这个程序需要自己重新编程:
想法一:建立一个循环,循环控制条件是 i , i 从0开始,到cloud->size(),然后使用cloud->points[i]和关键点集中的每一个关键点做对比,相同的,则记录这个点的 i ,存储到一个整型数组中,从头至尾。
想法二:在SIFT关键点搜索的过程中已经建立了kd-tree,对关键点集中的每个点在原始点云中进行最近邻搜索不就可以得到他们的索引了么?
比较:两种方法中,无疑,第二种方法要好得多,首先最近邻搜索算法要比盲目的循环对比要快速的多,而且第一种方法太蠢,不灵活
然而问题又有了:SIFT关键点搜索的家国输出的点集中并非全部都是原始点云不变的点,有很少数的点的坐标被改变了(因为算法的原因),这样,必然给对比带来不利影响,比如,当这个点不是原始点云中的点,而是被算法改变之后的点时,对齐进行上述第一种方法进行查找索引的话必然是找不到的,然而,使用最近邻算法进行查找的话却可以找到一个距离其最近的点,而这个距离它最近的点恰恰hi最能将该点的特征表现最全面的一个点,因此这个点也同样可以找到一个最近的点进行代替,不会漏掉点,而第一种方法却会漏掉。
可是对上一段思考之后,我想到如果对于几千个关键点来说,漏掉几个点,对于整体来说影响坑定不大,而且还少了几个需要法线估计的点和最后配准的时候要计算的点,不是正好还可以稍微节约点时间吗? 但是再一想,就算这几个点加进去对于整体速度的影响应该也类似九牛一毛的效果了吧,又何必在乎那一点,而且,SIFT改变点值的根本原因是没有点可以很好的表达这一部分的特征,所以才会改变它,如果我使用第二种方法的同时还保留了这几个点的近似点,那么对于这一片面积内的点来说则有了代表,因此最后还是决定保留下来。
因此最后对于点索引获取的程序设计思路是:对于关键点集,逐个取点,然后利用最近邻搜索算法在原始点云中搜索对应点的索引,并创建一个类似NARF算法输出格式的整型数组进行保存,并且在对关键点进行法线估计的时候传递过去。
我的想法就是FPFH的入口仅仅是对点云获取到的关键点,而发现估计则是对关键点的法线估计。这样做的好处是可以计算量大大减少,同时节约很多时间。可是问题来了,发现估计如果入口是关键点集的话,则对关键点进行法线估计的时候则是对该关键点周围的关键点进行的法线估计,这样做肯定是不准确的,而且不稳定。然而如果发现估计是原始点云的话,那么就是对所有的原始点云里面的点进行法线估计,这样做毫无意义。
针对这个问题,解决方法应该是入口依然是原始点云,但是同时把关键点的索引送给法线估计,这样对关键点周围的所有的原始点云进行法线估计才是最准确的,可是关键点的索引怎么获取呢?
SIFT关键点搜索的输出是关键点的点集,不像NARF关键点搜索完成之后的输出是点的索引,因此获取关键点索引的这个程序需要自己重新编程:
想法一:建立一个循环,循环控制条件是 i , i 从0开始,到cloud->size(),然后使用cloud->points[i]和关键点集中的每一个关键点做对比,相同的,则记录这个点的 i ,存储到一个整型数组中,从头至尾。
想法二:在SIFT关键点搜索的过程中已经建立了kd-tree,对关键点集中的每个点在原始点云中进行最近邻搜索不就可以得到他们的索引了么?
比较:两种方法中,无疑,第二种方法要好得多,首先最近邻搜索算法要比盲目的循环对比要快速的多,而且第一种方法太蠢,不灵活
然而问题又有了:SIFT关键点搜索的家国输出的点集中并非全部都是原始点云不变的点,有很少数的点的坐标被改变了(因为算法的原因),这样,必然给对比带来不利影响,比如,当这个点不是原始点云中的点,而是被算法改变之后的点时,对齐进行上述第一种方法进行查找索引的话必然是找不到的,然而,使用最近邻算法进行查找的话却可以找到一个距离其最近的点,而这个距离它最近的点恰恰hi最能将该点的特征表现最全面的一个点,因此这个点也同样可以找到一个最近的点进行代替,不会漏掉点,而第一种方法却会漏掉。
可是对上一段思考之后,我想到如果对于几千个关键点来说,漏掉几个点,对于整体来说影响坑定不大,而且还少了几个需要法线估计的点和最后配准的时候要计算的点,不是正好还可以稍微节约点时间吗? 但是再一想,就算这几个点加进去对于整体速度的影响应该也类似九牛一毛的效果了吧,又何必在乎那一点,而且,SIFT改变点值的根本原因是没有点可以很好的表达这一部分的特征,所以才会改变它,如果我使用第二种方法的同时还保留了这几个点的近似点,那么对于这一片面积内的点来说则有了代表,因此最后还是决定保留下来。
因此最后对于点索引获取的程序设计思路是:对于关键点集,逐个取点,然后利用最近邻搜索算法在原始点云中搜索对应点的索引,并创建一个类似NARF算法输出格式的整型数组进行保存,并且在对关键点进行法线估计的时候传递过去。
致谢:其中的想法并不全是我的思路,其中更多是和一个不认识的师兄讨论的,感谢小白师兄的无偿帮助。
这让我想起了七月等人为何对算法的改良如此热衷,其中吸引力和获得满足感无法为外人道。