KD-Tree的构建及检索

简介: KD-Tree的构建及检索

构建KD-Tree

百度百科定义: kd-tree(k-dimensional树的简称),是一种对k维空间中的实例点进行存储以便对其进行快速检索的树形数据结构。 [1] 主要应用于多维空间关键数据的搜索(如:范围搜索和最近邻搜索)。


其中K代表数据的维度,在激光雷达三维点云中,KD-Tree的维度是3。由于点云数据的数量一般较大,使用KD-Tree构建数据索引能够帮助我们快速的进行检索。


一个 kd-tree的节点的数据结构一般包括下述类型:

其中,常用的数据是: 数据适量,切割轴split,父节点,左支节点,右支节点。这些就能满足 kd-tree的构建与检索了。

  • 伪代码
输入: 大量无序化的点云,维度3
输出:点云对应的kd-tree数据结构
构建过程:
1、初始化分割轴:对每个维度的数据进行方差的计算,取最大方差的维度作为分割轴(另外一种说法是随机选择一个维度);
2、确定节点:对当前数据按分割轴维度进行检索,找到中位数数据,并将其放入到当前节点上;
3、划分双支:
    划分左支:在当前分割轴维度,所有小于中位数的值划分到左支中;
    划分右支:在当前分割轴维度,所有大于等于中位数的值划分到右支中。
4、更新分割轴:继续选择方差最大的轴作为分割轴(或者随机选择、或顺序选择);
5、确定子节点:
    确定左节点:在左支的数据中进行步骤2;
    确定右节点:在右支的数据中进行步骤2;

为了更好的理解上述伪代码,我们以下述例子进行更加详细的说明:

  • 二维样例:
{(1,1),(4,5),(2,9),(5,7),(6,1),(7,2),(9,3)}
  • 构建步骤:
  • 1)初始化分割轴:

这里为了简单,不计算方差,直接随机选择X轴作为分割轴。

2)确定当前节点:

对X轴中的{1,4,2,5,6,7,9}选取中位数为5,则选择**(5,7)** 点作为当前节点。

3)划定左右分支数据:

在分割轴X轴维度上,比较与中位数5的大小,进行划分:

左支:(1,1),(4,5),(2,9)
右支:(6,1),(7,2),(9,3)

4)更新左右分支的分割轴为y轴:

5)在左右分支中确定节点:

左支:y轴坐标的中位数为5,选取(4,5)作为子节点
右支:y轴坐标的中位数为2,选取(7,2)作为子节点

6)分别对子节点划分新的左支右支:

(4,5)节点:左支:(1,1),右支:(2,9)
(7,2)节点:左支:(6,1),右支:(9,3)

最终,就构建完成了整个KD-Tree。

示意图如下:

在对应的二维空间表示:

最近邻搜索

假设,在构建kd-tree之后,我们想在上述的点集合中要找一个与(2,2)点最近的点。


计算与当前节点(5,7)的距离,为5.8,并且暂定为(5,7),根据当前分割轴的维度(2 < 5),选取左支。


计算与左支节点(4,5)的距离,为3.6,小于5.8,暂定为(4,5),根据当前分割轴的维度(2 < 5),选取左支。


计算与左支节点(1,1)的距离,为1.4,小于3.6,暂定为(1,1),根据当前分割轴的维度(2 > 1),选取右支,而右支为空,回溯到上一节点。


计算(2,2)与(4,5)分割轴5之间的距离为3,3>1.4,说明当前节点(1,1)即为(2,2)点的最近邻。


距离范围搜索的原理和最近邻搜索的差不多,把满足距离的全部放进去就可以了。

PCL函数用法

kd-tree在PCL库的日常使用中,一般会在两个方面使用:

  • 最近邻搜索
//头文件
#include <pcl/kdtree/kdtree_flann.h>
//设定kd-tree的智能指针
pcl::KdTreeFLANN<pcl::PointXYZI>::Ptr kdtreeCornerLast(new pcl::KdTreeFLANN<pcl::PointXYZI>());
//输入三维点云,构建kd-tree
kdtreeCornerLast->setInputCloud(laserCloudCornerLast);
//在点云中寻找点searchPoint的k近邻的值,返回下标pointSearchInd和距离pointSearchSqDis
// k的值为搜索最近邻点的个数
kdtreeCornerLast->nearestKSearch (searchPoint, K, pointIdxNKNSearch, pointNKNSquaredDistance);
  • 距离范围搜索
//在点云中寻找和点searchPoint满足radius距离的点和距离,返回下标pointIdxRadiusSearch和距离pointRadiusSquaredDistance
kdtreeCornerLast->radiusSearch (searchPoint, radius, pointIdxRadiusSearch, pointRadiusSquaredDistance);
目录
相关文章
|
设计模式 程序员 C++
【C++ 泛型编程 高级篇】C++模板元编程:使用模板特化 灵活提取嵌套类型与多容器兼容性
【C++ 泛型编程 高级篇】C++模板元编程:使用模板特化 灵活提取嵌套类型与多容器兼容性
1177 2
|
网络协议 算法 Java
万字长文 | 保姆级的后台服务器开发C++学习路线
这一篇的主题是「Linux C/C++ 服务器/后台开发学习路线」
|
3月前
|
监控 Linux
Linux系统监控报告CPU软锁定问题(soft lockup)诊断方法
以上方法结合起来使用将大大提高解决此类问题效率与成功率。实际操作过程需谨慎考虑当前环境与场景特点选择合适方法,并且要注意数据备份与恢复计划防止误操作造成不可挽回损失。
505 13
|
12月前
|
机器学习/深度学习 人工智能 开发工具
Clone-voice:开源的声音克隆工具,支持文本转语音或改变声音风格,支持16种语言
Clone-voice是一款开源的声音克隆工具,支持16种语言,能够将文本转换为语音或将一种声音风格转换为另一种。该工具基于深度学习技术,界面友好,操作简单,适用于多种应用场景,如视频制作、语言学习和广告配音等。
2084 9
Clone-voice:开源的声音克隆工具,支持文本转语音或改变声音风格,支持16种语言
|
JSON 分布式计算 前端开发
前端的全栈之路Meteor篇(七):轻量的NoSql分布式数据协议同步协议DDP深度剖析
本文深入探讨了DDP(Distributed Data Protocol)协议,这是一种在Meteor框架中广泛使用的发布/订阅协议,支持实时数据同步。文章详细介绍了DDP的主要特点、消息类型、协议流程及其在Meteor中的应用,包括实时数据同步、用户界面响应、分布式计算、多客户端协作和离线支持等。通过学习DDP,开发者可以构建响应迅速、适应性强的现代Web应用。
865 2
|
JavaScript Windows
Electron——复制文件操作
Electron——复制文件操作
364 0
|
存储 边缘计算 物联网
未来数据存储技术发展趋势分析
随着数字化时代的到来,数据量不断增长,传统存储技术面临挑战。本文探讨未来数据存储技术的发展趋势,包括分布式存储、云存储、边缘计算等新兴技术的应用前景。
|
消息中间件 算法 调度
FreeRTOS 任务调度和任务的状态
FreeRTOS 任务调度和任务的状态
FreeRTOS 任务调度和任务的状态
|
存储 C++ 索引
C++中的string容器及字符串拼接操作讲解
C++中的string容器及字符串拼接操作讲解
642 3
|
SQL 安全 大数据
大数据生态安全框架的实现原理与最佳实践(下篇) 1
大数据生态安全框架的实现原理与最佳实践(下篇)

热门文章

最新文章