空飛ぶロボットのつくりかた

ロボットをつくるために必要な技術をまとめます。ロボットの未来についても考えたりします。

主成分分析のお勉強

やりたいこと

三次元点群に最もフィットする主軸を導出したい!

教科書

実装コード

#coding:utf-8
import numpy
from sklearn.decomposition import PCA

N = 20
t = numpy.random.rand(N)
x = t+numpy.random.rand(N)*0.3
y = t+numpy.random.rand(N)*0.3
z = t+numpy.random.rand(N)*0.3

pca_o = PCA(n_components=3)
pca_o.fit(zip(x,y,z))
pca = pca_o.components_

v  = []
mx = numpy.mean(x)
my = numpy.mean(y)
mz = numpy.mean(z)

for tx,ty,tz in zip(x,y,z):
    ax,ay,az = numpy.dot(pca,[(tx-mx),(ty-my),(tz-mz)])
    v.append( dict(ax=ax,ay=ay,az=az,x=tx,y=ty,z=tz) )

maxx = max(v,key=lambda x:x['ax'])
minx = min(v,key=lambda x:x['ax'])
maxy = max(v,key=lambda x:x['ay'])
miny = min(v,key=lambda x:x['ay'])
maxz = max(v,key=lambda x:x['az'])
minz = min(v,key=lambda x:x['az'])

#グラフ描画
from matplotlib.pyplot import *
from mpl_toolkits.mplot3d import Axes3D

fig = figure()
ax = Axes3D(fig)
ax.scatter3D(x,y,z)

# 表示範囲の設定
ax.set_xlim(0, 1.5)
ax.set_ylim(0, 1.5)
ax.set_zlim(0, 1.5)

#基底ベクトルの描画
v1x,v1y,v1z = pca[0]
ax.plot([mx+v1x,mx-v1x],[my+v1y,my-v1y],[mz+v1z,mz-v1z])
v2x,v2y,v2z = pca[1]
ax.plot([mx+v2x,mx-v2x],[my+v2y,my-v2y],[mz+v2z,mz-v2z])
v3x,v3y,v3z = pca[2]
ax.plot([mx+v3x,mx-v3x],[my+v3y,my-v3y],[mz+v3z,mz-v3z])

ax.plot([maxx['x']], [maxx['y']], [maxx['z']], "*", color="b", ms=10, mew=0.5)
ax.plot([minx['x']], [minx['y']], [minx['z']], "*", color="b", ms=10, mew=0.5)
ax.plot([maxy['x']], [maxy['y']], [maxy['z']], "*", color="r", ms=10, mew=0.5)
ax.plot([miny['x']], [miny['y']], [miny['z']], "*", color="r", ms=10, mew=0.5)
ax.plot([maxz['x']], [maxz['y']], [maxz['z']], "*", color="g", ms=10, mew=0.5)
ax.plot([minz['x']], [minz['y']], [minz['z']], "*", color="g", ms=10, mew=0.5)

show()

f:id:robonchu:20180401195542p:plain

ブルーの線が主軸です!

☆がそれぞれの軸での最大・最小の点!!

これを使って何をするかはお楽しみ♪