PCL学习笔记(六)-- k-d tree

一、k-d tree

原文链接:https://blog.csdn.net/qq_33143379/article/details/80962326

1)构建k-d tree

  k-d-tree是一棵每个节点都为k维点的二叉树,其中所有非叶子节点可以视作用一个超平面把空间分区成两个半空间( Half-space )。

  最典型的创建k-d tree的方式如下:

  (1)随着树的深度的增加,轮流选择轴当作分区面。在三维树中,其根节点是X轴的垂直分区面,其子节点是Y轴的垂直分区面,其孙节点则是Z轴的垂直分区面,其曾孙节点则又为X轴的垂直分区面,以此类推)。通常选择具有最大方差的维度k作为开始的垂直分区面,这样以保证在这个方向上的数据更为分散。

  (2)每次进行分区时,均按照上述选择轴对应的坐标对数据样本进行排序;排序的中间点就是此次分区的根节点,剩余的数据样本分别进入左子树、右子树。

  (3)对上面产生的左子树、右子树继续按照上面的方法进行排序分区,最终所有的样本数据将构件一个二叉树,每个节点就是样本数据中的某个数据。

2)最近邻搜索

  最近邻搜索用来找出树中与目标点最接近的点,k-d树最近邻走索的算法原理如下:

  (1)从根节点开始,递归地往下移。如果目标点在分区面的左边则进入左子节点,在右边则进入右子节点,并对走过的节点进行标记。

  (2)在接近叶节点时,如果往左或者往右下移时出现没有子节点的情况,则强制进入另一侧的子节点,保证必须最终到达的是叶节点。一但移动到叶节点,就将该节点当作“当前最近邻点”。

  (3)根据之前记录的走过的节点,从当前的叶节点逆向回溯,并对每个经过的节点递归地执行下列步骤:

      a)如果目前所在的节点比“当前最近邻点”更靠近输入点,则将其变为当前最近邻点,其距离为最近距离;

      b)检查目前所在节点的子树有没有更近的点,如果有则从该节点往下找。更具体地说,检查当前的“分割超平面”与“以目标点为球心,目标点与当前最近邻点之间距离为半径的超球体”是否相交。如果相交,则在该子树对应的区域内存在距离目标点更近的点,按照上面的步骤移动到该子树,直到其叶子节点;如果不相交,则向上回退。

  (4)当回退到根节点时,搜索结束,最后的“当前最近邻点”即为最近邻点。

3)举例说明工作过程

  如下图所示,query point是目标点,现在要找到query point在k-d tree中的最近邻点。

  (1)首先,从根节点1开始搜索,因为目标点位于点1所确定的超平面的左侧,所以进入左子节点3。由于节点3并不是叶子节点,因此还不能停止搜索,根据目标点在点3所确定的超平面的上侧,所以进入节点3的右子节点6。由于节点6是叶子节点,所以将节点6当作“当前最近邻点”(如果节点3的没有右子节点6,则强制进入对侧的节点4,并继续搜索,直到找到叶子节点),并计算节点6与目标点之间的距离,作为“当前最小距离”。

  (2)然后,从节点6开始进行回溯查找。经过节点3,计算节点3与目标点之间的距离,并与“当前最小距离”进行比较,发现节点3到目标点的距离较节点6而言更近,因此将节点3变为“当前最近邻点”,此时需要考虑需不需要进入节点3的另一侧子树。

  (3)由于想要讨论节点3的左子树中是否有更加的最近邻点,而节点3的左子树对应的区域是节点3所确定的分割超平面的下方。因此需要检查“由节点3确定的分割超平面”与“以目标点为球心,目标点与当前最近邻点:节点3之间距离为半径的超球体”是否相交。显然,它们是相交的,所以需要搜索节点3的左子树。

  (4)现在,从节点3开始向左侧子树进行搜索,经过节点4,计算目标点到节点4的距离,显然大于“当前最近距离”。由于此时目标点并不在节点4分割的超平面上,所以需要检查“由节点4确定的分割超平面”与“以目标点为球心,目标点与当前最近邻点:节点3之间距离为半径的超球体”是否相交,显然是相交的,所以需要搜索节点4的子树。由于节点4的右子树为空,不进行考虑。对于节点4的左子树,计算从节点5到目标点的距离,发现比“当前最近距离”要短,所以将节点5更新为“当前最临近点”。

  (5)此时从节点5进行节点回溯,节点4与节点3都已经检查过,继续回溯至节点1。对于节点1,需要检查“由节点1确定的分割超平面”与“以目标点为球心,目标点与当前最近邻点:节点5之间距离为半径的超球体”是否相交,显然是不相交的,此时的节点1已经是根节点,搜索结束,“当前最近邻点”为节点5。

二、区域搜索

  1)区域搜索的主要目的在于找出所有位于给定区域(最好是规则图像:矩形、圆形等,便于检测点是否在其里)中的点。主要通过执行如下三个步骤来实现:

  1、从根节点开始,先判断根节点是否在给定区域中;

  2、如果根节点完全在给定区域的左侧/下侧(根据分区维度来判断),则以根节点的右子树递归;

  3、如果根节点完全在给定区域的右侧/上侧(根据分区维度来判断),则以根节点的左子树递归;

  4、如果根节点骑跨在给定区域内(根据分区维度来判断),则以根节点的左、右子树递归;

  2)以下图为例:

  首先,从根节点开始,检查节点1是否在矩形框中。因为节点1不在矩形框中,且矩形框位于点1的左侧(也就是说框中的点在X轴方向上要小于节点1),于是继续搜索其左子树,而直接忽略其右子树。

  接着,检查根节点1的左子节点3是否在矩形框中。因为节点3不在矩形框中,且矩形框横跨节点3所分割的两个超空间平面,所以要继续搜索它的左右两个子树。

  如此递归搜索下去,最后就会发现节点5落在矩形框中。 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值