Files
massive-cloud/docs/点云测距算法性能分析报告.md
lipan 29f1d45d66 feat: 算法升级、整车配准集成与性能分析文档
算法更新: delivery v1.2.1、平整度v1.5、测距v2.2、整车配准v1.3
适配器: vehicle-registration 新增、各算法 manifest 和 adapter 更新
后端: taskCadFiles/source 字段迁移、derivedPointClouds 注册、取消任务联动
前端: ElapsedTime 时长显示、两步算法流程、canRun 逻辑修复
文档: 新增5份算法性能分析报告
2026-06-25 08:22:20 +00:00

5.9 KiB
Raw Permalink Blame History

点云测距算法性能分析报告

分析时间:2026-06-25
算法版本:train_measurement_system_v2.2
入口类:TaskManager(src/task_manager.py)
测试环境:INTEL SSDSC2KB01(SATA SSD,~394 MB/s);CPU 128 核
配置文件:config/measurements_0618.yaml(20 个测量任务)


执行流程总览

train_measurement_run.py (adapter)
    ├─ tm.pointcloud_path_override = pc_path
    ├─ tm.load_config()               # 读 YAML,解析 20 个任务
    ├─ tm.load_point_cloud()          # 一次性加载整车点云到内存  ← 瓶颈1
    └─ tm.run_all_tasks()
           ├─ 任务1: plane_to_plane
           │      ├─ ROIExtractor.extract_bbox_points()  # numpy 布尔索引,O(N)
           │      ├─ PlaneFitter.fit() × 2               # RANSAC,O(k×M)
           │      └─ distance calculation
           ├─ 任务2: plane_to_plane ... (× 10 个)
           ├─ 任务n: point_to_point  ... (× 3 个)
           ├─ 任务n: point_to_plane  ... (× 3 个)
           ├─ 任务n: plane_to_plane + 4_hole_center ... (× 2 个)
           └─ 任务n: point_to_point + hole_center   ... (× 2 个)

各步骤详细说明与时间估算

第一阶段:I/O — 加载点云

# 步骤 代码位置 说明 估算时间
1 PointCloudLoader.load_ply pointcloud_loader.py:11 逐点 struct.unpack for loop,O(N) 次 Python 调用 ← 瓶颈 ~3 min(10亿点)

关键问题:当前 _read_binary_ply 使用 struct.unpack 逐点循环,实测 ~5 M 点/s。对比 np.frombuffer(~30 M 点/s)慢 6×,10 亿点需要约 3 分钟仅用于读取。

# 当前实现:每个点一次 Python 函数调用
for _ in range(vertex_count):                     # ← N次循环
    data = struct.unpack(fmt, f.read(struct_size)) # ← N次 struct.unpack
    points.append(data[:3])

# 理想实现:一次性内存操作
data = f.read(vertex_count * struct_size)
arr  = np.frombuffer(data, dtype=record_dtype)    # ← 1次调用,~6× 更快

第二阶段:每个测量任务的执行(共 20 个)

每个任务共享同一份全量点云 self.point_cloud(已加载到内存),按序独立执行。

子步骤 A:ROI 裁剪

# 步骤 代码位置 说明 估算时间(单任务)
2 ROIExtractor.extract_bbox_points roi_extractor.py:10 numpy 全量布尔掩码,O(N) ~2–5 s(10亿点)

重要:每个任务都调用一次 extract_bbox_points,对 10 亿点全量 numpy 数组做 3 列比较。20 个任务 × 2–5 s = ~40–100 s 只用于 ROI 掩码,而 ROI 内实际只有 100–10 万个点。

各任务 ROI 尺寸与预期点数(10 亿点密度下):

任务 类型 source ROI 尺寸 (mm) source 预期点数
任务21_侧门高度 plane_to_plane [1000, 4, 20] ~221 pts
任务2_车体长度 plane_to_plane [4, 400, 1600] ~7,091 pts
任务43_窗口下沿高度 plane_to_plane [1210, 2, 5] ~33 pts
任务44_车顶高度 plane_to_plane [10449, 2, 474] ~27,439 pts

子步骤 B:平面拟合(plane_to_plane / point_to_plane 任务)

# 步骤 代码位置 默认参数 说明 估算时间(单任务)
3 PlaneFitter.fit(RANSAC) plane_fitter.py:44 max_iter=1000, threshold=0.1, sample_pts=100 RANSAC:1000 次随机抽 3 点 + 全 ROI 距离计算 < 0.1 s(ROI内千点级)
4 SVD 精确平面拟合 plane_fitter.py:137 max_svd_pts=10000 收敛后 SVD 精确拟合;>1 万点自动降采样 < 0.1 s
5 计算平面间距离 plane_distance.py — 点到平面距离 + 统计 < 0.01 s

子步骤 C:孔心检测(含 _hole_center 的任务)

# 步骤 代码位置 说明 估算时间(单任务)
6 HoleDetector.detect hole_detect/hole_detector.py 圆心检测 + RANSAC 圆拟合 ~2–5 s

第三阶段:结果输出

# 步骤 代码位置 说明 估算时间
7 ExcelExporter.export excel_exporter.py openpyxl 生成 xlsx ~5 s
8 MeasurementLogger.save measurement_logger.py JSON 结果落盘 < 1 s

总时间汇总(10 亿点输入)

阶段 估算耗时 说明
struct loop 读取 12 GB 点云 ~3 min 10 亿次 Python 调用
20 次全量 ROI 布尔索引 ~40–100 s 每次 O(N),共 20 次
20 个任务实际测量计算 ~20 s ROI 内点数少,RANSAC 极快
孔心检测(共 6 次) ~20 s —
输出(Excel + JSON) ~5 s —
估算总计 ~5–6 min 远超算法方测试的 ROI 后场景

算法方基准(~2 min)是直接在 ROI 后的小点云上跑的结果,没有计入全量加载和 20 次全量 ROI 索引的开销。


主要瓶颈与优化建议

瓶颈 1:struct.unpack 逐点读取(改算法方可根治)

当前:struct.unpack × 10亿次 → ~3 min
优化:np.frombuffer 一次性读 → ~35 s
速度提升:~5×,改动:pointcloud_loader.py _read_binary_ply 约 3 行

瓶颈 2:20 次全量 numpy 布尔索引(适配器层可缓解)

当前:每个任务都对 10亿点数组做 3 列 boolean 比较,共 20 次
优化方案 A:adapter 预处理——用 Open3D 先按整车大 bbox 粗裁剪到 ~1亿点,
           再传给 TaskManager,ROI 索引代价降 10×
优化方案 B:修改 TaskManager,第一次裁剪后缓存点云,
           下一个任务的 ROI 在上次结果上继续裁(层次裁剪)

GPU 使用情况

不使用 GPU。 所有计算为 CPU + numpy + scipy,无 torch/CUDA 依赖。