Python中从嵌套NumPy数组移除完全匹配的三维点云坐标
移除NumPy三维点云数组中完全匹配的点
你当前用np.isin(point, r).all(axis=1)的逻辑存在问题:np.isin会逐元素检查point中的每个坐标值是否出现在r的所有元素中(将r扁平化后),再通过all(axis=1)要求三个维度的坐标值都在r里——但这会误删那些三个维度的坐标值分别出现在r的不同点中的点,而非完全匹配r中某个完整点的点。
下面是两种高效的解决方法,均为向量化操作,无需循环:
方案1:利用视图将三维点转为一维结构化元素(推荐)
通过np.view将每个三维点转换为单一的“复合元素”,让np.isin直接按完整点匹配,效率极高,适合大数据量场景:
import numpy as np # 示例数据(替换为你的实际数组) r = np.array([[1, 2, 3], [4, 5, 6]]) point = np.vstack((las.x, las.y, las.z)).transpose() # 将三维数组转为一维结构化视图(不占用额外内存) point_view = point.view(np.dtype((np.float64, 3))) r_view = r.view(np.dtype((np.float64, 3))) # 生成掩码:保留不在r中的点 non_building_mask = ~np.isin(point_view, r_view).flatten() # 提取结果并保存LAS文件 sampled_points = point[non_building_mask] new_file = laspy.create(point_format=las.header.point_format, file_version=las.header.version) new_file.x, new_file.y, new_file.z = sampled_points.T
方案2:利用广播机制逐点匹配
逻辑更直观,通过广播让point和r逐行比对,判断每个点是否存在于r中,适合数据量不大的场景(几千个点完全没问题):
import numpy as np # 示例数据(替换为你的实际数组) r = np.array([[1, 2, 3], [4, 5, 6]]) point = np.vstack((las.x, las.y, las.z)).transpose() # 广播比对:判断每个点是否与r中任意点完全匹配 is_in_r = (point[:, None] == r).all(axis=2).any(axis=1) non_building_mask = ~is_in_r # 提取结果并保存LAS文件 sampled_points = point[non_building_mask] new_file = laspy.create(point_format=las.header.point_format, file_version=las.header.version) new_file.x, new_file.y, new_file.z = sampled_points.T
两种方案特点:
- 方案1:几乎不占用额外内存,向量化操作效率拉满,适合上万级及以上的点云数据。
- 方案2:代码逻辑易懂,但广播会生成临时数组,数据量极大时(如十万级)会占用较多内存。
内容的提问来源于stack exchange,提问作者Purple_Ad
相关产品推荐
相关产品推荐

