2.2 点云处理
点云处理是LiDAR激光雷达感知中的一个重要步骤,它涉及到对从激光雷达获得的点云数据进行预处理、去噪、降采样等操作,以提高数据的质量和准确性。在下面的内容中,将详细讲解实现点云处理的知识。
2.2.1 滤波(Filtering)算法
滤波的目的是去除点云中的异常值,降低噪声。用到的算法有高斯滤波(Gaussian Filter)算法和中值滤波(Median Filter)算法。
1. 高斯滤波(Gaussian Filter)算法
使用高斯函数对周围点的权重进行加权平均。在智能驾驶中,LiDAR传感器采集的点云数据通常需要进行滤波处理,以去除噪声并平滑点云。高斯滤波是一种常用的滤波算法,通过对每个点的邻域进行高斯权重加权平均,实现了有效的噪声去除和数据平滑。
2. 中值滤波(Median Filter)算法
中值滤波是一种常用的信号处理和图像处理技术,用于去除图像或信号中的噪声。在中值滤波中,对于给定的一组数据,将其按大小排序,然后选择中间位置的值作为滤波结果。这种方法对于椒盐噪声等离群值有较好的抑制效果。在LiDAR(激光雷达)点云处理中,中值滤波可以用于去除由于噪声或其他因素引起的离群点,使得点云更加平滑,有助于后续的地图构建、目标检测等任务。
请看下面的实例,功能是使用 Python 中的 NumPy、Matplotlib 和 SciPy 库生成并可视化模拟的一维 LiDAR 点云数据,并对该数据进行高斯滤波处理。
实例2-1:对一维 LiDAR 点云数据进行高斯滤波处理(codes/2/filting.py)
实例文件filting.py的具体实现代码如下所示。
import numpy as np
import matplotlib.pyplot as plt
from scipy.ndimage import gaussian_filter1d
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimSun', 'Arial'] # 同时设置中文和英文字体
# 假设这是来自LiDAR传感器的真实一维点云数据
lidar_data = np.random.normal(0, 0.1, 1000) # 这里使用随机生成的一维数据,实际应替换为真实LiDAR数据
# 高斯滤波处理
sigma = 5.0 # 高斯核的标准差,根据实际情况调整
smoothed_lidar_data = gaussian_filter1d(lidar_data, sigma=sigma)
# 可视化结果
plt.plot(lidar_data, label='原始LiDAR数据', alpha=0.5)
plt.plot(smoothed_lidar_data, label='滤波后LiDAR数据', alpha=0.8)
plt.legend()
plt.title('LiDAR点云数据高斯滤波示例')
plt.show()
上述代码的实现流程如下:
- 使用 NumPy 的 random.normal 函数生成一个包含1000个元素的随机正态分布数据,模拟 LiDAR 传感器采集到的一维点云数据。
- 使用 SciPy 的 gaussian_filter1d 函数对模拟的 LiDAR 数据进行一维高斯滤波处理,sigma 参数表示高斯核的标准差,根据实际情况进行调整。
- 使用 Matplotlib 绘制原始 LiDAR 数据和经过高斯滤波处理后的数据的折线图,并添加图例和标题,最后显示绘制的可视化图形。效果如图2-1所示。
图2-1 滤波处理后的折线图
注意:本实例的整个流程通过Python语言实现,使用了NumPy和Matplotlib等库来生成、处理和可视化LiDAR点云数据。这种流程可以用于初步的LiDAR数据处理,例如去除噪声,使得点云更适合进行后续的地图构建或目标检测等应用。
2.2.2 降采样(Downsampling)算法
降采样的目的是减少点云数据量,提高计算效率。用到的降采样(Downsampling)算法如下所示。
1. 体素滤波(Voxel Grid Filter)算法
体素滤波算法将点云划分为小的立方体,每个立方体内只保留一个点。它通过将点云数据划分为三维空间中的小立方体单元(称为体素),并对每个体素内的点进行聚合或采样,从而实现去噪或下采样的效果。该算法的基本原理是将三维点云数据划分为规则的立方体网格,然后对每个立方体内的点进行处理。具体步骤如下:
- 确定立方体的大小和边界:根据应用需求,选择适当的立方体大小,通常使用正方形或长方体形状,并确定边界范围。
- 创建体素网格:根据设定的立方体大小和边界范围,在三维空间中创建一个规则的体素网格。
- 将点云数据分配到体素:遍历点云数据,将每个点分配给对应的体素,可以根据点与立方体的位置关系进行简单的计算来确定归属关系。
- 对每个体素进行处理:对于每个体素,可以选择两种操作之一,其中一种是聚合操作,是指将体素内的所有点聚合成一个新的代表点,例如计算平均值或中心点。另一种是采样操作,是指从体素内随机选择一个或多个点作为代表,可以通过随机抽取或均匀采样等方式进行。
- 生成滤波后的点云数据:经过处理的体素及其代表点集合将形成滤波后的点云数据。
2. 随机采样一致(Random Sample Consensus,RANSAC)算法
随机选择点云中的样本来进行拟合,从而减少数据量。RANSAC的基本思想是通过随机选择一小部分数据点来估计模型,然后通过检查其他数据点与该模型的拟合程度来评估模型的质量。这个过程被迭代执行,直到找到满足一定条件的最佳模型。
请看下面的例子,首先生成了随机点云,然后用体素滤波简化点云,最后通过Matplotlib可视化展示原始与滤波后的点云。
实例2-2:使用体素滤波算法处理点云数据(codes/2/ti.py)
实例文件ti.py的具体实现代码如下所示。
import matplotlib.pyplot as plt
import numpy as np
num_points = 1000
points = np.random.randn(num_points, 3)
def voxel_grid_filter(points, voxel_size):
min_coords = np.min(points, axis=0)
max_coords = np.max(points, axis=0)
num_voxels = np.ceil((max_coords - min_coords) / voxel_size).astype(int)
voxel_grid = [[] for _ in range(num_voxels[0] * num_voxels[1] * num_voxels[2])]
for i, point in enumerate(points):
voxel_indices = ((point - min_coords) / voxel_size).astype(int)
voxel_index = np.ravel_multi_index(voxel_indices, num_voxels)
voxel_grid[voxel_index].append(point)
filtered_points = [voxel[0] for voxel in voxel_grid if len(voxel) > 0]
return np.array(filtered_points)
voxel_size = 0.1 # Voxel size (in meters)
filtered_points = voxel_grid_filter(points, voxel_size)
fig = plt.figure()
ax = fig.add_subplot(121, projection='3d')
ax.scatter(points[:, 0], points[:, 1], points[:, 2])
ax.set_title('Original Point Cloud')
ax = fig.add_subplot(122, projection='3d')
ax.scatter(filtered_points[:, 0], filtered_points[:, 1], filtered_points[:, 2])
ax.set_title('Filtered Point Cloud')
plt.show()
上述代码的实现流程如下:
- 首先,生成了包含1000个三维点的随机点云数据,其中每个点的坐标由正态分布产生。
- 接着,定义了一个名为voxel_grid_filter的函数,该函数用于对点云进行体素滤波。在函数内部,首先计算了点云的最小和最大坐标,然后根据指定的体素大小计算了每个维度上的体素数量。接下来,创建了一个空的体素网格,用于存储每个体素中的点。随后,遍历点云中的每个点,将其分配到相应的体素中。最后,从每个体素中选择一个代表性点,形成了滤波后的点云。
- 然后,定义了体素大小为0.1米,并调用了voxel_grid_filter函数对之前生成的随机点云进行体素滤波,得到了滤波后的点云数据。
- 最后,通过Matplotlib进行可视化,创建了一个包含两个子图的可视化图,如图2-2所示。左侧子图展示了原始点云数据,右侧子图展示了经过体素滤波后的点云数据。这种对比有助于直观地观察体素滤波对点云的影响,以及如何通过减少点云密度来简化数据。
图2-2 可视化点云图的对比
2.2.3 去噪(Noise Removal)算法
去噪的目的是去除由于传感器错误或环境干扰引入的噪声点,常用的去噪(Noise Removal)算法如下所示。
1. 基于统计的去噪(Statistical Outlier Removal)算法
基于统计的去噪(Statistical Outlier Removal)算法用于移除具有异常统计特征的点,是一类通过统计分析来识别和移除离群值或噪声点的方法。这类算法通常基于假设数据中的噪声点是少数,并且它们的统计属性(如均值和标准差)与主要数据分布不同。一个常见的统计去噪方法是使用均值和标准差来判断数据点是否为离群值。
2. 移动最小二乘法(Moving Least Squares,MLS)算法
基于统计的去噪(Statistical Outlier Removal)算法是一种用于平面拟合、曲面拟合以及点云去噪等任务的算法,它基于最小二乘法的思想,通过在点云上的局部邻域内拟合局部模型来平滑和修复点云数据。
请看下面的例子,演示了使用基于统计的去噪算法处理LiDAR点云数据的过程。
实例2-3:使用基于统计的去噪算法处理LiDAR点云(codes/2/qu.py)
实例文件qu.py的具体实现代码如下所示。
import numpy as np
import matplotlib.pyplot as plt
# 生成模拟的LiDAR点云数据
np.random.seed(42)
num_points = 1000
x = np.random.uniform(low=-10, high=10, size=num_points)
y = np.sin(x) + 0.2 * np.random.normal(size=num_points)
z = 0.5 * x + 0.1 * y + 2 * np.random.normal(size=num_points)
points = np.column_stack((x, y, z))
# 添加椒盐噪声
noise_ratio = 0.05
num_noise_points = int(noise_ratio * num_points)
noise_indices = np.random.choice(num_points, num_noise_points, replace=False)
points[noise_indices] += np.random.uniform(low=-2, high=2, size=(num_noise_points, 3))
# 实现基于统计的去噪算法
def statistical_denoising(points, threshold=2.0):
mean = np.mean(points, axis=0)
std = np.std(points, axis=0)
# 计算每个点到均值的距离
distances = np.linalg.norm(points - mean, axis=1)
# 根据距离和阈值判断是否为噪声点
is_outlier = distances > threshold * np.mean(std) # 使用均值而不是数组
# 去除噪声点
denoised_points = points[~is_outlier]
return denoised_points
# 使用基于统计的去噪算法
denoised_points = statistical_denoising(points, threshold=2.0)
# 可视化结果
fig = plt.figure(figsize=(10, 6))
ax = fig.add_subplot(121, projection='3d')
ax.scatter(points[:, 0], points[:, 1], points[:, 2], c='b', marker='.', label='Original Point Cloud')
ax.set_title('Original LiDAR Point Cloud')
ax = fig.add_subplot(122, projection='3d')
ax.scatter(denoised_points[:, 0], denoised_points[:, 1], denoised_points[:, 2], c='r', marker='.',
label='Denoised Point Cloud')
ax.set_title('LiDAR Point Cloud after Statistical Denoising')
plt.show()
上述代码的实现流程如下:
- 首先,生成模拟的LiDAR点云数据,包括x、y和z坐标。在这个例子中,点云数据被设计为具有正弦形状,并添加了一些椒盐噪声。
- 然后定义函数statistical_denoising(),实现了一个基于统计的去噪算法。该算法首先计算点云的均值和标准差,然后计算每个点到均值的距离。通过设定阈值,判断哪些点被认为是噪声点,最终去除了这些噪声点。
- 最后,通过Matplotlib可视化工具展示了原始LiDAR点云和经过统计去噪后的LiDAR点云,如图2-3所示。这种可视化有助于观察去噪算法的效果,使得点云更加清晰并减少了噪声的影响。
图2-3 可视化比较原始点云和去噪后的点云