文章目录
- [【项目实战】PointCloud-GeoLab:用 Python / NumPy 搭建一个可运行的点云几何算法实验室](#【项目实战】PointCloud-GeoLab:用 Python / NumPy 搭建一个可运行的点云几何算法实验室)
-
- [1. 为什么做这个项目?](#1. 为什么做这个项目?)
- [2. 项目整体定位](#2. 项目整体定位)
- [3. 项目能做什么?](#3. 项目能做什么?)
- [4. 一键运行 Demo](#4. 一键运行 Demo)
-
- [4.1 安装依赖](#4.1 安装依赖)
- [4.2 生成 demo 数据](#4.2 生成 demo 数据)
- [4.3 运行完整 pipeline](#4.3 运行完整 pipeline)
- [5. 效果展示](#5. 效果展示)
-
- [5.1 原始点云](#5.1 原始点云)
- [5.2 ICP 配准前后对比](#5.2 ICP 配准前后对比)
- [5.3 点云分割结果](#5.3 点云分割结果)
- [5.4 包围盒与法向量分析](#5.4 包围盒与法向量分析)
- [6. 核心模块一:空间索引](#6. 核心模块一:空间索引)
-
- [6.1 KDTree](#6.1 KDTree)
- [6.2 VoxelHashGrid](#6.2 VoxelHashGrid)
- [7. 核心模块二:点云预处理](#7. 核心模块二:点云预处理)
-
- [7.1 Voxel Downsampling](#7.1 Voxel Downsampling)
- [7.2 局部 PCA 法向量估计](#7.2 局部 PCA 法向量估计)
- [8. 核心模块三:ICP 点云配准](#8. 核心模块三:ICP 点云配准)
- [9. Robust ICP、Multi-scale ICP 与 GICP-style ICP](#9. Robust ICP、Multi-scale ICP 与 GICP-style ICP)
-
- [9.1 Point-to-plane ICP](#9.1 Point-to-plane ICP)
- [9.2 Robust / Trimmed ICP](#9.2 Robust / Trimmed ICP)
- [9.3 Multi-scale ICP](#9.3 Multi-scale ICP)
- [9.4 GICP-style ICP](#9.4 GICP-style ICP)
- [10. 核心模块四:RANSAC 几何拟合](#10. 核心模块四:RANSAC 几何拟合)
- [11. 核心模块五:几何分析](#11. 核心模块五:几何分析)
-
- [11.1 PCA 主方向分析](#11.1 PCA 主方向分析)
- [11.2 AABB](#11.2 AABB)
- [11.3 OBB](#11.3 OBB)
- [12. 核心模块六:点云分割与 LiDAR-like 示例](#12. 核心模块六:点云分割与 LiDAR-like 示例)
- [13. Benchmark 与报告生成](#13. Benchmark 与报告生成)
- [14. 测试与工程化验证](#14. 测试与工程化验证)
- [15. 实验性 Web Console](#15. 实验性 Web Console)
- [16. 当前限制](#16. 当前限制)
- [17. 后续计划](#17. 后续计划)
- [18. 总结](#18. 总结)
【项目实战】PointCloud-GeoLab:用 Python / NumPy 搭建一个可运行的点云几何算法实验室
摘要:本文介绍一个偏学习、实验和作品集展示的点云处理项目 PointCloud-GeoLab。项目用 Python / NumPy 实现并串联 KDTree、VoxelHashGrid、ICP、RANSAC、PCA、OBB、DBSCAN、地面移除、Benchmark、报告生成和实验性 Web Console,适合正在学习点云处理、三维视觉、LiDAR perception 或几何算法的同学参考。
项目地址 :
https://github.com/lazyJLBL/PointCloud-GeoLab
最近整理并开源了一个点云处理项目:PointCloud-GeoLab。
这个项目不是为了替代 PCL、Open3D 这类成熟点云库,也不是简单把现有库再封装一层。它更像是我在学习点云处理、三维视觉和几何算法过程中的一个阶段性整理:把常见点云算法拆开,用 Python / NumPy 写成相对容易阅读、运行、测试和复现的版本。
一句话概括:
PointCloud-GeoLab 更关注算法过程、工程结构和结果可复现,而不是追求极限性能。
目前项目主要覆盖:
- 空间索引:KDTree、VoxelHashGrid
- 点云预处理:下采样、裁剪、采样、去噪、法向量估计
- 点云配准:ICP、Robust ICP、Trimmed ICP、Multi-scale ICP、GICP-style ICP
- 几何拟合:RANSAC 平面、球、圆柱拟合
- 几何分析:PCA、AABB、OBB
- 点云分割:DBSCAN、欧式聚类、区域生长、地面移除
- 结果输出:Benchmark、Markdown / HTML 报告、可视化图片、PLY 文件
- 交互展示:实验性的 FastAPI + Vue Web Console
相比单独写几个算法函数,我更希望这个项目能形成一个完整链路:
text
输入数据 -> 算法处理 -> 指标统计 -> 可视化图片 -> Markdown / HTML 报告 -> PLY / JSON artifact
这也是它更适合作为学习项目、实验项目和作品集项目的原因。
1. 为什么做这个项目?
点云处理里有很多经典算法,比如 KDTree、ICP、RANSAC、PCA、DBSCAN 等。
直接使用 Open3D 或 PCL 可以很快跑出结果,但在学习阶段,我经常会遇到一个问题:
结果出来了,但很多中间细节并不清楚。
例如:
- KDTree 是怎么做空间划分和剪枝的?
- ICP 每一轮是怎么找对应点、估计刚体变换的?
- RANSAC 为什么能在存在离群点的情况下拟合模型?
- PCA 为什么可以用来估计法向量和包围盒?
- DBSCAN 的半径参数为什么会明显影响点云分割结果?
- Benchmark 结果为什么不能只看单次运行时间?
所以我做 PointCloud-GeoLab 的主要目的,是把这些常见算法整理成一个可以运行、可以查看结果、也方便继续修改的实验环境。
我希望它尽量满足几个目标:
- 核心算法尽量保持可读。
- Demo 可以一键运行,并生成可检查的结果。
- 每个模块尽量配套测试或 benchmark。
- 项目结构不要只停留在单个脚本,而是方便后续扩展。
- 能够生成报告、图片、指标等 artifact,方便复盘和展示。
2. 项目整体定位
PointCloud-GeoLab 的定位可以概括为三个关键词:
学习型、实验型、作品集型。
它不是一个生产级点云库,也不是为了替代成熟三维视觉框架,而是把点云几何处理中常见的算法拆成相对清晰的模块,让它们能够被阅读、运行、测试和复现。
项目整体分成了算法层、API 层、CLI 层、报告层和 Web 展示层。
这样做的好处是:
- 算法模块可以单独测试;
- CLI 可以复用 API 层能力;
- Web Console 只是建立在已有任务接口上的展示层;
- Benchmark、报告和 artifact 可以单独验证;
- 后续扩展新算法时,不需要把所有逻辑都塞进一个脚本。
3. 项目能做什么?
PointCloud-GeoLab 目前采用模块化结构,主要包括下面几部分:
| 模块 | 主要功能 |
|---|---|
| KDTree / VoxelHashGrid | 最近邻搜索、kNN 查询、半径查询、空间索引 |
| Preprocessing | 下采样、裁剪、采样、去噪、局部 PCA 法向量估计 |
| Registration | ICP、Robust ICP、Trimmed ICP、Multi-scale ICP、GICP-style ICP |
| Geometry | PCA、AABB、OBB、点到平面/直线距离 |
| RANSAC Primitives | 平面、球、圆柱拟合,多模型提取 |
| Segmentation | DBSCAN、欧式聚类、区域生长、地面移除 |
| Benchmark | 输出 CSV、JSON、Markdown、PNG 等性能与指标结果 |
| Portfolio Pipeline | 一键生成报告、metrics、图片和点云结果 |
| Web Console | 通过浏览器上传点云、运行任务、查看和下载结果 |
从功能上看,它覆盖了点云几何算法项目中比较常见的一条链路:
text
空间索引 -> 预处理 -> 配准 / 拟合 / 分割 -> 几何分析 -> 指标统计 -> 报告输出
这也是我想通过这个项目表达的一点:算法项目不应该只有几个函数,最好还能说明输入是什么、输出是什么、指标怎么记录、结果怎么复现。
4. 一键运行 Demo
项目里提供了一个 portfolio pipeline,用来快速跑通完整流程。
4.1 安装依赖
bash
python -m pip install -e ".[dev,vis,bench]"
4.2 生成 demo 数据
bash
python examples/generate_demo_data.py --output examples/demo_data
4.3 运行完整 pipeline
bash
python -m pointcloud_geolab pipeline \
--input examples/demo_data \
--output outputs/portfolio_demo
运行结束后,会在输出目录中生成报告、指标、可视化图片和点云文件。例如:
text
outputs/portfolio_demo/
├── report.md
├── report.html
├── metrics.json
├── figures/
│ ├── raw_pointcloud.png
│ ├── downsampled.png
│ ├── registration_before_after.png
│ ├── segmentation_result.png
│ └── bounding_box_or_normals.png
└── artifacts/
├── processed_cloud.ply
└── transformation.json
默认 demo 的输出指标大致如下:
text
Input Points: 1000
Processed Points: 921
ICP RMSE: 0.178003 -> 0.008549
Clusters: 5
Noise Ratio: 60.50%
这部分是我比较看重的地方:项目不是只写几个算法函数,而是希望从输入数据、算法处理、结果统计到报告输出形成一个完整流程。
5. 效果展示
下面是 portfolio pipeline 生成的一些可视化结果。
5.1 原始点云
这是 pipeline 中生成的合成点云数据,用来演示后续的预处理、配准、分割和几何分析流程。

5.2 ICP 配准前后对比
下面这张图展示了 ICP 配准前后的点云变化。相比只看 RMSE 数字,前后对比图更容易直观看出配准效果。

5.3 点云分割结果
分割模块会对点云进行聚类,并输出不同 cluster 的统计信息。

5.4 包围盒与法向量分析
几何分析模块会计算 PCA、AABB、OBB 和局部法向量等信息,可用于目标尺寸估计、姿态分析和 cluster 报告生成。

6. 核心模块一:空间索引
点云算法中,邻域搜索是一个非常基础的部分。
比如:
- ICP 需要最近邻对应点;
- 法向量估计需要 kNN;
- DBSCAN 需要半径查询;
- 分割和特征描述也依赖邻域统计。
项目里实现了两个空间索引:KDTree 和 VoxelHashGrid。
6.1 KDTree
KDTree 支持最近邻、kNN、radius search、batch 查询等功能,并处理了空输入、重复点、高维输入等边界情况。
它主要用于展示递归空间划分和剪枝查询的思路。
KDTree 的核心思想是:
在每一层选择一个维度对点集进行划分,把空间递归拆成左右子树。查询时,先沿着目标点所在方向向下搜索,再根据距离判断是否需要回溯到另一侧子树。
这种结构可以减少不必要的距离计算,尤其适合最近邻和 kNN 查询。
6.2 VoxelHashGrid
VoxelHashGrid 是另一种更直观的空间索引方式。
它会将空间划分为固定大小的 voxel,每个点映射到一个整数 voxel key,再根据周围 voxel 查找邻域。
它适合用来理解:
- 空间哈希;
- 固定半径查询;
- 体素下采样;
- 局部邻域近似搜索。
这两个模块本身不一定要比成熟库更快,但它们有助于理解点云算法背后的基础查询逻辑。
7. 核心模块二:点云预处理
预处理模块包含一些常见操作:
- voxel downsampling
- AABB crop
- random sampling
- farthest point sampling
- statistical outlier removal
- radius outlier removal
- local PCA normal estimation
- point cloud normalization
其中比较典型的是体素下采样和法向量估计。
7.1 Voxel Downsampling
体素下采样的思路比较直接:
- 将点云空间划分为固定大小的 voxel;
- 把每个点映射到对应 voxel;
- 对同一个 voxel 内的点求均值或选代表点;
- 得到更稀疏但整体结构相近的点云。
它常用于减少点数量、加速后续 ICP、分割或几何分析。
7.2 局部 PCA 法向量估计
法向量估计采用的是经典的局部 PCA 方法:
- 对每个点查找 kNN 邻域;
- 计算邻域点的协方差矩阵;
- 对协方差矩阵做特征分解;
- 取最小特征值对应的特征向量作为局部法向量方向。
直观理解是:
一个局部平面上的点,在平面内两个方向的方差较大,而垂直平面的方向方差最小。因此,最小特征值对应的特征向量可以作为局部法向量。
当前实现主要用于学习和实验,没有加入复杂的全局方向一致化处理。
8. 核心模块三:ICP 点云配准
ICP 是项目中比较重要的模块之一。
目前包含:
- point-to-point ICP
- point-to-plane ICP
- robust ICP
- trimmed ICP
- multi-scale ICP
- GICP-style covariance-weighted ICP
基础 point-to-point ICP 的流程可以概括为:
- 对 source 点云做初始变换;
- 使用 KDTree 在 target 点云中查找最近邻;
- 根据对应点估计刚体变换;
- 更新 source 点云;
- 重复迭代,直到 RMSE 收敛或达到最大迭代次数。
在 portfolio pipeline 中,配准模块会记录:
- initial RMSE
- final RMSE
- fitness
- iterations
- converged
- correspondence count
- transformation matrix
这些信息最后会写入 metrics 和报告中,方便对比和复盘。
9. Robust ICP、Multi-scale ICP 与 GICP-style ICP
除了基础 ICP,项目还加入了一些常见扩展。
9.1 Point-to-plane ICP
Point-to-plane ICP 会利用目标点的法向量构造误差项。
相比 point-to-point ICP,它不只是最小化两个点之间的欧氏距离,而是更关注 source 点到 target 局部切平面的距离。
在局部表面比较稳定、法向量质量较好时,point-to-plane ICP 通常收敛更快。
但它也更依赖法向量估计质量。如果法向量噪声较大,或者方向不一致,结果可能会受到影响。
9.2 Robust / Trimmed ICP
普通 ICP 对离群点比较敏感。
如果 source 和 target 中存在噪声、遮挡或错误对应点,最近邻匹配会引入较大误差。
项目中的 robust ICP 和 trimmed ICP 主要用于降低离群点影响:
- Huber kernel:对大残差降低权重;
- Tukey kernel:对异常残差进一步抑制;
- trimmed correspondence:只保留较小残差的一部分对应关系。
这些方法并不能让 ICP 变成全局配准算法,但可以提升局部配准在噪声场景下的稳定性。
9.3 Multi-scale ICP
Multi-scale ICP 使用 coarse-to-fine 策略:
- 先在较大 voxel size 的下采样点云上做粗配准;
- 再逐级缩小 voxel size;
- 最后在更细尺度上做精配准。
这样做的好处是,粗尺度阶段点数更少、结构更平滑,有助于快速接近合理解;细尺度阶段再进一步优化局部细节。
9.4 GICP-style ICP
项目中也实现了一个 GICP-style ICP。
这里需要特别说明:
它不是完整的 nonlinear GICP optimizer。
当前实现更准确地说是 covariance-weighted ICP:
先估计局部 covariance,再根据 covariance-informed cost 得到权重,最后通过 weighted SVD 更新刚体变换。
这个模块更适合作为学习和实验版本,用来理解普通 ICP 到 covariance-aware ICP 的过渡。
10. 核心模块四:RANSAC 几何拟合
项目实现了 RANSAC primitive fitting,支持:
- 平面拟合
- 球拟合
- 圆柱拟合
- sequential primitive extraction
RANSAC 的基本思路是:
- 随机采样最小点集;
- 根据样本拟合候选模型;
- 计算所有点到模型的 residual;
- 根据阈值统计 inliers;
- 多次迭代后选择 inliers 数量更多、残差更小的模型。
这个模块可以用来从点云中提取常见几何结构,例如平面、球体和圆柱体。
比如在地面移除中,可以使用 RANSAC 拟合主导平面,然后把地面点和非地面点分开。
11. 核心模块五:几何分析
几何分析模块主要包括:
- PCA 主方向分析
- AABB 轴对齐包围盒
- PCA-based OBB 有向包围盒
- 点到平面距离
- 点到直线距离
11.1 PCA 主方向分析
PCA 可以用于分析点云的主要分布方向。
例如一个长条形物体,它在最长方向上的方差最大;如果对点云做 PCA,最大特征值对应的特征向量通常可以近似表示物体的主方向。
这在姿态估计、包围盒构造和 cluster 分析中比较常见。
11.2 AABB
AABB 是 Axis-Aligned Bounding Box,也就是轴对齐包围盒。
它的计算方式很直接:
分别取 x、y、z 三个方向上的 min 和 max,就可以得到一个与坐标轴对齐的包围盒。
AABB 简单、稳定、计算快,但如果物体本身是倾斜的,AABB 可能会包含较多空白区域。
11.3 OBB
OBB 是 Oriented Bounding Box,也就是有向包围盒。
项目中的 OBB 是 PCA-based OBB:
- 先对点云做 PCA;
- 使用 PCA 主轴构造局部坐标系;
- 把点云投影到主轴坐标系中计算范围;
- 再将 corner 转回世界坐标。
需要注意的是,PCA-based OBB 不一定是严格意义上的最小体积 OBB。
当点云接近球形,或者多个特征值接近时,PCA 主方向可能不够稳定。
12. 核心模块六:点云分割与 LiDAR-like 示例
分割模块包含:
- DBSCAN clustering
- Euclidean clustering
- Region growing segmentation
- RANSAC ground removal
- Ground-object clustering
- Cluster statistics
在 LiDAR-like 场景中,项目提供了一个 ground-object clustering 流程:
- 使用 RANSAC 拟合主导地面;
- 将地面点和非地面点分开;
- 对非地面点做聚类;
- 为每个 cluster 计算 centroid、AABB、OBB、volume 等统计信息;
- 输出 report、metrics 和 colored PLY。
这个流程不是完整自动驾驶感知系统,但可以作为理解 LiDAR 点云处理中"地面移除 + 目标聚类 + 几何统计"的一个入门实验。
项目也提供了读取 Velodyne .bin 格式的单帧示例。
不过它不是官方 KITTI benchmark,更准确地说是一个 user-provided KITTI-like single-frame workflow,用来展示点云数据在这个 pipeline 中的处理流程。
13. Benchmark 与报告生成
项目提供 benchmark 命令:
bash
python -m pointcloud_geolab benchmark \
--suite all \
--quick \
--output outputs/benchmarks
Benchmark 会输出 CSV、JSON、Markdown、PNG 等比对结果,以及详细的 metrics.json。
这些结果会记录:
- 参数配置;
- random seed;
- 数据规模;
- Python 版本;
- 平台信息;
- 可选依赖版本;
- repeat mean / std / min / max;
- benchmark artifact 路径。
这里我没有把某个固定 benchmark 数字写成性能结论,因为运行时间和内存占用都和机器环境有关。
更合理的做法是:
项目提供可复现的 benchmark 流程,用户可以在自己的机器上运行并查看结果。
14. 测试与工程化验证
除了算法实现,项目里也加入了一些测试和检查脚本,例如:
- 单元测试;
- CLI 测试;
- API 测试;
- benchmark artifact 检查;
- portfolio pipeline 检查;
- packaging / repo hygiene 检查;
- documented commands 检查。
常用验证命令包括:
bash
python -m pytest
python -m ruff check .
python -m black --check .
python scripts/check_artifact_schema.py
python scripts/check_documented_commands.py
python scripts/check_v1_ready.py
我认为一个算法项目如果只有 demo,可信度是不够的。
至少应该能说明:
- 结果如何生成;
- 指标如何记录;
- artifact 如何保存;
- 命令是否能够复现;
- 边界情况有没有测试;
- 后续修改是否容易破坏已有能力。
这也是这个项目除了算法实现之外,额外整理 benchmark、报告生成和验证脚本的原因。
15. 实验性 Web Console
项目还提供了一个实验性的 Web Console。
后端使用 FastAPI,前端使用 Vue 3。它的主要作用是方便上传点云、运行任务、查看 metrics 和下载 artifacts。
基本流程是:
text
上传点云 -> 采样预览 -> 运行任务 -> 查看 metrics -> 下载 artifacts
启动后端:
bash
python -m pip install -r web/backend/requirements.txt
make web-backend
启动前端:
bash
cd web/frontend
npm install
npm run dev
目前 Web Console 主要用于演示和调试,还不是生产级平台。
长任务、后台队列、权限控制和并发执行这些功能都还没有作为重点处理。
我把它放进项目里,主要是为了让算法结果不只停留在命令行里,而是可以通过一个更直观的界面查看输入、任务、metrics 和 artifacts。
16. 当前限制
这个项目目前仍然有不少限制,需要明确说明:
- ICP、robust ICP、multi-scale ICP 和 GICP-style ICP 都是局部优化方法,需要较好的初始姿态和重叠区域。
- GICP-style 使用 covariance-derived scalar weights + weighted SVD,不是完整 nonlinear GICP optimizer。
- DBSCAN 和 Euclidean clustering 使用全局半径,对 LiDAR 点云密度变化比较敏感。
- Ground removal 假设存在主导地面平面,对坡道、路沿和复杂道路结构还不够。
- Benchmark 结果和机器环境强相关,不能直接作为跨机器性能结论。
- Web Console 当前更适合演示和调试,不适合作为生产平台。
- optional PointNet 只是 synthetic shape demo,不是完整点云学习框架。
- 大规模 LiDAR 序列还需要 streaming、chunking、tiling 或更高效的空间后端。
把这些边界写清楚,并不是削弱项目价值。
相反,我觉得这能让项目更加真实,也更适合作为学习和作品集项目。
17. 后续计划
后续我想继续完善几个方向:
- 更完整的 nonlinear GICP optimizer;
- 更适合 LiDAR 密度变化的聚类方法;
- 更多真实点云数据 case study;
- Web Console 的后台任务队列与更丰富的交互式可视化;
- 为每个核心模块单独写技术文章。
后续也可以继续拆成系列文章,例如:
- 从零实现 KDTree 点云邻域搜索;
- Python 实现 ICP 点云配准;
- PCA、AABB、OBB 点云几何分析;
- RANSAC 平面、球、圆柱拟合;
- 如何为算法项目设计 benchmark 和 artifact verification。
18. 总结
PointCloud-GeoLab 是一个围绕点云几何算法构建的学习型、实验型、作品集型项目。
它的重点不是封装一个新的点云库,而是把点云处理中常见的核心模块拆开,让它们能够被阅读、运行、测试和复现。
目前项目已经覆盖:
- 空间索引;
- 点云预处理;
- 点云配准;
- RANSAC primitive fitting;
- PCA / AABB / OBB 几何分析;
- DBSCAN / 欧式聚类 / 区域生长;
- 地面移除和 LiDAR-like 示例;
- benchmark;
- Markdown / HTML 报告生成;
- CLI;
- 实验性 Web Console。
如果你也在学习点云处理、3D vision、LiDAR perception 或几何算法,希望这个项目能提供一些参考。
项目地址 :
https://github.com/lazyJLBL/PointCloud-GeoLab
欢迎交流、提 issue,也欢迎基于这个项目继续扩展更多点云算法实验。