三维点云处理第二章(2)--Kd-tree

 Kd-tree就是可以在K维空间中(任一维均可)工作的树。类似于在每一个维度都跑一下二叉树。

如何建这个Kd-tree呢?在每一个维度都跑一下二叉树。二叉树最后一个节点只有一个点,但Kd-tree最后一个节点可以包含多个点。要建一个树,先看看点是否足够多。若有多个点,多个维度,则在每个维度都将其切成一半一半的,左右点数基本平均。

 有两种方法·,但都差不多,一种是左边这种,将超平面划到数据点上:另一种就是确保每个点都在区域内,不在超平面上。

 首先要找到要切的维度,这个波浪线是二维、横向分布,第一步很自然的从中间竖着切。第二部可以采用轮流切的方式,第一步竖着切,第二部就横着切。也可以采用自适应切法·,如图,我们切开是为了每一部分点更加的平均。两者速度相差不大。

 如下图,建Kd-tree。第一步先随意选一个平面切(尽量使切平面两边数据个数相差不多),如图竖着切s1。第二部横着y轴切,如s2。我们将做末端叶子包含数据个数设为1,那么我们就需要分割至每个区域只剩一个点。那么第三步如s3,因为leaf-size = 1,此时这边无法再切,我们回到s2的另一边,切出s4,s4有一边仅有一个g,无需再切,另一边切出s5,s5左右均只有一个点,无需再切。此时我们往上走回到s1,同理切出s6,s7,s8。最后,成功把空间分为这么多。

 如何表达一个Kd-tree的节点呢?先看左下角绿色区域,我们首先是s2,按x轴去切的,那么axis=1(因为垂直于y轴),切的位置就是s2,我们将s2放到value里面去,左边右边各是s2的节点,将这边区域所有的点存起来,存到point_indices里面,存的是标号。然后判断是不是一个leaf,如果是,那就不需要继续切了。

 如何建树?(第一步沿着哪个轴去切,第二部把点分为左右各一半。)第一步判断要不要把这个点切开,如果点数小于lesf_size,那么就不用再切。若点数够多,则选一个维度,将所有点按照哪一个维度排序,然后找中间点(就知道中间点左右各一半),把左边的丢进递归函数,右边丢进另一个递归函数,结束。(找维度按照轮换方式)

 时间、空间复杂度。用随便选一些点找中值或者所有点找平均值都会降低复杂度。

 如何查找KNN呢?(在左边先找左边,右边先找右边)第一步找到根节点,然后一直朝左或右。例子:找红色方块最邻近的点。找到根节点后,找s1左边,左边更有可能找到。然后s2右边,然后s4,找到叶节点g,画一个圆(我们已经找到一个最坏距离),此时我们只需去找最坏距离内的点,回到s4,s4左边有跟我的圆有交集,然后s5,s5右边有叶节点e,比最坏距离更小,因此最坏距离缩小,回到s5,不需要找左边,无交集(丢弃该区域,无需查找),再回,回到s2,不需要走左边,无交集,再回到s1,跟s1右边有交集,需要查找s1右边,到s6,走右边,没找到更小的,最坏距离不变,走s6左边,也没找到更小的,最坏距离不变。(其实就是给定一个点,看要不要查找某一个区域)

 代码描述

  

 时间复杂度

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值