想象你是一名夜间生态学家,背着一台高速激光相机走进漆黑的山谷。快门一响,成千上万只萤火虫被“定格”——每一只都记下了自己的空间坐标,构成一片漂浮在黑暗中的光点星图。这幅星图,就是计算机眼中的“点云”。可现实远不浪漫:远处路灯的余光混进来变成噪点,萤火虫密密麻麻难以数清,山谷太宽一次拍不全,必须从多个角度拍摄再拼接……点云处理,就是生态学家整理星图的整套手艺:如何表示萤火虫的位置、如何给星图瘦身、如何洗去杂光、如何读出每只萤火虫的姿态、如何把多张局部星图拼成完整山谷地图,再把光点归类成一个个萤火虫家族。这套手艺,正是自动驾驶感知、机器人抓取、三维重建的底层地基。本文用一场“萤火虫科考”贯穿始终,带你零基础看懂 3D 点云处理的完整流程。

岗位关联

点云处理是 3D 视觉的基石技能:自动驾驶目标检测、机器人抓取、数字孪生重建都离不开它。掌握它,你就拿到了进入顶尖 AI 工程师团队的“三维世界通行证”。

目录
  1. 可视化演示
  2. 认识点云:夜空中定格的萤火虫
  3. 点云采样:给星图做减法
  4. 点云滤波:洗去噪点尘埃
  5. 特征提取:给萤火虫量姿态
  6. 点云配准:把零散星图拼成银河
  7. 点云分割:辨认萤火虫家族
  8. 工具与实战:生态学家的工具箱
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

动态演示3D点云处理技术入门的核心机制,通过架构/数据/状态/性能四种模式展示关键概念与交互流程。

本节配有交互动效(进入视口后自动加载,约 3KB)。

3D点云处理技术入门:点云处理 点云处理概述 点云处理原理 核心机制可视化 3D点云处理技术入门整体架构与关键组件

认识点云:夜空中定格的萤火虫

你按下科考相机快门的一瞬间,山谷里的萤火虫全部“定格”了。每一只都被记下位置——就像地图上的经度、纬度加高度。在计算机眼里,每只萤火虫是一个点(point),整幅光点星图就是点云(point cloud)。这幅星图不关心“这是什么虫”,只关心“哪里有光、光在什么位置”。

现实中的点云来自激光雷达、深度相机等传感器。激光雷达发射激光束,碰到物体表面反弹回来,根据光的飞行时间算出距离,从而得到物体表面一个点的三维坐标。一帧扫描下来,成千上万个点汇成一片点云。它天生像一群萤火虫:无序——点与点之间没有先后顺序,谁先谁后都无所谓;稀疏——远处物体表面只有零星几点,近处却密密麻麻。

从数据结构看,一个点的最基本形式是三维坐标 (x, y, z),有些传感器还会附带颜色、反射强度等信息,但坐标永远是“身份证”。常见存储格式有三兄弟:PCD 是 PCL 库的通用格式,PLY 常配合网格用于三维重建,LAS 则是机载激光雷达测绘的行业标准。用数学语言概括:

回到星图本身:我们现在有一大袋不分先后的坐标点。直接处理这么多点会很吃力,下一步先给星图“瘦身”。

pi=(xi, yi, zi)T,P={p1, p2, …, pN}\displaystyle \mathbf{p}_i = (x_i,\ y_i,\ z_i)^{\mathrm{T}}, \qquad P = \{\mathbf{p}_1,\ \mathbf{p}_2,\ \ldots,\ \mathbf{p}_N\}
这段公式是说:点 i 用 x、y、z 三个坐标表示位置;点云 P 就是把所有点装进同一个“袋子”,袋子里不分先后。
  1. 点的坐标第 i 只萤火虫的位置由 x、y、z 三个数值共同决定,就像经度、纬度加高度。
    pi=(xi, yi, zi)T\displaystyle \mathbf{p}_i = (x_i,\ y_i,\ z_i)^{\mathrm{T}}
  2. 点的集合整个点云 P 是把 N 个点全部收进一个集合,集合中元素顺序无所谓,交换任意两点位置不会改变点云。
    P={p1, p2, …, pN}\displaystyle P = \{\mathbf{p}_1,\ \mathbf{p}_2,\ \ldots,\ \mathbf{p}_N\}
  3. 转置记号上标 T 表示把行向量转成列向量,这是数学书写惯例,提醒你坐标是“一个整体”而不是三个独立的数。

