Python实现点云逐点生成定半径球体并统计球内点数
三维点云固定半径邻域点计数Python实现
实现思路
- 读取txt格式存储的点云数据,逐行解析每个点的X、Y、Z三维坐标
- 针对不同数据规模选择计算逻辑:千级以内小数据可以直接暴力遍历计算距离,十万级以上数据用KD树空间索引加速,避免O(n²)复杂度导致计算过慢
- 对每个点作为球心,统计三维欧氏距离小于等于指定半径的点总数(计数包含球心点本身)
- 将每个点对应的计数结果逐行写入新的txt文件,和输入点的顺序一一对应
首先安装需要的科学计算依赖(仅优化版需要,纯Python版无依赖):pip install numpy scipy
推荐版本:KD树加速版(支持百万级以内点云快速计算)
import numpy as np from scipy.spatial import cKDTree import time # ------------------- 自定义参数区 ------------------- INPUT_TXT_PATH = "input_pointcloud.txt" # 你的点云输入文件路径 OUTPUT_TXT_PATH = "count_result.txt" # 计数结果输出路径 SPHERE_RADIUS = 0.5 # 固定球体半径,按实际需求修改 # ---------------------------------------------------- if __name__ == "__main__": # 读取点云数据 print("正在读取点云文件...") point_cache = [] with open(INPUT_TXT_PATH, "r", encoding="utf-8") as f: for line in f: line = line.strip() if not line: continue # 跳过文件里的空行 x, y, z = map(float, line.split()) point_cache.append([x, y, z]) points = np.array(point_cache, dtype=np.float64) print(f"读取完成,共{len(points)}个点") # 构建KD树空间索引 print("正在构建空间索引...") kdtree = cKDTree(points) # 批量查询半径范围内的邻域点 print("正在统计邻域点数量...") start_ts = time.time() # workers=-1表示调用所有CPU核心并行计算 neighbors = kdtree.query_ball_point(points, r=SPHERE_RADIUS, workers=-1) count_list = [len(idx_list) for idx_list in neighbors] print(f"统计完成,耗时{time.time() - start_ts:.2f}秒") # 写入结果文件 print("正在写入结果文件...") with open(OUTPUT_TXT_PATH, "w", encoding="utf-8") as f: for cnt in count_list: f.write(f"{cnt}\n") print(f"处理完成,结果已保存到{OUTPUT_TXT_PATH}")
无依赖纯Python版(仅适合千级以内小点云测试)
这个版本不需要安装第三方库,但是点数量过万后速度会非常慢,仅做临时测试用:
# ------------------- 自定义参数区 ------------------- INPUT_TXT_PATH = "input_pointcloud.txt" OUTPUT_TXT_PATH = "count_result.txt" SPHERE_RADIUS = 0.5 # ---------------------------------------------------- if __name__ == "__main__": # 读取点云 points = [] with open(INPUT_TXT_PATH, "r", encoding="utf-8") as f: for line in f: line = line.strip() if not line: continue x, y, z = map(float, line.split()) points.append((x, y, z)) radius_sq = SPHERE_RADIUS ** 2 # 用平方值比较距离,省去开根号运算提速 count_res = [] for cx, cy, cz in points: cnt = 0 for x, y, z in points: dist_sq = (x-cx)**2 + (y-cy)**2 + (z-cz)**2 if dist_sq <= radius_sq: cnt += 1 count_res.append(cnt) # 写入结果 with open(OUTPUT_TXT_PATH, "w", encoding="utf-8") as f: for cnt in count_res: f.write(f"{cnt}\n")
几个注意点:
- 球体半径参数要和你点云的坐标单位匹配,不要出现坐标单位是米、半径填成毫米级数值的情况
- 点云规模超过100万的话,建议先做体素下采样减少点数量再计算,否则内存占用会很高
- 输出结果的顺序和输入点云的点顺序完全对应,不会出现错位
内容的提问来源于stack exchange,提问作者youssef
相关产品推荐
相关产品推荐

