Obvious,最小特征值对应的特征向量为平面的法向
这个问题还有个关键是通过python求协方差矩阵的特征值和特征向量,np.linalg.eig()方法直接返回了特征值的向量和特征向量的矩阵
scipy.linalg.eigh()方法可以对返回的特征值和特征向量进行控制,通过eigvals参数,可以控制,比如我要返回最小的特征值,和其对应的特征向量,那么就是eigvals(0:0),在升序的情况下。还是很有用的。
scipy.linalg.
eigh
(a, b=None, lower=True, eigvals_only=False, overwrite_a=False, overwrite_b=False, turbo=True, eigvals=None, type=1, check_finite=True)
@author: Bambo """ import numpy as np import scipy x=[random.randint(0,100) for i in range(40)] y=[random.randint(0,100) for i in range(40)] z=[a*3+b*2+1 for a,b in zip(x,y)] r=map(list,zip(x,y,z)) k=mat(r) re=k.T*k e,v=scipy.linalg.eigh(re,turbo=False,eigvals=(0,0)) #e,v=scipy.linalg.eigh(re,eigvals=(a,b)) print e print v
下面这段代码是当有两个平面时,通过协方差矩阵的奇异值分解,求两个平面的法向,测试显示结果是正确的。
会有人问为啥你知道了平面的法向还通过奇异值分解又求了一次,为了科研。
# -*- coding: utf-8 -*- """ Created on Sun Nov 05 19:37:26 2017 @author: Bambo """ import numpy as np import scipy #随机生成平面一上的点 x1=[np.random.randint(0,100) for i in range(400)] y1=[np.random.randint(0,100) for i in range(400)] z1=[a*3+b*2+1 for a,b in zip(x1,y1)] #随机生成平面二上的点 x2=[np.random.randint(0,100) for i in range(400)] y2=[np.random.randint(0,100) for i in range(400)] z2=[c*3+d*2+5 for c,d in zip(x2,y2)] x1c=np.mean(x1) y1c=np.mean(y1) z1c=np.mean(z1) x2c=np.mean(x2) y2c=np.mean(y2) z2c=np.mean(z2) xc=(x1c+x2c)/2 yc=(y1c+y2c)/2 zc=(z1c+z2c)/2 #扩充成为两个平面的点 x1[len(x1):len(x1)]=x2 y1[len(y1):len(y1)]=y2 z1[len(z1):len(z1)]=z2 x=[(x1[i]-xc) for i in range(len(x1))] y=[(y1[j]-yc) for j in range(len(y1))] z=[(z1[p]-zc) for p in range(len(z1))] print x print y print z r=map(list,zip(x,y,z)) k=np.mat(r) re=k.T*k #求最小特征值对应的特征向量 e,v=scipy.linalg.eigh(re,turbo=False,eigvals=(0,2)) #e,v=scipy.linalg.eigh(re,eigvals=(a,b)) print e print v