点云采样:给星图做减法

山谷里的萤火虫可能有上亿只,逐只清点既不现实也没必要。生态学家的做法是抽选有代表性的样本:只要抓住“哪里密、哪里疏、轮廓长什么样”这几个关键信息就够了。

点云同样如此。一帧 64 线激光雷达点云可达 12 万~20 万点,直接做分割、识别会让算法慢如蜗牛。采样(sampling)的目的,就是在保留几何结构的前提下大幅减少点数。四种常用方法各有性格:随机采样最省事,像抓阄一样随意丢点,速度快但可能破坏密度分布;均匀采样按网格均匀抽点,分布规整;体素采样把空间切成小立方体,每个立方体只留一个“代表点”;最远点采样贪心地挑选彼此距离尽量远的点,保证采样点铺满整个表面,是深度学习中点云网络最常用的预处理手段。

体素采样是工程中的首选,因为它在压缩的同时最大限度保住了密度差异——就像给每个格子里的萤火虫拍一张“集体照”,只留一位代表。它背后的计算朴素得惊人:

瘦身后的星图保住了“哪里密、哪里疏”的轮廓。但照片里还混着路灯的余光、镜头上的灰尘,下一步要把假星光洗掉。

pˉk=1nk∑i=1nkpi\displaystyle \bar{\mathbf{p}}_k = \frac{1}{n_k} \sum_{i=1}^{n_k} \mathbf{p}_i
这就是体素采样的“平均数法则”:每个小方格里的 nk 个点,用一个质心代替,既不偏袒某只萤火虫,又能代表整个方格。
  1. 体素格子把三维空间像切豆腐一样切成等大的小方块,每个方块就是一个体素(Voxel)。
    Lvoxel=格子边长\displaystyle L_{\mathrm{voxel}} = \text{格子边长}
  2. 落格的点第 k 个格子里落进了 nk 个点,它们组成一个局部小集合。
    {p1, p2, …, pnk}\displaystyle \{\mathbf{p}_1,\ \mathbf{p}_2,\ \ldots,\ \mathbf{p}_{n_k}\}
  3. 求质心把所有点坐标逐分量相加,再除以个数 nk,得到平均位置,这就是该格子的代表点。
    pˉk=1nk∑i=1nkpi\displaystyle \bar{\mathbf{p}}_k = \frac{1}{n_k}\sum_{i=1}^{n_k} \mathbf{p}_i

点云滤波:洗去噪点尘埃

山谷里不仅有萤火虫,还有远处路灯的余光、空气里的浮尘、相机感光元件的热噪点。它们混进星图,会让后续的分割和识别张冠李戴。

滤波(filtering)就是星图的“去污”工序。直通滤波(pass-through filter)最直白:按坐标范围切一刀,只保留 x、y、z 落在指定区间内的点,适合快速裁掉背景。半径滤波(radius filter)看局部人气:某个点周围的邻居数少于预设值就删掉,适合清理孤立稀疏的杂点。

统计滤波(statistical filter)则是最高频的“噪点猎手”。它先计算每个点到最近 k 个邻居的平均距离 d_i;再统计所有 d_i 的均值 μ 和标准差 σ。如果某只“萤火虫”与邻居们的平均距离远超整体水平,说明它是离群的外来光点,删除。数学上就是一条阈值判断:

洗干净的星图只剩真正的萤火虫。但光知道“哪里有光”还不够——每只萤火虫面朝哪个方向?局部表面是平坦还是起伏?下一节给光点量姿态。

di>μ+kσ\displaystyle d_i > \mu + k\sigma
这个公式是个“离群判定器”:某只萤火虫离邻居们的平均距离,比整体平均水平高出太多,就判定为混进来的假光点。
  1. 邻居平均距离d_i 表示第 i 个点到它最近 k 个邻居的平均距离,反映它周围是“拥挤”还是“冷清”。
    di=1k∑j=1k∥pi−pij∥2\displaystyle d_i = \frac{1}{k}\sum_{j=1}^{k}\|\mathbf{p}_i - \mathbf{p}_{i_j}\|_2
  2. 全局均值与标准差对所有 d_i 求平均得到 μ,求标准差得到 σ,刻画正常萤火虫的疏密尺度。
    μ=1N∑i=1Ndi,σ=1N∑i=1N(di−μ)2\displaystyle \mu = \frac{1}{N}\sum_{i=1}^{N} d_i, \quad \sigma = \sqrt{\frac{1}{N}\sum_{i=1}^{N}(d_i - \mu)^2}
  3. 阈值判定如果 d_i 大于 μ + kσ,说明该点与同类相差悬殊,标记为噪点并删除。

特征提取:给萤火虫量姿态

生态学家想知道萤火虫群聚成的“光面”如何起伏:是平坦的草地还是起伏的山坡?这需要知道每个局部小区域的“朝向”,就像每片屋瓦都有自己的倾斜方向。

在点云里,这个朝向叫法向量(normal vector)。但点与点之间没有连线,表面是隐形的。办法是问邻居:把某个点最近的 k 个点看作一个局部小平面,这个小平面“抬头”的方向,就是这个点的法向量。更进一步的曲率(curvature)描述表面弯曲程度——球面曲率大,平面曲率趋近于零。

数学上通常用 PCA(主成分分析)估计法向量:先求局部邻居点的协方差矩阵,再做特征分解。三个特征值代表邻域点在三个方向上的散布程度,最小特征值对应的方向就是邻域最“扁”的方向,也就是法向量。此外,FPFH 描述子把局部几何“指纹”编码成固定维度的直方图,关键点检测则挑出几何显著的“地标点”,两者都是配准与识别的好帮手。协方差矩阵长这样:

现在每只萤火虫都有一张“姿态名片”了。不同角度拍摄的星图之间,就能靠这些名片认出同一个位置,实现拼接。

C=1k∑i=1k(pi−pˉ)(pi−pˉ)T\displaystyle \mathbf{C} = \frac{1}{k}\sum_{i=1}^{k}(\mathbf{p}_i - \bar{\mathbf{p}})(\mathbf{p}_i - \bar{\mathbf{p}})^{\mathrm{T}}
协方差矩阵是邻域点的“形状测量仪”:把邻居们相对质心的分布方向记录下来,特征分解后就能读出表面的朝向。
  1. 邻域质心先算出 k 个邻居的中心位置 p̄。
    pˉ=1k∑i=1kpi\displaystyle \bar{\mathbf{p}} = \frac{1}{k}\sum_{i=1}^{k}\mathbf{p}_i
  2. 偏离向量每个点减去质心,得到它相对中心的“偏离量”。
    vi=pi−pˉ\displaystyle \mathbf{v}_i = \mathbf{p}_i - \bar{\mathbf{p}}
  3. 外积求和把偏离向量与自身转置相乘,得到 3×3 矩阵并求和取平均,描述点在三个方向上的散布程度。
    C=1k∑i=1kviviT\displaystyle \mathbf{C} = \frac{1}{k}\sum_{i=1}^{k}\mathbf{v}_i \mathbf{v}_i^{\mathrm{T}}
  4. 特征分解求法向量解特征方程得到三个特征值和特征向量,最小特征值对应的特征向量即法向量。
    Cv=λv,n=vmin⁡\displaystyle \mathbf{C}\mathbf{v} = \lambda \mathbf{v}, \quad \mathbf{n} = \mathbf{v}_{\min}

