PCL库学习笔记(二)
一、点云搜索与压缩
1、KD-tree
KD-tree是一种面向k(k≥2)维空间点数据组织的二叉树结构。在树的根部,所有子项都将根据第一维进行拆分(即,如果第一维坐标小于根,则它将在左子树中;如果大于根,则显然会在 右边的子树)。 树中向下的每个级别都在下一个维度上划分,一旦所有其他级别都用尽后,将返回到第一个维度。 构造k-d树的最有效方法是使用一种分区方法,将中值点放置在根上,具有较小一维值在左子树,较大的值在右子树。 然后,在左右两个子树上都重复此过程,直到要分区的最后一棵树仅由一个元素组成。
Kd-tree 具体排序理论可参考链接: 点击此处.
K近邻搜索
利用kd-tree实现点云的k近邻搜索(当k为1是就是最近邻点)时,步骤如下:
1、建立kd-tree
2、设置搜索空间
3、输入点云
4、设置搜索中心
5、创建一个整数K以及两个向量
代码
#include <pcl/point_cloud.h>
#include <pcl/kdtree/kdtree_flann.h> //kd-tree依赖的头文件
#include <iostream>
#include <vector>
#include <ctime>
int main (int argc, char**argv)
{
srand (time (NULL));//利用系统时间,产生随机数
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
//生成点云
cloud->width =1000;
cloud->height =1;
cloud->points.resize (cloud->width * cloud->height);
for (size_t i=0; i< cloud->points.size (); ++i)
{
cloud->points[i].x =1024.0f* rand () / (RAND_MAX +1.0f);
cloud->points[i].y =1024.0f* rand () / (RAND_MAX +1.0f);
cloud->points[i].z =1024.0f* rand () / (RAND_MAX +1.0f);
}
//建立kd-tree
pcl::KdTreeFLANN<pcl::PointXYZ>kdtree;
//输入点云
kdtree.setInputCloud (cloud);
//设定搜索的中心点
pcl::PointXYZ searchPoint;
searchPoint.x=1024.0f* rand () / (RAND_MAX +1.0f);
searchPoint.y=1024.0f* rand () / (RAND_MAX +1.0f);
searchPoint.z=1024.0f* rand () / (RAND_MAX +1.0f);
// 搜索k个与中心点的最近邻点
int K =10;
std::vector<int>pointIdxNKNSearch(K);//存储k个最近邻点的索引
std::vector<float>pointNKNSquaredDistance(K);//存储最近邻点的距离平方
//打印
std::cout<<"K nearest neighbor search at ("<<searchPoint.x
<<" "<<searchPoint.y
<<" "<<searchPoint.z
<<") with K="<< K <<std::endl;
if ( kdtree.nearestKSearch (searchPoint, K, pointIdxNKNSearch, pointNKNSquaredDistance) >0 )//执行搜索,搜索到后返回值大于0
{
for (size_t i=0; i<pointIdxNKNSearch.size (); ++i)
std::cout<<" "<< cloud->points[ pointIdxNKNSearch[i] ].x
<<" "<< cloud->points[pointIdxNKNSearch[i] ].y
<<" "<< cloud->points[pointIdxNKNSearch[i] ].z
<<" (squared distance: "<<pointNKNSquaredDistance[i] <<")"<<std::endl;
}
return 0;
}
kd-tree半径搜索
利用kd-tree半径搜索时,步骤与k近邻搜索一致,唯一不同是需要创建半径和两个向量
代码
#include <pcl/point_cloud.h>
#include <pcl/kdtree/kdtree_flann.h>
#include <iostream>
#include <vector>
#include <ctime>
int main (int argc, char**argv)
{
srand (time (NULL));
std::vector<int> pointIdxRadiusSearch;
std::vector<float> pointRadiusSquaredDistance;
float radius =256.0f* rand () / (RAND_MAX +1.0f);//随机的生成某一半径
std::cout<<"Neighbors within radius search at ("<<searchPoint.x
<<" "<<searchPoint.y
<<" "<<searchPoint.z
<<") with radius="<< radius <<std::endl;
if ( kdtree.radiusSearch (searchPoint, radius, pointIdxRadiusSearch, pointRadiusSquaredDistance<