使用PCA 计算点云平面法向量,并旋转至二维XoY坐标系
2017-12-24 19:33
465 查看
PCA对点云平面处理后,返回三个特征向量,分别是平面自身坐标系的X轴,Y轴和Z轴在点云全局坐标系中的向量。其中Z轴信息最少,就是平面的法向量。要想把点云从全局坐标系下转化到XoY的二维平面,只需把点按照旋转矩阵R变换后,PCA返回的三个向量就组成了3X3的旋转矩阵R。
换句话说,PCA对平面点云的变换,就是把点转换到三个特征向量组成的新的XYZ坐标系下,新坐标系的原点和全局原点是相同的。
首先import相关库:
平面方程为 aX + bY + cZ + d = 0
下面我们自己随机生成一个平面的4个参数(3维法向量[a,b,c]和平面离原点的距离d),并生成1000点:
下面调用上面的函数,生成平面点和参数model,其中红色的就是随机生成的法向量:
接下来我们用PCA分析出3个特征向量(pca.components_), 并打印旋转后的平面点
那pca.fit_transform(data)这样的PCA变换具体做的什么事情呢,它就是把所有点旋转到pca.components_[0]和pca.components_[1]组成的坐标平面,然后把原点移动到点云的中心点。下面我们验证一下:
换句话说,PCA对平面点云的变换,就是把点转换到三个特征向量组成的新的XYZ坐标系下,新坐标系的原点和全局原点是相同的。
首先import相关库:
from sklearn.decomposition import PCA from sklearn import preprocessing import numpy as np
平面方程为 aX + bY + cZ + d = 0
下面我们自己随机生成一个平面的4个参数(3维法向量[a,b,c]和平面离原点的距离d),并生成1000点:
def create_plain_data(): model = np.random.randint(1,100,4).astype('float64') model[:3] = preprocessing.normalize(np.array([model[:3]]), norm='l2') x_range = (100,110) y_range = (1000, 1010) data = np.zeros((1000,3), dtype='float64') data[:,0] = np.random.randint(x_range[0],x_range[1],data.shape[0]) data[:,1] = np.random.randint(y_range[0],y_range[1],data.shape[0]) data[:,2] = -( data[:,0] * model[0] + data[:,1] * model[1] + model[3] ) / model[2] return model, data
下面调用上面的函数,生成平面点和参数model,其中红色的就是随机生成的法向量:
if __name__ == '__main__': model, data = create_plain_data() print "model: ", model print "data:" print data > model: [ 0.59223344 0.41456341 0.69093902 92. ] data: [[ 103. 1007. -825.63784149] [ 101. 1004. -822.12355578] [ 107. 1001. -825.46641292] ..., [ 107. 1007. -829.06641292] [ 108. 1004. -828.12355578] [ 109. 1006. -830.18069863]]
接下来我们用PCA分析出3个特征向量(pca.components_), 并打印旋转后的平面点
pca = PCA(n_components=3) pca.fit(data) print "variance_ratio: ", pca.explained_variance_ratio_ print "components_", pca.components_ print "Transformed points in 3 components' coordinate" print pca.fit_transform(data) > variance_ratio: [ 6.84766389e-01 3.15233611e-01 1.19653080e-26] components_ [[ 0.55240657 0.4153701 -0.7227134 ] [ 0.58660594 -0.8096943 -0.01698851] [-0.59223344 -0.41456341 -0.69093902]] Transformed points in 3 components' coordinate [[ 6.16324398e-01 -2.80846397e+00 6.11165344e-13] [ -4.27442042e+00 -1.61229542e+00 6.22402823e-13] [ 2.09836384e-01 4.39321328e+00 4.99872091e-13] ..., [ 5.30382521e+00 -4.03793897e-01 5.06568841e-13] [ 3.92870600e+00 2.59587721e+00 6.45553024e-13] [ 6.79857748e+00 1.59804234e+00 4.62417997e-13]]可以看到最后一个特征向量的信息量(variance_ratio[2])非常少1.19653080e-26,说明点的坐标在这个特征向量的方向上计划是没有区分度的,所以它pca.components_[2]就是点平面的法向量。我们对比前面的model输出(红色的)发现它们的确是相等的。而且,转换后点的Z值都为0.
那pca.fit_transform(data)这样的PCA变换具体做的什么事情呢,它就是把所有点旋转到pca.components_[0]和pca.components_[1]组成的坐标平面,然后把原点移动到点云的中心点。下面我们验证一下:
rotated_data = np.dot(data, pca.components_.T) mean_data = rotated_data - np.mean(rotated_data, axis=0) print "manual transformed ponts" print mean_data > manual transformed ponts [[ 6.16324398e-01 -2.80846397e+00 -4.68958206e-13] [ -4.27442042e+00 -1.61229542e+00 -5.68434189e-13] [ 2.09836384e-01 4.39321328e+00 -5.96855898e-13] ..., [ 5.30382521e+00 -4.03793897e-01 -6.25277607e-13] [ 3.92870600e+00 2.59587721e+00 -4.68958206e-13] [ 6.79857748e+00 1.59804234e+00 -6.53699317e-13]]对比上下两组蓝色数据,的确是一样的。
相关文章推荐
- 使用向量的方法来计算点到直线的距离
- HDU 3692 Shade of Hallelujah Mountain (计算几何,三维空间点的旋转,二维凸包)
- 用抽象类设计计算二维平面图形面积的程序,在基类TDshape中设计纯虚函数area()和printName()......C++的158页5题
- 游戏开发之二维向量角度计算
- poj 2957 计算几何向量的旋转
- 同一坐标系中,由任意两点计算地图旋转角度
- [转]开源Math.NET基础数学类库使用(02)矩阵向量计算
- POJ 2079 Triangle(旋转卡壳计算平面点集最大三角形面积)
- C++链接库的使用,二维向量,三维向量,Ubuntu下C++测试向量库
- 【Unity3D】计算二维向量夹角(-180到180)
- Eigen库使用教程之旋转矩阵,旋转向量和四元数的初始化和相互转换的实现
- 设 P(x,y,z)是所求平面上任一点,则向量 AB=(-3,0,1),AP=(x-3,y,z), 因此平面的法向量为 n1=AB×AP=(-y,x+3z-3,-3y), 而 xoy 坐标面的法向量为
- 使用SIFT描述子计算模板旋转角度
- POJ2991_Crane_计算几何::向量化|向量旋转公式||线段树维护向量和
- poj 2194 Stacking Cylinders 计算几何之向量旋转
- BZOJ-2829信用卡凸包 凸包+向量旋转计算
- 使用向量的方法计算点到直线的距离
- 二维向量旋转公式
- 【BZOJ3707】圈地 计算几何 旋转坐标系
- 为任意网格计算切空间坐标系向量