点云配准:把零散星图拼成银河

山谷太大,一次只能拍下一小块。要得到完整星图,得从多个角度拍摄,再把交叠的部分严丝合缝地拼起来。

配准(registration)就是干这个的。标准流程分两步:粗配准借助 FPFH 特征找到两片点云中相似的“同名点”,估算一个大致的旋转和平移,把两片星图大致摆到一起;精配准则用 ICP(迭代最近点,Iterative Closest Point)算法反复微调,让对应点之间的距离不断缩小,直到严丝合缝。

ICP 的思路像一个固执的拼图匠:每轮迭代,先为源点云的每个点找到目标点云中离它最近的点作为“疑似对应点”,再求解一个旋转矩阵 R 和平移向量 t,使所有对应点对的距离平方平均值最小;然后更新位姿,重新找对应点,循环往复直至收敛。它的目标函数是:

拼好的星图覆盖了整个山谷,但光点还混成一团。最后一步,把星图按“家族”归类,变成结构化的地图。

E(R,t)=1N∑i=1N∥Rpi+t−qi∥22\displaystyle E(\mathbf{R}, \mathbf{t}) = \frac{1}{N} \sum_{i=1}^{N} \left\| \mathbf{R}\mathbf{p}_i + \mathbf{t} - \mathbf{q}_i \right\|_2^2
这是 ICP 的“拼图误差”公式:每对对应点差得越少,E 越小;当 E 足够小时,两片星图就算对齐了。
  1. 源点与目标点p_i 是源点云中的点,q_i 是目标点云中找到的对应点,两者应代表同一物理位置。
    pi↔qi\displaystyle \mathbf{p}_i \leftrightarrow \mathbf{q}_i
  2. 旋转与平移R 是 3×3 旋转矩阵,t 是平移向量;R p_i + t 表示把源点按当前估计翻转、挪动到目标位置。
    pi′=Rpi+t\displaystyle \mathbf{p}_i' = \mathbf{R}\mathbf{p}_i + \mathbf{t}
  3. 距离平方求变换后的点与对应点的欧氏距离再平方,避免正负误差相互抵消。
    ∥Rpi+t−qi∥22\displaystyle \|\mathbf{R}\mathbf{p}_i + \mathbf{t} - \mathbf{q}_i\|_2^2
  4. 取平均最小化对 N 对点求平均,得到总误差 E;优化目标就是让 E 尽量小。

点云分割:辨认萤火虫家族

完整的星图上,萤火虫三三两两聚成家族:草丛上方一群,溪流旁一群;地面则像铺开的绒布,托着所有光点。

分割(segmentation)就是按“家族”把点云拆开。RANSAC 平面分割最擅长处理地面:随机取三个点拟合一个平面方程,统计有多少点支持这个平面,反复迭代选出支持者最多的平面,地面就被分离出来。区域生长(region growing)从种子点出发,把法向量夹角小于阈值、曲率相近的邻居不断并入同一区域,像墨水在宣纸上晕开。聚类分割按欧氏距离把点连成簇,适合分离彼此独立的物体。语义分割则借助深度学习网络,给每个点打上“车、人、树”等类别标签,是自动驾驶感知的主力。

划分离不开平面方程。一个空间平面可以用四个参数描述:

星图终于整理成了“一片地面 + 几簇家族”的结构化地图。这套复杂的手艺需要趁手的工具,最后一节打开生态学家的工具箱。

ax+by+cz+d=0\displaystyle ax + by + cz + d = 0
这是平面家族的“族规”:所有属于同一平面的点,把坐标代入方程后结果都约等于 0;偏离这条规则的光点就不属于这个平面家族。
  1. 平面参数a、b、c 是平面法向量的三个分量,决定平面朝向;d 决定平面到原点的偏移。
    n=(a, b, c)T\displaystyle \mathbf{n} = (a,\ b,\ c)^{\mathrm{T}}
  2. 代入判定平面上任意点 (x, y, z) 满足 ax + by + cz + d = 0,实际计算时允许一个很小的容差。
    ∣ax+by+cz+d∣<ε\displaystyle |ax + by + cz + d| < \varepsilon
  3. RANSAC 循环随机取三个点估计平面,统计多少点支持该平面,反复迭代取支持数最多的平面作为最终地面。

工具与实战:生态学家的工具箱

生态学家不会徒手数萤火虫——强光手电、捕虫网、记录本缺一不可。点云工程师也有三大标配工具。

PCL(Point Cloud Library)是点云界的“元老”,以 C++ 为主,采样、滤波、特征、配准、分割算法几乎全覆盖,工业级项目和 SLAM 系统里到处可见。Open3D 是“后起之秀”,Python 接口优雅,读写、可视化、几何处理几行代码搞定,特别适合快速验证想法和接入深度学习。CloudCompare 则是“鹰眼”:专门用于浏览、比对、编辑点云,检查数据质量、量测尺寸非常方便。

典型工程流程像一条流水线:读取原始点云 → 体素下采样瘦身 → 统计滤波去噪 → RANSAC 分割地面 → 聚类出物体 → 提取法向量 → 配准拼接 → 输出结构化结果。开工前,可以用一个公式快速估算采样后的点数,便于规划内存和算力:

从“给萤火虫拍照”到“输出整张结构化星图”,你已经走完了点云处理的核心旅程。下次看到激光雷达画面时,相信你能认出:这是一群等待被理解的萤火虫。

Nout≈VboxL3\displaystyle N_{\mathrm{out}} \approx \frac{V_{\mathrm{box}}}{L^3}
这个公式用来估算“瘦身效果”:包围盒越大、体素边长越小,保留的点越多;反之点越少。工程上常据此推算内存与计算开销。
  1. 包围盒体积V_box 是点云外接长方体的体积,由 x、y、z 三个方向的最大最小值围成。
    Vbox=(xmax⁡−xmin⁡)(ymax⁡−ymin⁡)(zmax⁡−zmin⁡)\displaystyle V_{\mathrm{box}} = (x_{\max}-x_{\min})(y_{\max}-y_{\min})(z_{\max}-z_{\min})
  2. 体素体积每个小格子的边长是 L,体积是 L³。
    Vvoxel=L3\displaystyle V_{\mathrm{voxel}} = L^3
  3. 相除估算非空格子数约等于两者相除,即采样后的点数上限。

AI 应用场景

自动驾驶地面分割与目标聚类

阶段:环境感知与数据预处理

解决的问题:自动驾驶的激光雷达每帧产出几十万点,直接送进目标识别模型既慢又容易误检。先用体素下采样把点云从 20 万点压到 2 万点,再用统计滤波去掉飞溅噪点,接着用 RANSAC 分割出地面,剩下的点做欧氏聚类,得到一个个独立的障碍物候选框,最后交给检测网络识别车、人、骑行者。

具体案例:某自动驾驶公司在高速场景中,点云经过“采样→滤波→地面分割→聚类”流水线后,障碍物召回率提升 15%,单帧耗时从 120ms 降到 35ms。

三维重建与文物数字化

阶段:多视角融合与建图

解决的问题:手持扫描仪绕文物转一圈,得到几十帧局部点云,需要用 FPFH 特征做粗配准、ICP 做精配准,把多帧点云拼成完整三维模型,再经体素网格重建表面。配准的精度直接决定模型的细节是否清晰。

具体案例:敦煌壁画洞穴数字化项目中,扫描仪每帧约 5 万点,通过配准拼接与简化,生成可在线浏览的高精度彩色点云模型。

机器人抓取位姿估计

阶段:目标识别与抓取规划

解决的问题:机器人需要知道零件在传送带上的位置和朝向。对深度相机点云做直通滤波裁掉背景,统计滤波去噪,再用区域生长分割出单个零件,结合法向量和曲率估计抓取位姿。

具体案例:3C 组装产线上,机械臂依靠点云分割与法向量估计,将杂乱堆叠的螺丝钉逐颗抓取,抓取成功率从 82% 提升到 97%。

Python 演示

python47 行
import numpy as np  def voxel_downsample(points, voxel_size=0.05):    """体素下采样: 将空间切成小方格, 保留每个方格内点的质心."""    if voxel_size <= 0 or len(points) == 0:        return points.copy()    voxel_idx = np.floor(points / voxel_size).astype(np.int64)    _, inverse = np.unique(voxel_idx, axis=0, return_inverse=True)    counts = np.bincount(inverse).astype(np.float64)    centroids = np.zeros((inverse.max() + 1, points.shape[1]))    for dim in range(points.shape[1]):        centroids[:, dim] = np.bincount(inverse, weights=points[:, dim])    return centroids / counts[:, None]  def statistical_filter(points, k=10, m=3.0):    """统计滤波: 剔除与最近 k 个邻居平均距离过大的离群噪点."""    n = len(points)    if n == 0:        return points.copy(), np.zeros(0, dtype=bool)    dists = np.empty(n)    for i in range(n):        d = np.sqrt(((points - points[i]) ** 2).sum(axis=1))        d.sort()        dists[i] = d[1:k + 1].mean()    mu, sigma = dists.mean(), dists.std()    keep = dists <= mu + m * sigma    return points[keep], keep  if __name__ == "__main__":    rng = np.random.default_rng(42)    n = 5000    phi = rng.uniform(0, 2 * np.pi, n)    theta = np.arccos(rng.uniform(-1, 1, n))    r = 1.0 + rng.normal(0, 0.03, n)    pts = np.stack([r * np.sin(theta) * np.cos(phi),                    r * np.sin(theta) * np.sin(phi),                    r * np.cos(theta)], axis=1)    pts = np.vstack([pts, rng.uniform(-3, 3, (100, 3))])     pts_clean, keep = statistical_filter(pts, k=8, m=2.0)    pts_voxel = voxel_downsample(pts_clean, voxel_size=0.1)    print("原始点数:", len(pts))    print("统计滤波后点数:", len(pts_clean))    print("体素下采样后点数:", len(pts_voxel))
目的:模拟一帧带噪点的球面点云,依次执行统计滤波去噪与体素下采样瘦身,输出每一步的点数变化,直观演示正文中的两种核心预处理算法。
  1. voxel_idx = np.floor(points / voxel_size).astype(np.int64)把每个点的坐标除以体素边长并向下取整,得到它所在的格子编号,像给萤火虫按网格分筐。
  2. _, inverse = np.unique(voxel_idx, axis=0, return_inverse=True)找出所有非空格子的唯一编号,返回每个点属于哪个格子的映射。
  3. counts = np.bincount(inverse).astype(np.float64)统计每只“筐”里装了多少只萤火虫。
  4. centroids[:, dim] = np.bincount(inverse, weights=points[:, dim])按格子累加每个维度的坐标和。
  5. return centroids / counts[:, None]除以格内点数得到质心,即体素采样输出的代表点。
  6. d = np.sqrt(((points - points[i]) ** 2).sum(axis=1))计算第 i 个点与其余所有点的欧氏距离,评估它周围“热闹还是冷清”。
  7. d[1:k + 1].mean()跳过自己(距离 0),取最近 k 个邻居的平均距离作为局部疏密指标。
  8. keep = dists <= mu + m * sigma距离超过整体平均的 m 倍标准差,就判定为孤立噪点并剔除。
  9. pts = np.vstack([pts, rng.uniform(-3, 3, (100, 3))])人为加入 100 个远离主体的随机点,模拟混入星图的杂光。

