三维点云处理第二章笔记(1)—Binary Search Tree

最近邻查找是点云算法的最重要根基之一。点云滤波、聚类、特征点提取、匹配、点云配准等等都用到了最近邻查找,深度学习算法也离不开最近邻查找(比如点云骨干网络)。

最邻近问题

对于点云里面的点,我们如何找离它最近的点。最常用的两种方法:Kd-tree和Octree。

首先需要讲一下Binary Search Tree,这是其它方法的基础。二叉树可处理一维数据点的最邻近问题查找。Kd-tree可以处理任何维度数据,但通常用于处理二维;Octree是专门为三维数据设计的,它是空间中有大有小的立方体,比Kd-tree更适合用于三维。三种方法的共同点就是空间分割,找到大概最近的,直接处理近的。

K-NN和Fixed Radius-NN是两种不一样的找邻居的方法。

红色的点是要查的点,蓝色绿色点是数据库里有的点。第一个图其实就是3-NN,我们要找三个与红色点最近的点,就是绿色的123。第二个图Radius-NN方法就是以要查的点即红点为圆心,画一个圆,里面的点都算邻居。

1.如何跳过一些小的不需要查找的区间?举个例子:假设只找一个最邻近点,我本来的点在(0,0),我已经找到了一个点在(1,1),那么(0,0)到(1,1)的这段距离就是我的“worst distance”,我不需要再去找比这个worst distance更远的区间了(因为只找一个点,而最远就是(1,1),这段距离内可能有更近的,而距离外的都更远),所以就可以跳过那段区间。

2.如何更快的结束搜索? 若我知道可能的邻居都在某一个区间里面,那么我查找万完这个区间就可以结束了,不需要再去查找其他的了。

总之,就是如何分割空间,分割后跳过某一空间以及停止搜索。

二叉树

 特性:左边的树一定比右边小、右边的比中间的大,左右子树都是二叉树。(小的放左边,大的放右边)

二叉树代码实现:value不仅仅可以是值,也可以是节点颜色,或者该节点在原来数组的位置、编号等。

 给定一维的数组{x1,x2,x3,...,xn},xi\epsilonR,我们如何构造二叉树。总结就是“小放左,大放右”

 代码如图

 复杂度

 给定一个数据点,查找是否在二叉树里面,不在,返回NULL。可用递归和循环两种方式。递归方法代码:调用本身,放进栈里面,什么时候回到那个地方就从栈里面拿出来。

 循环代码实现:

 

 中序,前序,后序,便历方式不同,得到的数组排序不同。

如何查找离11最近的一个邻居?首先查到8这个节点,那么我的worst distance = 3(11-8),最近的邻居距离11至少3那么远,左边距离会更远,11比8大,故应该先向右边看,到10,此时最坏距离为1,需要搜索(10-12),右边比10大,先找右边,找到14,最坏距离不变,11比14小,所以需要寻找14的左边,找到13,发现没有变化,返回14,返回10,返回8,此时看看是否需要找左边,我在右边已经找到10,最坏距离为1,无论在8的左边如何找,都不会使最坏距离小于1,故不需再找。根据8分割两边,我们不去找左边,省去了5个比较点,跳过了一个区域。

如何查找最近的k个邻居?怎么确定最坏距离呢?最开始两边都有,随着查找,右边不再相交,去掉右边区域。

 建一个容器保存已搜索过的知道的k个结果,这已知k个点按顺序排列,最后面那一个就是我们知道的最坏距离。

代码实现1)建一个装K个数据容器,里面的数据初始化为很大 2)来一个点,先给它腾空间,再把它放进去,add_point函数确保容器里的数按从小到大排列,方便确定最坏距离

 3)确定最坏距离之后,KNN查找和之前最邻近查找是一样的,首先进来一个查找函数,对比根节点自己,如果是要找的K个元素之一,则按顺序排列进容器里面,若不在,则不加进去。对比根节点自己,大于根节点,则向右边走,小于则左边走。到达某一步之后,可能会已经找到最近的k个节点,之后便不再向另一边走。

 如何查找Radius NN?最坏距离已经给定,就是半径,在这个半径里面的,都得查找。不需要排序,建容器,只需要把小于半径内的元素都放大结果里面就好。KNN和Radius NN代码对比:Radius NN最坏距离不能等于0.而KNN可以。

 一个实验

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值