直通滤波-PassThrough Filter-原理-代码实现
前言
- 对坐标轴上的上下限进行约束,选取其中符合范围的点云区域
- 使用场景:去除噪声点,关注特定区域,减小计算量
工作流程
- 假设我们要在 d d d 轴( d ∈ { x , y , z } d \in \{x, y, z\} d∈{x,y,z} )上应用直通滤波
- 设定该轴的下限为 d min d_{\text{min}} dmin ,上限为 d max d_{\text{max}} dmax,那么点 P i P_i Pi 是否被保留可以用以下公式表示: P i = ( x i , y i , z i ) P_i = (x_i, y_i, z_i) Pi=(xi,yi,zi)。
- 滤波条件为: d min ≤ d i ≤ d max d_{\text{min}} \leq d_i \leq d_{\text{max}} dmin≤di≤dmax
- 其中 d i d_i di 是点 P i P_i Pi 在指定轴上的坐标值(即 x i x_i xi 或 y i y_i yi 或 z i z_i zi)。直通滤波的结果是保留满足该条件的点,丢弃其他点。
- 假设点云的初始集合为 P = { P 1 , P 2 , . . . , P N } \mathcal{P} = \{P_1, P_2, ..., P_N\} P={P1,P2,...,PN},经过直通滤波后,得到新的点云集合 P ′ \mathcal{P}' P′,它由所有满足滤波条件的点构成:
- P ′ = { P i ∈ P ∣ d min ≤ d i ≤ d max } \mathcal{P}' = \{P_i \in \mathcal{P} \mid d_{\text{min}} \leq d_i \leq d_{\text{max}}\} P′={Pi∈P∣dmin≤di≤dmax}
具体示例
- 选择滤波轴:例如选择在
x
轴、y
轴或z
轴上进行过滤。 - 设置上下限:例如,在
z
轴上设定一个范围,如z_min = 0.5
,z_max = 1.5
,表示只保留高度在0.5到1.5之间的点。 - 过滤点云:滤波器会遍历整个点云数据,保留满足条件的点,丢弃超出上下限的点。
代码实现
import open3d as o3d
import numpy as npdef passthrough_filter(point_cloud, axis='z', lower_limit=0.0, upper_limit=1.0):"""对点云数据应用 PassThrough 过滤器,只保留指定范围内的点。参数:point_cloud (open3d.geometry.PointCloud): 输入点云数据。axis (str): 过滤的轴 ('x', 'y' 或 'z')。lower_limit (float): 过滤的下限。upper_limit (float): 过滤的上限。返回值:open3d.geometry.PointCloud: 过滤后的点云数据。"""# 将点云数据转换为 numpy 数组points = np.asarray(point_cloud.points)# 根据指定轴进行过滤if axis == 'x':mask = (points[:, 0] >= lower_limit) & (points[:, 0] <= upper_limit)elif axis == 'y':mask = (points[:, 1] >= lower_limit) & (points[:, 1] <= upper_limit)elif axis == 'z':mask = (points[:, 2] >= lower_limit) & (points[:, 2] <= upper_limit)else:raise ValueError("Axis must be 'x', 'y', or 'z'")# 应用过滤器filtered_points = points[mask]# 创建新的点云对象filtered_cloud = o3d.geometry.PointCloud()filtered_cloud.points = o3d.utility.Vector3dVector(filtered_points)return filtered_cloud# 加载点云数据
point_cloud = o3d.io.read_point_cloud("./data/33pod.ply")# 对点云应用 PassThrough 过滤器
filtered_point_cloud = passthrough_filter(point_cloud, axis='z', lower_limit=10, upper_limit=20)o3d.visualization.draw_geometries([point_cloud])
o3d.visualization.draw_geometries([filtered_point_cloud])
原始数据点云:
滤波后显示区域: