目录
一、拓扑关系
1.概念:
2.点云拓扑概念:
二、建立拓扑关系
三、建立拓扑关系算法
(一) KD-Tree 算法
1. 概念:
2. 划分K维数据:
3. KD-Tree构建
4. KD-Tree的最近邻查找
(二) Octree 算法
1.概念:
2. 划分原理
3.最近邻搜索
(三)栅格法
1.概念
2.划分原理
3.K近邻搜索
(四)优缺点
拓扑关系是指满足拓扑几何学原理的各空间数据间的相互关系。即用结点、弧段和多边形所表示的实体之间的邻接、关联、包含和连通关系。如:点与点的邻接关系、点与面的包含关系、线与面的相离关系、面与面的重合关系等。
通过雷达、激光扫描、立体摄像机等三维测量设备获取的点云数据,具有数据量大、分布不均匀等特点。点与点之间没有任何的拓扑关系,即为无序点云。而点云数据处理,如滤波、点云分割等,都是基于邻域,这就需要对点云进行邻域划分,以实现点云邻近点的快速查询,这就是建立点云拓扑的重要性。
作为三维领域中一个重要的数据来源,点云数据主要是表征目标表面的海量点集合,并不具备传统网格数据的集合拓扑信息。当我们需要对点云数据处理,例如滤波、建立法式向量、点云分割等操作,这需要点云之间存在联系,都是基于领域上操作。这就需要对点云进行领域划分,以实现点云邻近点的快速查询。
常见的构建邻域的方法有:1)搜索距离采样点最近的k个点,称为k 邻域搜索;2)搜索以采样点为中心的 r 半径球域内的所有邻近点,称半径搜索。
建立空间索引在点云数据处理中已被广泛应用,常见空间索引一般是自顶向下逐级划分空间的各种空间索引结构,比较有代表性的包括 BSP树、 KD树、 KDB树、 R树、 R+树、 CELL树、四叉树和八叉树等索引结构,而在这些结构中KD树和八叉树在3D点云数据组织中应用较为广泛,PCL对上述两者进行了实现。
kd树(k-dimensional树的简称),是一种分割k维数据空间的数据结构,主要应用于多维空间关键数据的近邻查找(Nearest Neighbor)和近似最近邻查找(Approximate Nearest Neighbor)。
其实KDTree就是二叉查找树(Binary Search Tree,BST)的变种。二叉查找树的性质如下:
1)若它的左子树不为空,则左子树上所有结点的值均小于它的根结点的值;
2)若它的右子树不为空,则右子树上所有结点的值均大于它的根结点的值;
3)它的左、右子树也分别为二叉排序树;
我们要处理的对象集合是一个K维空间中的数据集,将其划分到具体的每个区域去,并且每个区域只能有一个数据。划分过程:我们每选择一个维度进行如上的划分,就会将K维数据空间划分为两个部分,如果我 们继续分别对这两个子K维空间进行如上的划分,又会得到新的子空间,对新的子空间又继续划分,重复以上过程直到每个子空间都不能再划分为止。关键涉及两个问题:
(1)选择维度:统计样本在每个维度上的数据方差,挑选出对应方差最大值的那个维度。数据方差大说明沿该坐标轴方向上数据点分散的比较开。这个方向上,进行数据分割可以获得最好的平衡。
(2)平衡KD-Tree:在维度d上进行划分时,划分点(pivot)就选择该维度d上所有数据的中值,这样得到的两个子集合数据个数就基本相同了,能平衡KD-Tree生长。(选择大的中值)
(1) 在K维数据集合中选择具有最大方差的维度k,然后在该维度上选择中值m为pivot对该数据集合进行划分,得到两个子集合;同时创建一个树结点node,用于存储;
(2)对两个子集合重复(1)步骤的过程,直至所有子集合都不能再划分为止;
例子: 假设有6个二维数据点{(2,3),(5,4),(9,6),(4,7),(8,1),(7,2)},数据点位于二维空间内(如下图中黑点所示)。kd树算法就是要确定图1中这些分割空间的分割线(多维空间即为分割平面,一般为超平面)。下面就要通过一步步展示kd树是如何确定这些分割线的。
(1)分别计算x,y方向上数据的方差,得知x方向上的方差最大;
(2)根据x轴方向的值2,5,9,4,8,7排序选出中值为7,所以该node中的data = (7,2)。这样,该节点的分割超平面就是通过(7,2)并垂直于x轴的直线x = 7;
(3)确定左子空间和右子空间。分割超平面x = 7将整个空间分为两部分,如下图所示。x < = 7的部分为左子空间,包含3个节点{(2,3),(5,4),(4,7)};另一部分为右子空间,包含2个节点{(9,6),(8,1)}。
(1)将查询数据Q从根结点开始,按照Q与各个结点的比较结果向下访问Kd-Tree,直至达到叶子结点。
其中Q与结点的比较指的是将Q对应于结点中的k维度上的值与中值m进行比较,若Q(k) < m,则访问左子树,否则访问右子树。达到叶子结点时,计算Q与叶子结点上保存的数据之间的距离,记录下最小距离对应的数据点,记为当前最近邻点nearest和最小距离dis。
(2)进行回溯操作,该操作是为了找到离Q更近的“最近邻点”。即判断未被访问过的分支里是否还有离Q更近的点,它们之间的距离小于dis。
如果Q与其父结点下的未被访问过的分支之间的距离小于dis,则认为该分支中存在离P更近的数据,进入该结点,进行(1)步骤一样的查找过程,如果找到更近的数据点,则更新为当前的最近邻点nearest,并更新dis。
如果Q与其父结点下的未被访问过的分支之间的距离大于dis,则说明该分支内不存在与Q更近的点。
回溯的判断过程是从下往上进行的,直到回溯到根结点时已经不存在与P更近的分支为止。
注:判断未被访问过的树分支中是否还有离Q更近的点,就是判断"Q与未被访问的树分支的距离|Q(k) - m|"是否小于"Q到当前的最近邻点nearest的距离dis"。从几何空间上来看,就是判断以Q为中心,以dis为半径超球面是否与未被访问的树分支代表的超矩形相交。
例子: 假设我们的kd树就是上面通过样本集{(2,3),(5,4),(9,6),(4,7),(8,1),(7,2)}创建的。
查找点Q(2,4.5)
如下图所示,同样经过图4的二叉搜索,可得当前的最邻近点(4,7),产生的搜索路径节点有<(7,2),(5,4),(4,7)>。首先以(4,7)作为当前最近邻点nearest,计算其到查询点Q(2,4.5)的距离dis为3.202,然后回溯到其父节点(5,4),并判断在该父节点的其他子节点空间中是否有距离查询点Q更近的数据点。以(2,4.5)为圆心,以为3.202为半径画圆,如图7所示。发现该圆和超平面y = 4交割,即这里:|Q(k) - m|=|4.5 - 4|=0.5 < 3.202,因此进入(5,4)节点右子空间中去搜索。所以,将(2,3)加入到搜索路径中,现在搜索路径节点有<(7,2), (2, 3)>。同时,注意:点Q(2,4.5)与父节点(5,4)的距离也要考虑,由于这两点间的距离3.04 < 3.202,所以将(5,4)赋给nearest,并且dist=3.04。
接下来,回溯至(2,3)叶子节点,点Q(2,4.5)和(2,3)的距离为1.5,比距离(5,4)要近,所以最近邻点nearest更新为(2,3),最近距离dis更新为1.5。回溯至(7,2),如图8所示,以(2,4.5)为圆心1.5为半径作圆,并不和x = 7分割超平面交割,即这里:|Q(k) - m|=|2 - 7|=5 > 1.5。至此,搜索路径回溯完。返回最近邻点(2,3),最近距离1.5。
Kd-Tree在维度较小时(比如20、30),算法的查找效率很高,然而当数据维度增大(例如:K≥100),查找效率会随着维度的增加而迅速下降。假设数据集的维数为D,一般来说要求数据的规模N满足N>>2的D次方,才能达到高效的搜索。
八叉树(Octree)是一种用于描述三维空间的树状数据结构。八叉树的每个节点表示一个正方体的体积元素,每个节点有八个子节点,这八个子节点所表示的体积元素加在一起就等于父节点的体积。一般中心点作为节点的分叉中心。
举例:有一个房间,房间里某个角落藏着一枚金币,我们想很快的把金币找出来,聪明的你会怎么做?我们可以把房间当成一个立方体,先切成八个小立方体,然后排除掉没有放任何东西的小立方体,再把有可能藏金币的小立方体继续切八等份….如此下去,平均在Log8(房间内的所有物品数)的时间内就可找到金币。因此,八叉树就是用在3D空间中的场景管理,可以很快地知道物体在3D场景中的位置,或侦测与其它物体是否有碰撞以及是否在可视范围内。
八叉树是一种用于描述三维空间的树状数据结构。八叉树的每个节点表示一个正方体的体积元素,每个节点有八个子节点,将八个子节点所表示的体积元素加在一起就等于父节点的体积。
(个人认为不是寻找最近邻点的算法,而是其他的)
(1). 设定最大递归深度。
(2). 找出场景的最大尺寸,并以此尺寸建立第一个立方体。
(3). 依序将单位元元素丢入能被包含且没有子节点的立方体。
(4). 若没达到最大递归深度,就进行细分八等份,再将该立方体所装的单位元元素全部分担给八个子立方体。
(5). 若发现子立方体所分配到的单位元元素数量不为零且跟父立方体是一样的,则该子立方体停止细分,因为跟据空间分割理论,细分的空间所得到的分配必定较少,若是一样数目,则再怎么切数目还是一样,会造成无穷切割的情形。
(6). 重复3,直到达到最大递归深度。
仿照四叉树的原理,从二维推广到三维上,根据点云数据结构确定最小的立方体,然后对立方体内的点云数据进行划分,当划分出来的子立方体结构不包含点云数据就停止划分,而其他的子立方体结构这继续划分,直至指定的深度范围(分层树)或者规定的点云数据密度或者子立方体的大小等条件就停止划分,最后建立起点云的拓扑结构。
根据八叉树建立起好的点云拓扑结构,按照上述介绍KD-Tree寻找最近邻点的方式对建立好的点云拓扑结构进行查找最邻近点,这种方式相比较KD-Tree,占用较多发存储空间,使得查询时间很大,但查找方式较为简单。
栅格化法是将点云数据的最小外包围长方体,按预先设定的长度 L 进行均等划分,形成多个立方体单元格,即栅格。
具体过程:首先建立点云数据的最小外包围长方体 即,按照某一设定的L将 划分成大小均等的栅格,记作,,其中分别表示在 x、y、z 方向上的栅格数。
的计算公式如下:
其中:表示向上取整。栅格总数的计算公式为:
假设点云模型中数据的总点数为 N,每个栅格中的数据点个数 α 与 k 成简单线性关系,则:
联立以上公式可得:
完成栅格化,对划分后的每一小栅格进行编号,所有数据点均与栅格一一对应。
拓扑关系建立后,当对某一点 Pi 进行 K 近邻搜索时,只需将搜索范围先锁定到 Pi 所在的栅格内及与之上下、左右、前后相邻的 26 个栅格内,如果 Pi 位于栅格边缘附近时,与Pi 距离最近的点更有可能位于相邻栅格内,此时就要在相邻栅格内进行搜索。当搜索完这 27 个目标栅格后,仍不足 K 个时,此时要将搜索范围扩大到与 26 个栅格相邻的 98个栅格内,依次类推,直至满足 K 个,搜索结束。
1. K-D tree:在处理大规模数据时,在对点云数据进行分割构建 K-D 树的过程要耗费大量的时间,同时数据的存储也会占用大量内存资源,因此 K-D 法不适合处理规模量较大的点云数据。
2.Octree: 不需要过多的考虑点云的密度分布情况,操作起来也较为简单,只需要预先设定好阈值,根据阈值条件进行分割产生八叉树。但在分割的过程中会出现一些的空子空间块,这些空子空间块的产生会影响点云数据的查询效率。
3. 栅格法: 虽然原理相对简单易懂,但操作起来并不太容易,尤其在处理数据量较大且点云密度分布不均匀的点云数据时,栅格边长的选取是最大的难题,边长选取的过大会导致每个小栅格中的点云数过多,增加计算时间,边长选取过小会导致栅格的个数过多,影响最终的拼接精度。
因此,在对点云数据进行处理时,要全面考虑点云数据的特性和每种拓扑关系构建方法的优缺点,选择一种适合的处理方法,有助于提高点云拼接算法的效率。