1、背景介绍
将三维空间中位于任意平面上的点云数据,通过一系列的坐标变换(平移+旋转),使其投影到与XOY平面平行,同时点云形状保持不变。具体效果如下,对于原始点集(蓝色点集),对其进行平移+旋转处理后,得到新的点云(红色点云),该点云与水平面平行,同时保持与原始点云形状相同。
三维空间动图 | 前视图(红色点云水平) |
为什么要将点云旋转,将其与水平面平行,这样做的好处体现在以下几方面:
- 数据简化:将三维问题简化为二维问题,便于后续处理,如数据分析、可视化、特征提取等。
- 算法适用性:某些算法可能在二维平面上表现得更好或更高效,投影可以使得这类算法得以应用。
- 几何一致性:确保所有点云数据在同一参考平面上,便于比较和处理。
2、点云旋转投影流程与原理
2.1 流程介绍
一般来说,点云旋转投影至水平面,包括如下步骤:
- 中心化点云:首先计算点云的几何中心,然后将点云相对于其几何中心平移,使中心点与全局坐标系的原点重合。
- 确定平面法向量:找出点云所在平面的法向量,这是点云所在平面垂直于三维空间的方向。
- 旋转对齐:根据平面法向量与Z轴的偏差,构造旋转矩阵,旋转点云使之与XOY平面平行或重合。目的是消除Z坐标的影响,使所有点落在XOY平面上。
- 投影:完成旋转后,可以安全地忽略所有点的Z坐标,只保留X和Y坐标,从而将点云投影到XOY平面上。
上述四个步骤中,其实最为核心的步骤是求解旋转矩阵,本文介绍基于罗德里格旋转公式方法求解旋转矩阵。
2.2 推导过程
假设待旋转的点云集,其拟合平面对应的法向量为vectorBefore(x1,y1,z1),经过旋转处理后,最终要得到的平面法向量为 vectorAfter(x2,y2,z2),将这两个向量转为单位向量。
得到 va = normalize(vectorBefore), vb = normalize(vectorAfter)
② vs = vb × va, 叉乘得到旋转轴vs
③ v = normalize(vs), vs转为单位向量得到v
④ ca = vb · va, 点乘得到旋转角的余弦值 ca, 即cos(angle)
⑤ vt = v * scale, 对v进行缩放,方便后面计算, scale = 1 - ca
⑥ 旋转矩阵rm为 [3,3]矩阵, 计算原理为罗德里格旋转公式(Rodrigues' rotation formula)
rm[0,0] = vt.x * v.x + ca
rm[1,1] = vt.y * v.y + ca
rm[2,2] = vt.z * v.z + ca
vt.x *= v.y
vt.z *= v.x
vt.y *= v.z
rm[0,1] = vt.x - vs.z
rm[0,2] = vt.z - vs.y
rm[1,0] = vt.x - vs.z
rm[1,2] = vt.y - vs.x
rm[2,0] = vt.z - vs.y
rm[2,1] = vt.y - vs.x
3、测试与结果
本程序基于python、pycharm编写的源代码,下载链接:https://download.csdn.net/download/qq_32867925/89595152
3.1 随机平面点集测试
随机生成10000个位于同一平面点集,在本次测试中,假设平面方程为x+y-z-5=0。该平面不平行于xoy平面,与xoy平面存在明显的夹角。
numpt = 10000
points = []
for _ in range(numpt):
x = random.randint(0, 500)
y = random.randint(0, 500)
z = 1 * x + 1 * y - 5 # 假设平面方程类型 x+y-z-5=0
points.append(np.array([x, y, z]))
对该点云进行旋转平移后,效果如下,其中蓝色点为未旋转前点集,位于平面x+y-z-5=0上。经过旋转平移后,为红色点集,从三维动图和前视图可见,红色点是平行于xoy平面,证明旋转正确,旋转后法向量近似为(0,0,1)。
三维空间动图 | 前视图(红色点云水平) |
3.2 竖直平面点集测试
对10000x+y+z-5=0平面上点集,进行旋转。蓝色点集为未旋转前,该点集所在平面近似平行于yoz平面。那么经过旋转平移后点集,应该平行于xoy。红色点集为旋转后点集,可以发现其平行于xoy,且与蓝色点集垂直,证明旋转正确。旋转后法向量为(0,0,1)。
三维空间动图 | 前视图(红色点云水平) |