常见误区

误区点云就是一张深度图、一张照片,直接看图就知道物体是什么。

正解点云是一组没有像素排列规则的三维坐标点,天然无序、稀疏;深度图则是规则的二维网格,每个像素存一个距离值。点云可以渲染成图像,但它本身不是图像。处理时必须使用面向点集的方法(如 KNN 邻域),不能像卷积神经网络处理图像那样直接套用。

为何常见:点云可视化后看起来像一张“光点照片”,初学者容易把显示效果和底层数据结构混为一谈。

误区体素下采样就是随机扔掉一些点,反正都是减少点的数量,快就完事了。

正解随机采样确实会丢点,但可能让原本密集的区域变得稀疏,破坏密度分布。体素下采样按空间格子的质心替代整格点,能保持点的密度分布和几何轮廓,是“有策略地精简”而不是“抓阄扔点”。

为何常见:都叫“采样”,随机采样“抽签”的印象太强,掩盖了体素采样的结构化思路。

误区统计滤波的 k 和 m 随便设,效果不好就多滤几遍,总能干净。

正解k 决定“邻居视野”的大小,m 决定判定松紧。k 太小会把正常点当噪点,k 太大会漏掉真正的离群点;m 太大滤不干净,m 太小误伤边缘点。参数必须结合点云密度与噪点比例调试,多滤几遍还可能把薄壁结构(如树叶)整体删掉。

为何常见:滤波看起来只是“删点”,让人误以为参数只是灵敏度旋钮,忽略了它对几何细节的破坏力。

误区法向量是点自带的属性,传感器会直接告诉我们每个点朝哪个方向。

正解大多数点云只含坐标,法向量要从邻居点用 PCA 等方法估计出来,而且方向存在二义性——法向量与负法向量都满足特征方程,还需做方向一致性处理。就像测萤火虫的朝向,得先观察周围同伴的位置才能推断它的“面向”。

为何常见:可视化工具把法向量画得像点自带的小箭头,容易让人误以为它是原始数据的一部分。

误区ICP 是万能的,随便把两片点云丢进去就能严丝合缝地对齐。

正解ICP 是局部优化算法,对初始位姿非常敏感。两片点云初始差距太大时,它容易收敛到错误的局部最优。正确姿势是先用特征匹配做粗配准,把两片星图大致摆正,再用 ICP 精配准。而且它只适用于刚体变换、有足够重叠区域的场景。

为何常见:ICP 名气太大,教程里“一键配准”的演示让人忽略了前置条件。

面试题

Q1. 点云中一个点的最基本属性是什么?

单选题 · easy

  • A.颜色与纹理特征
  • B.三维空间坐标← 正确答案
  • C.时间戳与编号
  • D.物体类别标签

答案:B。点云最基本的属性是 (x, y, z) 三维坐标,就像萤火虫星图上每只萤火虫的经纬度加高度。颜色、时间戳、类别都是可选的附加属性,传感器通常只保证坐标本身。

Q2. 体素下采样中,每个非空体素最终保留的点是?

单选题 · easy

  • A.格子内随机的一点
  • B.格子内所有点的质心← 正确答案
  • C.距离坐标原点最近的点
  • D.距离格子中心最近的点

答案:B。体素下采样保留格内所有点的平均值,即质心,从而在减少点数的同时保持密度分布。随机一点会丢失分布信息,“离原点最近”与格内几何无关,“离中心最近”是另一种策略而非体素方法的默认做法。

Q3. 统计滤波判定一个点为噪点的依据是?

单选题 · mid

  • A.点的颜色与周围差异大
  • B.点与其最近邻居平均距离过大← 正确答案
  • C.点与坐标原点距离超过阈值
  • D.点所在位置的局部密度太高

