点云分割
图自:https://openaccess.thecvf.com/content_cvpr_2017/papers/Qi_PointNet_Deep_Learning_CVPR_2017_paper.pdf《PointNet:用于3D分类和分割的点集深度学习》
点云分割
(Point Cloud Segmentation)是计算机视觉和3D图像处理中的一个重要步骤,通过将点云数据划分成有意义的子集,以便于进一步分析和处理。点云分割可以帮助识别和提取场景中的特定对象或区域,例如建筑物、道路、车辆等。这对于各种应用场景如自动驾驶、3D建模、机器人导航等都至关重要。
图自:https://openaccess.thecvf.com/content_cvpr_2017/papers/Qi_PointNet_Deep_Learning_CVPR_2017_paper.pdf《PointNet:用于3D分类和分割的点集深度学习》
点云平面分割是从激光扫描仪获取的无序点云自动重建室内和城市环境的基本任务。作为最常见的平面分割方法之一,随机采样一致性 (RANSAC) 通常用于连续检测一个又一个的平面。
为什么要进行点云分割?
进行点云分割的主要原因有以下几点:
-
简化数据处理:分割后的点云数据更易于处理和分析,减少了计算复杂度。
-
提高识别精度:通过分割,将不同对象从点云中分离出来,有助于提高对象识别和分类的准确性。
-
增强应用效果:在实际应用中,分割后的点云可以更好地用于3D建模、环境感知、物体检测等任务,提高应用效果和实用性。
RANSAC算法发展历史
RANSAC(Random Sample Consensus,随机抽样一致性)算法由Fischler和Bolles于1981年提出,是一种通过随机抽样找到数据中的模型参数的算法。RANSAC在处理含有大量噪声和离群点的数据时,表现尤为出色。该算法的核心思想是反复从数据集中随机抽取样本,估计模型参数,并通过评估一致性来选择最优模型。尽管RANSAC已经有40多年的历史,但其简单有效的特性使其在点云分割、图像匹配、平面拟合等领域依然广泛应用。
算法概述
Fischler 和 Bolles 提出的 RANdom SAmple Consensus (RANSAC) 算法 [1] 是一种通用的参数估计方法,旨在应对输入数据中大量离群值。与许多从统计学文献中被计算机视觉社区采用的常见鲁棒估计技术(如 M-估计和最小中值平方)不同,RANSAC 是由计算机视觉社区内部开发的。
RANSAC 是一种重采样技术,通过使用估计基础模型参数所需的最小观察数(数据点)来生成候选解决方案。正如 Fischler 和 Bolles [1] 指出,与使用尽可能多的数据来获得初步解决方案然后剔除离群值的传统采样技术不同,RANSAC 使用最小的可能集合,然后使用一致的数据点扩展这个集合 [1]。
基本算法RANSAC概述如下:
-
随机选择确定模型参数所需的最小点数。
-
求解模型参数。
-
确定所有点集中有多少点符合预定的容差 。
-
如果集合中内点的数量与总点数的比例超过预定阈值 ,则使用所有识别的内点重新估计模型参数并终止。
-
否则,重复步骤 1 到 4(最多 次)。
迭代次数 的选择足够高,以确保至少有一个随机样本集不包含离群值的概率 (通常设为 0.99)。设 表示任何选定数据点为内点的概率, 表示观察到离群值的概率。需要进行 次最小点数 的迭代,其中
因此,通过一些操作得到:
有关基本 RANSAC 公式的更多详细信息,请参见 [1, 2]。RANSAC 的扩展包括使用最大似然框架 [4] 和重要性采样 [3]。
原文参见:https://www.cse.yorku.ca/~kosta/CompVis_Notes/ransac.pdf
RANSAC算法的数学原理可以概括如下:
-
随机抽样:从点云数据中随机选择若干点作为样本。
-
模型拟合:使用选定的样本点拟合模型。
-
一致性检验:计算拟合模型的所有点的误差,确定与模型一致的点(内点)。
-
模型优化:重复上述步骤多次,选择内点最多的模型作为最终模型。
假设我们要拟合一个平面模型,平面方程为:
RANSAC的具体步骤如下:
-
从点云数据中随机选择三个点,设为, 和。
-
计算平面模型参数 , , 和 :
-
计算所有点到该平面的距离,根据距离判断是否为内点。
-
重复上述步骤,选择内点最多的平面模型作为最终结果。
应用领域和场景
RANSAC算法在各种应用领域中得到了广泛应用,主要包括:
https://isprs-annals.copernicus.org/articles/IV-2/1/2018/isprs-annals-IV-2-1-2018.pdf《H-RANSAC: A HYBRID POINT CLOUD SEGMENTATION COMBINING 2D AND 3D DATA》
-
3D建模:用于从点云数据中提取建筑物、道路等结构
https://ieeexplore.ieee.org/document/7989159/
-
自动驾驶:在环境感知中,RANSAC用于分割和识别道路、障碍物等。
https://openaccess.thecvf.com/content/CVPR2023W/PVUW/papers/Sakaino_PanopticRoad_Integrated_Panoptic_Road_Segmentation_Under_Adversarial_Conditions_CVPRW_2023_paper.pdf
-
机器人导航:帮助机器人识别和避开障碍物,提高导航精度。
-
图像处理:用于图像配准、平面拟合等任务。
https://www.cs.princeton.edu/courses/archive/fall11/cos495/COS495-Lecture11-LineExtraction.pdf
基于Python的可视化算法实例
下面是一个基于Python实现RANSAC点云分割的简单示例,点云数据均可在网址上获取(https://towardsdatascience.com/3d-model-fitting-for-point-clouds-with-ransac-and-python-2ab87d5fd363):
import random # 导入用于生成随机数的库
import numpy as np # 导入用于科学计算的库
import matplotlib.pyplot as plt # 导入用于数据可视化的库
from sklearn.neighbors import KDTree # 导入用于快速最近邻搜索的KDTree实现
from mayavi import mlab # 导入用于3D数据可视化的库# 选择数据集路径
data_file = r"D:\系统默认\桌面\协作文件夹\Open3d python三维点云学习资料\the_researcher_desk.xyz" # 请替换为你的数据文件路径# 读取点云数据
pcd = np.loadtxt(data_file, skiprows=1) # 读取点云数据文件,跳过第一行# 分离几何属性和辐射属性
xyz = pcd[:, :3] # 提取前三列作为几何属性(x, y, z坐标)
rgb = pcd[:, 3:6] # 提取后三列作为辐射属性(颜色值)# 可视化点云(2D视图)
plt.figure(figsize=(8, 5), dpi=150) # 创建一个8x5英寸,150dpi的图形
plt.scatter(xyz[:, 0], xyz[:, 1], c=rgb/255, s=0.05) # 绘制散点图,颜色为rgb值,点大小为0.05
plt.title("Top-View") # 设置图形标题
plt.xlabel('X-axis (m)') # 设置x轴标签
plt.ylabel('Y-axis (m)') # 设置y轴标签
plt.show() # 显示图形# 使用Mayavi进行3D可视化
mlab.points3d(xyz[:, 0], xyz[:, 1], xyz[:, 2], xyz[:, 2], mode="point", colormap='viridis') # 使用Mayavi绘制3D点云,颜色为高度(z值)
mlab.title("Point Cloud Visualization") # 设置图形标题
mlab.colorbar(title='Height', orientation='vertical') # 添加颜色条,表示高度
mlab.show() # 显示图形# 设置RANSAC参数
threshold = 0.05 # 设置点到平面的距离阈值
iterations = 1000 # 设置RANSAC算法的迭代次数# 自动设置参数
tree = KDTree(np.array(xyz), leaf_size=2) # 使用KDTree进行最近邻搜索,加速计算
nearest_dist, nearest_ind = tree.query(xyz, k=8) # 查询每个点的8个最近邻点
avg_distance = np.mean(nearest_dist[:, 1:]) # 计算平均距离,忽略自身距离
threshold = avg_distance * 10 # 设置新的距离阈值为平均距离的10倍# RANSAC 平面检测函数
def ransac_plane(xyz, threshold=0.05, iterations=1000):inliers = [] # 初始化内点列表n_points = len(xyz) # 获取点云的点数i = 0 # 初始化迭代计数器while i < iterations: # 迭代进行RANSACidx_samples = random.sample(range(n_points), 3) # 随机选择3个点pts = xyz[idx_samples] # 获取这3个点的坐标vecA = pts[1] - pts[0] # 计算向量AvecB = pts[2] - pts[0] # 计算向量Bnormal = np.cross(vecA, vecB) # 计算法向量a, b, c = normal / np.linalg.norm(normal) # 归一化法向量d = -np.sum(normal * pts[1]) # 计算平面方程的d值distance = (a * xyz[:, 0] + b * xyz[:, 1] + c * xyz[:, 2] + d) / np.sqrt(a ** 2 + b ** 2 + c ** 2) # 计算所有点到平面的距离idx_candidates = np.where(np.abs(distance) <= threshold)[0] # 找到所有符合距离阈值的点(内点)if len(idx_candidates) > len(inliers): # 如果当前内点数量大于之前的最大内点数量equation = [a, b, c, d] # 更新平面方程参数inliers = idx_candidates # 更新内点列表i += 1 # 迭代计数器加1return equation, inliers # 返回平面方程参数和内点列表# 执行RANSAC
eq, idx_inliers = ransac_plane(xyz, threshold, iterations) # 调用RANSAC平面检测函数
inliers = xyz[idx_inliers] # 获取内点坐标# 获取外点
mask = np.ones(len(xyz), dtype=bool) # 创建一个全为True的布尔数组
mask[idx_inliers] = False # 将内点位置设置为False
outliers = xyz[mask] # 获取外点坐标# 可视化结果(Matplotlib)
ax = plt.axes(projection='3d') # 创建一个3D绘图对象
ax.scatter(inliers[:, 0], inliers[:, 1], inliers[:, 2], c='cornflowerblue', s=0.02) # 绘制内点,颜色为淡蓝色
ax.scatter(outliers[:, 0], outliers[:, 1], outliers[:, 2], c='salmon', s=0.02) # 绘制外点,颜色为鲑鱼色
plt.show() # 显示图形# 导出结果
result_folder = r"D:\系统默认\桌面\python三维点云学习资料\RESULTS" # 设置结果保存路径
np.savetxt(result_folder + "inliers.xyz", inliers, fmt='%1.4f', delimiter=';') # 保存内点坐标
np.savetxt(result_folder + "outliers.xyz", outliers, fmt='%1.4f', delimiter=';') # 保存外点坐标
通过上述代码,我们可以将点云数据中的平面部分(例如桌面、地板等)分割出来,并以不同颜色进行可视化。这种分割方法不仅简化了后续处理步骤,还能显著提高对象识别的精度和效率。
可视化 1:Matplotlib 2D视图
提供点云数据的2D平面视图,从而快速了解数据的分布和结构。
实现方式:
-
使用
matplotlib.pyplot
创建一个2D散点图,展示点云数据的X和Y坐标。 -
使用颜色 (
c=rgb/255
) 表示点的辐射属性(颜色值)。 -
设置图形的大小、分辨率和标题。
表现内容:
-
从上方观察的点云数据平面视图(Top-View)。
-
X轴和Y轴表示点的平面位置,颜色则提供了点的辐射属性信息。
-
该视图有助于识别数据中的密集区域、异常点和总体分布趋势。
可视化 2:Mayavi 3D视图
提供点云数据的交互式3D视图,使用户能够从多个角度查看数据并理解其空间结构。
实现方式:
-
使用
mayavi.mlab
创建一个3D散点图,展示点云数据的X、Y和Z坐标。 -
颜色渐变表示点的高度(Z轴),使用
colormap='viridis'
设定颜色映射。 -
添加颜色条(colorbar)以表示高度信息。
表现内容:
-
点云数据的3D视图,用户可以通过旋转和缩放来观察数据的三维结构。
-
颜色表示高度(Z轴),使得不同高度的点可以通过颜色轻松区分。
-
该视图提供了全面的空间结构理解,有助于识别数据的高低变化和总体形状。
可视化 3:Matplotlib 3D视图(分割结果)
展示通过RANSAC算法分割后的点云数据,区分内点和外点。
实现方式:
-
使用
matplotlib.pyplot
创建一个3D散点图,分别展示内点和外点的X、Y和Z坐标。 -
内点(符合平面模型的点)使用淡蓝色(
cornflowerblue
)表示,外点(不符合平面模型的点)使用鲑鱼色(salmon
)表示。 -
通过不同颜色区分内点和外点。
表现内容:
-
分割后的点云数据3D视图,清晰展示了内点和外点的空间分布。
-
内点和外点的颜色区分使得用户能够直观地看到哪些点符合平面模型,哪些点为异常点或噪声。
-
该视图有助于评估RANSAC算法的效果,理解数据的分割情况。
该代码实现了从点云数据文件中读取数据,进行预处理和可视化,并通过RANSAC算法进行平面检测。具体流程包括:1)读取和分离点云数据的几何和辐射属性,2)使用Matplotlib进行2D和3D数据可视化,3)使用Mayavi进行3D可视化以展示点云的高度信息,4)使用KDTree加速最近邻搜索,5)基于自动计算的阈值和迭代次数运行RANSAC算法,检测平面并识别内点和外点,6)最终可视化分割结果并保存内点和外点数据到文件中。
以上内容总结自网络,如有帮助欢迎关注与转发,我们下次再见!