Floor Determination -Kinect for Windows SDK beta-

| コメント(0) | トラックバック(0) このエントリーを含むはてなブックマーク

さて秋も深まり一層寒くなってきました。 これだけ寒いと、運動したくなるという事で、Kinectを使って運動しましょう。

【送料無料】Kinect スポーツ

【送料無料】Kinect スポーツ
価格:4,998円(税込、送料別)

運動と言えば、なでしこジャパンなど、サッカー。 拡張現実を使って、サッカーフィールドを再現してみるとか思うのも一つかと思います。

さて、今回は Kinect for Windows SDK beta を題材です。いままでは OpenNI でしたが やっぱり マイクロソフトさんということで、Kinect for Windows SDK beta に取り組みます。

Kinect for Windows SDK beta に関しては、記事を書いているので Kinect for Windows SDK(ベータ版)開発入門 を参考にしてください。

床面について

さて、アバターをだして、サッカーをするのはいいんだけど、奥行きや骨格情報は 先ほどの記事から大体わかる。しかし、床面を推定するとなると、厄介だとおもう。

Kinect for Windows SDK beta は Floor Determinationをする為のパラメータがあり それを取得すると簡単にできそうと考えました。

Programming Guide: Getting Started with the Kinect for Windows SDK Beta

によれば、以下の方程式が成り立てば、そこは床面と推定できるようで、それをつかいます。

The general plane equation is:

Ax + By + Cz + D = 0

where:

A = vFloorClipPlane.x

B = vFloorClipPlane.y

C = vFloorClipPlane.z

D = vFloorClipPlane.w

つまり、ベクトル(x,y,z) と FloorClipPlane(x,y,z) の 内積が -D であれば そのベクトル(x,y,z)は床面と断定できると。

式の変形

「Ax + By + Cz + D = 0」から、床面ベクトル(x,y,z)を求める事を考えると... 例えば次のような事が考えられる。

例えば、人間の頭部分、つまり JointID.Head にある床面がどこか? というと、頭のあるベクトルの X,Zを元にしたベクトルと、FloorClipPlaneの 内積が -D になるような場所を探せばOK。

つまり

「 y = -(Ax + Cz + D) / ( B ) 」

x: data[JointID.Head].Position.X

z: data[JointID.Head].Position.Z

で計算出来るハズと考えた。

//Joint data via e.SkeletonFrame.Skeltons
var x = data[JointID.Head].Position.X
var z = data[JointID.Head].Position.Z
var y = -(FloorClipPlane.X * x + FloorClipPlane.Z * z + FloorClipPlane.W) 
			/ FloorClipPlane.Y;
 
 

つまり上記で、床面ベクトルが分かるハズと。

ちなみに、上記床面ベクトルは、骨格情報の座標系なので、画像への対応が必要です。

よって以下の方法で、画像空間へマッピングします。

var v = new Vector();
v.X = (float)x;
v.Y = (float)y;
v.Z = (float)z;

float depthX, depthY;
nui.SkeletonEngine.SkeletonToDepthImage(v, out depthX, out depthY);

depthX = Math.Max(0, Math.Min(depthX * 320, 320));  //convert to 320, 240 space
depthY = Math.Max(0, Math.Min(depthY * 240, 240));  //convert to 320, 240 space

int colorX, colorY;
ImageViewArea iv = new ImageViewArea();
nui.NuiCamera.GetColorPixelCoordinatesFromDepthPixel(ImageResolution.Resolution640x480, iv, (int)depthX, (int)depthY, (short)0, out colorX, out colorY);

var p = new Point((int)(pictureBox2.Image.Width * colorX / 640.0), (int)(pictureBox2.Image.Height * colorY / 480));
 
 

例えば、上記で pictureBox2 に表示されている画像に表示されている人の頭の直下にある床面座標が とれるでしょう。

試しに上記座標に点を表示してみると、確かに頭の下の床面部分に点が表示されます。

まとめ

FloorClipPlaneがあるので、床面の推定ができます。ただ、画像上の任意の点が床面かどうかを どのように推定すべきかは、一工夫必要そうです。

【送料無料】Xbox360 Kinect センサー

【送料無料】Xbox360 Kinect センサー
価格:12,283円(税込、送料別)

トラックバック(0)

トラックバックURL: http://www.m-tea.info/mt-tb.cgi/95

コメントする

あわせて読みたいブログパーツ

このブログ記事について

このページは、k1ha410が2011年9月20日 14:31に書いたブログ記事です。

ひとつ前のブログ記事は「「モテるプログラミング女子力を磨くための4つの心得」」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。