基于八叉树的区域增长点云分割算法

22 篇文章 6 订阅
17 篇文章 0 订阅

该篇文章出自2015年ICIP会议,主要介绍图像分割领域一种新的区域生长算法 
[TOC]

参考:https://blog.csdn.net/cjx2lxj/article/details/50529618 

提出的问题

激光雷达探测到城市环境的物体表面构成三维几何点,相应的点云分割技术常用于建筑物重建。由于建筑物的复杂性,数据分割计算量很大,传统的点云分割方法需人工干预,又很耗时。为了提高分割算法的效率和精确度,本文采用了一种高效的区域增长算法,对航空激光扫描到的建筑物点数据进行分割,提取出关注的特征。

相关工作

三种数据分割方法的比较: 
1)基于模型拟合的方法 
常见的有Hough变换法,RANSAN法 
优点:主要用于3D点云分割,不受噪声和异常数据干扰 
缺点:分割质量受像素点特征影响较大,不适于大量数据的分割 
2)基于区域增长的方法 
优点:广泛应用在3D点云分割中,执行简单 
缺点:鲁棒性不是很好,受分割的多种评判标准的影响,计算时间长 
3)基于聚类特征的方法 
优点:鲁棒性较好,不需要查找点或查找区域 
缺点:大数据量的分割计算量很大,无法检测连续的边界点,分割后需细化处理。

提出的方案

对获取到的点云数据集使用基于八叉树的区域生长算法,把点云分割成子数据块,再把得到的不完整的数据块进行细化处理。该算法主要由粗分割和细化两部组成。粗分割阶段(A),点云数据集经体素化表示后(A.1),迅速聚类成多个平滑的子数据块,采用区域增长方法,逐步对相邻的有相似特征的体素进行分组(A.2);细化阶段(B),把未分配点(点还没有分配给任何片段)合并到不完整的数据块中使其变成平滑完整的片段。 
算法结构图如图所示: 
算法结构图

粗分割

3.1. 体素化处理 
体素化即为基于八叉树的分解过程,首先确定封闭的最小立方体,作为根节点或零级节点。根节点递归细分为八个子像素,非空体素继续划分,直到划分到剩余阈值或达到最小像素尺寸的标准时终止。分解过程如图所示。 
八叉树分解
体素在这种树状形式下,进行一致的空间分解——所有节点分裂成八个相同大小的子区域。此外,指针被存储在每一个非叶节点,从而显式地连接到子节点,以方便树横向连接。从父节点到子节点的链接是单向的。每个节点以其中样本点的数目为准再分类。在这里,一个节点如果包含超过三个点,则被定义为非空节点,否则为空节点。值得注意的是,只有非空的节点才能进行细分。 
可以采用多种终止标准,如最小像素尺寸,一个预定义的最大深度的树,或每个体素的样本点的最大数目。这里选择剩余阈值r和最小体素的大小d,作为终止条件。体素的大小选择以点云的最小密度为基准。在密集数据的情况下,可以参照预期的分割等级。 
为了使分割块的表面更加平滑,这里采用自适应八叉树的分解方法,这样可以明显减少体素的数量,从而减少在这个区域生长步骤的工作量。分割过程中,采用剩余值继续分割八叉树使分割的表面平滑,如图3.3所示,体素的大小以不同的颜色标记,其中较大的体素出现在平滑区域,较小的像素出现在边缘、角落、及周围的粗糙区域。 
自适应八叉树分解效果

3.2. 特征显著性估计 
计算体素化处理后的体素的特征向量和剩余值,在后面的基于体素的区域增长中过程中,会应用这两种显著性特征。这里采用主成分分析法计算显著性特征。 
剩余向量求法:剔除数据缺失点后,用剩余的点建立协方差矩阵M,对M进行特征值分解,对应于M的最小特征值的特征向量,即为该点的法向量。 
点数据的拟合平面由中心P和法向量N决定,点Pi到平面正交距离为di;平面上所有点偏差均方根r,r即为本文中的剩余值,它与数据噪声级和曲率成比例。 
 
3.3. 基于八叉树的区域生长算法 
基于八叉树的区域增长分割后相邻的体素具有相似的特征,区域生长过程是把具有相似特征的数据块分组分类。下图描述了八叉树的区域增长算法,返回一组大致光滑的表面块。 
区域增长算法 
然而,得到的分割片段是不完整的,这意味着还有多个点尚未分配。由于在建筑边缘的像素可能包含来自多个曲面数据点,这些点不在基于体素化步骤中。因此,提取的片段都需要进一步的细化步骤。

细化