答案:B。统计滤波先求每个点到最近 k 个邻居的平均距离 d_i,再求全局均值 μ 与标准差 σ,把距离超过 μ + mσ 的点判为离群噪点。A 是颜色准则,C 是直通滤波思路,D 与噪点“孤立稀疏”的特征正好相反。

Q4. 用 PCA 估计法向量时,应该取协方差矩阵的哪个特征向量?

单选题 · hard

  • A.最大特征值对应的特征向量
  • B.中间特征值对应的特征向量
  • C.最小特征值对应的特征向量← 正确答案
  • D.三个特征向量的平均值

答案:C。邻域点分布最“扁”的方向对应最小的特征值,该方向就是表面法向量;最大特征值方向是散布最大的方向,位于切平面内。所以取最小特征值对应的特征向量作法向量。

Q5. ICP 精配准的优化目标是什么?

单选题 · hard

  • A.最大化两片点云的包围盒体积
  • B.最小化所有对应点对距离的平方和← 正确答案
  • C.最小化点云中点的总数量
  • D.最大化两片点云的颜色一致性

答案:B。ICP 每轮迭代寻找最近对应点,求解旋转矩阵 R 和平移向量 t,使所有对应点距离平方的平均值 E 最小,直到收敛。它不优化体积、点数和颜色,只优化几何对齐误差。

Q6. RANSAC 平面分割最典型的应用是?

单选题 · easy

  • A.从点云中分割出地面← 正确答案
  • B.从点云中统计点数
  • C.从点云中提取颜色
  • D.从点云中压缩存储

答案:A。RANSAC 通过随机抽样拟合平面方程,在含噪点云中把地面这类大面积平面稳健地分离出来,是自动驾驶地面分割的经典做法。其余选项都不是 RANSAC 的典型用途。

Q7. 为什么说点云是“无序”数据?

单选题 · mid

  • A.点的坐标是随机生成的
  • B.点没有固定的先后顺序← 正确答案
  • C.点云文件无法顺序存取
  • D.点云只能表示未知物体

答案:B。点云是坐标点的集合,集合内元素天然没有顺序。交换任意两个点的存储位置,点云代表的几何完全不变。这与图像像素有固定行列结构形成鲜明对比,也决定了点云网络需要置换不变性的设计。

Q8. 区域生长分割主要依据哪两个相似性判据?

单选题 · mid

  • A.法向量方向与曲率相近← 正确答案
  • B.颜色深度与时间戳相同
  • C.坐标原点与包围盒相同
  • D.点云格式与文件大小相同

答案:A。区域生长从种子点出发,将法向量夹角小、曲率接近的点不断并入同一区域,从而把表面连续的物体“长”出来。颜色、时间戳、文件属性都不是区域生长的核心判据。

Q9. 关于点云配准,下列说法正确的是?

多选题 · hard

  • A.粗配准为精配准提供初始位姿← 正确答案
  • B.ICP 对初始位姿完全不敏感
  • C.配准求解的是旋转矩阵与平移向量← 正确答案
  • D.配准前无需任何特征信息

答案:AC。粗配准通常借助 FPFH 等特征找到同名点,估算初始位姿,再用 ICP 精配准微调。ICP 是局部优化算法,对初值敏感,所以 B 错;D 错在配准前通常需要特征或几何信息建立对应关系。

Q10. 下列哪些属于常见的点云滤波方法?

多选题 · mid

  • A.统计滤波去除离群点← 正确答案
  • B.直通滤波按范围裁切← 正确答案
  • C.体素下采样精简点数← 正确答案
  • D.快速傅里叶变换

答案:ABC。统计滤波去离群噪点,直通滤波按坐标范围裁切,体素下采样用格内质心精简点数,三者都常用于点云预处理。傅里叶变换是信号处理方法,不直接用于点云滤波。