PCL学习总结KdTree搜索
Posted 非晚非晚
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PCL学习总结KdTree搜索相关的知识,希望对你有一定的参考价值。
1. 理论基础
KdTree(k-dimensional树的简称),是一种对k维空间中的实例点进行存储以便对其进行快速检索的树形数据结构。 主要应用于多维空间关键数据的搜索(如:范围搜索和最近邻搜索)。K-D树是二进制空间分割树的特殊的情况。
k-d树是每个节点都为k维点的二叉树。所有非叶子节点可以视作用一个超平面把空间分割成两个半空间
。节点左边的子树代表在超平面左边的点,节点右边的子树代表在超平面右边的点。(比如右节点大于父节点,左节点小于父节点,很明显使用一次快速排序就能实现该功能。)
选择超平面的方法如下:每个节点都与k维中垂直于超平面的那一维有关。因此,如果选择按照x轴划分,所有x值小于指定值的节点都会出现在左子树,所有x值大于指定值的节点都会出现在右子树。有很多种方法可以选择轴垂直分割面( axis-aligned splitting planes ),所以有很多种创建k-d树的方法。 最典型的方法如下:
- 随着树的深度轮流选择轴当作分割面。(例如:在三维空间中根节点是 x 轴垂直分割面,其子节点皆为 y 轴垂直分割面,其孙节点皆为 z轴垂直分割面,其曾孙节点则皆为 x 轴垂直分割面,依此类推。)
- 点由垂直分割面之轴座标的中位数区分并放入子树
下图演示了以A、B和C为超平面进行划分的二叉树构建,以及kdtree的搜索功能。
2. KdTree搜索代码举例
pcl中的KdTree有两种搜索方式:
- k近邻域搜索:搜索某个点附近的
k个点
。- R半径搜索:搜索某个点半径为
R内的所有点
。
#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)); //随机种子
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
// Generate pointcloud data
cloud->width = 1000;
cloud->height = 1;
cloud->points.resize(cloud->width * cloud->height);
for (std::size_t i = 0; i < cloud->size(); ++i) //填充点云数据
{
(*cloud)[i].x = 1024.0f * rand() / (RAND_MAX + 1.0f);
(*cloud)[i].y = 1024.0f * rand() / (RAND_MAX + 1.0f);
(*cloud)[i].z = 1024.0f * rand() / (RAND_MAX + 1.0f);
}
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 nearest neighbor search
/***********************k近领域搜索*************************/
int K = 10;
std::vector<int> pointIdxNKNSearch(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) //开始搜索
{
for (std::size_t i = 0; i < pointIdxNKNSearch.size(); ++i)
std::cout << " " << (*cloud)[pointIdxNKNSearch[i]].x
<< " " << (*cloud)[pointIdxNKNSearch[i]].y
<< " " << (*cloud)[pointIdxNKNSearch[i]].z
<< " (squared distance: " << pointNKNSquaredDistance[i] << ")" << std::endl;
}
// Neighbors within radius search
/***********************半径R搜索************************/
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) > 0) //开始搜索
{
for (std::size_t i = 0; i < pointIdxRadiusSearch.size(); ++i)
std::cout << " " << (*cloud)[pointIdxRadiusSearch[i]].x
<< " " << (*cloud)[pointIdxRadiusSearch[i]].y
<< " " << (*cloud)[pointIdxRadiusSearch[i]].z
<< " (squared distance: " << pointRadiusSquaredDistance[i] << ")" << std::endl;
}
return 0;
}
以上是关于PCL学习总结KdTree搜索的主要内容,如果未能解决你的问题,请参考以下文章