在细化过程中,为了加快进程,只把与不完整的片段边界相邻的体素合并到片段中,每一个不完整的集群扩展到附近成为完整的片段。 
1. 提取边界像素点,查找集群附近的邻近边界点 
为了提高细化步骤的效率,只有边界体素和集群内部的边界周围的缓冲区的像素被细化处理。体素具有少于八个相邻的有限段(具有相同的段ID的体素)可能位于一段边界。缓冲区是由一定的距离扩展集群边界的确定。 
2.快速细化 
细化算法过程如图所示。 
目标点即为上述的边界点(不完整点),求目标点与其邻近的集群的最佳拟合平面的距离,如果小于给定的阈值,就把目标点划分到对应的集群中,如果大于,则继续查找。 
细化算法

达到的效果

实验测试样本模型
实验采用了两个陆地探测的古老建筑及一个空中探测的现代建筑模型,将古老建筑与现代复杂的样本作对比,同时,将基于八叉树的区域增长算法与原始的基于点的分割算法作对比。分割效果图如图所示。 
1970S建筑分割结果图
300年前校园古老建筑分割结果图
现代建筑分割结果图
实验结果图上方使用的是本文提出的区域增长点云分割算法,下方使用的是原始的基于点的区域增长分割算法,可以看出,本文算法分割的效果很平滑,原始算法分割后略粗糙。且本文的算法准确度更高,运行效率更高。 
实验的结果表明,该算法确定了算法的效率和鲁棒性,比传统的区域分割算法快至少一个数量级,适应性比例在75-95%之间,分割效果较好,得到的分割图像很平滑。

认为的优点

(1)八叉树算法的高效利用,分割过程与传统算法相比较耗时最小。采用八叉树的好处有以下三点: 
1)体素的数量比点数量明显要小,从而大大加快区域增长过程。 
2)基于邻域计算法向量有助于避免对初始数据点的大量的最近邻搜索。 
3)体素网格本身具有一种内在的空间结构,从而允许快速和容易寻找相邻的体素。 
(2)本文的算法有效的融合了八叉树和聚类分割区域生长算法,大大提高了算法的效率,准确度也有所提升。

可能的改进

(1)选择适当体素的大小依然需要人工干预,才能使体素网格能够精确呈现出点云的局部表面特征,因此体素大小选择上有待改进。 
(2)现代建筑测试中,弯道等比较复杂的部分,分割效果不是很平滑,算法有待优化。

  • 2
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
以下是一个简单的基于八叉树的3D点体素化和可视化的Python代码示例: ```python import numpy as np from mpl_toolkits.mplot3d import Axes3D import matplotlib.pyplot as plt class Octree: def __init__(self, center, half_size, depth=0, max_depth=5): self.center = center self.half_size = half_size self.depth = depth self.max_depth = max_depth self.children = [None] * 8 def insert(self, point): if self.depth == self.max_depth: return index = 0 if point[0] > self.center[0]: index |= 4 if point[1] > self.center[1]: index |= 2 if point[2] > self.center[2]: index |= 1 if self.children[index] is None: half_size = self.half_size / 2 child_center = np.zeros(3) if index & 4: child_center[0] = self.center[0] + half_size else: child_center[0] = self.center[0] - half_size if index & 2: child_center[1] = self.center[1] + half_size else: child_center[1] = self.center[1] - half_size if index & 1: child_center[2] = self.center[2] + half_size else: child_center[2] = self.center[2] - half_size self.children[index] = Octree(child_center, half_size, self.depth + 1, self.max_depth) self.children[index].insert(point) def visualize(self, ax): if self.depth == self.max_depth: ax.scatter(self.center[0], self.center[1], self.center[2], color='red') return for child in self.children: if child is not None: child.visualize(ax) def main(): # Generate random 3D points within a cube points = np.random.rand(100, 3) # Create octree center = np.array([0.5, 0.5, 0.5]) half_size = 0.5 octree = Octree(center, half_size, max_depth=4) for point in points: octree.insert(point) # Visualize octree fig = plt.figure() ax = fig.add_subplot(111, projection='3d') octree.visualize(ax) ax.set_xlim([0, 1]) ax.set_ylim([0, 1]) ax.set_zlim([0, 1]) ax.set_xlabel('X') ax.set_ylabel('Y') ax.set_zlabel('Z') plt.show() if __name__ == '__main__': main() ``` 该代码生成了100个随机3D点,并将它们插入到一个深度为4的八叉树中。然后,使用matplotlib库中的3D散点图将八叉树可视化。在可视化中,每个叶子节点用红色点表示。
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值