PCA对点云平面处理后,返回三个特征向量,分别是平面自身坐标系的X轴,Y轴和Z轴在点云全局坐标系中的向量。其中Z轴信息最少,就是平面的法向量。要想把点云从全局坐标系下转化到XoY的二维平面,只需把点按照旋转矩阵R变换后,PCA返回的三个向量就组成了3X3的旋转矩阵R。
换句话说,PCA对平面点云的变换,就是把点转换到三个特征向量组成的新的XYZ坐标系下,新坐标系的原点和全局原点是相同的。
首先import相关库:
from sklearn.decomposition import PCAfrom sklearn import preprocessingimport 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
接下来我们用PCA分析出3个特征向量(pca.components_), 并打印旋转后的平面点
那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]]对比上下两组蓝色数据,的确是一样的。