Kinect for Windows SDK 入門4:骨格トラッキングと3D表示

objective

  • 未だに骨格追跡の機能を使ったことがなかったので、使ってみた。
  • OpenGLを使って3Dデータに骨格をかぶせてみたりする

骨格トラッキングを使う

  • 基本的に他と同様、まずはWPFで作ったwindowのWindow_Loadedの外側に、以下を
Runtime nui = new Runtime();
  • そして、Window_Loadedイベント内でランタイムの初期化のパラメーターに、骨格データを扱うためのRuntimeOptions.UseSkeletalTrackingを追加し、SkeletonFrameReadyに登録
  • また、TransformSmoothParametersを使うことによって、骨格エンジンの細かい揺らぎを減少させることができる。
nui.Initialize(RuntimeOptions.UseSkeletalTracking);

nui.SkeletonEngine.TransformSmooth = true;
var parameters = new TransformSmoothParameters
{
    Smoothing = 0.75f,
    Correction = 0.0f,
    Prediction = 0.0f,
    JitterRadius = 0.05f,
    MaxDeviationRadius = 0.04f
};
nui.SkeletonEngine.SmoothParameters = parameters;

nui.SkeletonFrameReady += new EventHandler<SkeletonFrameReadyEventArgs>(nui_SkeletonFrameReady);
void nui_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
{
	//to be implemented
}

UI

  • UIのXAMLには、キャンバス上に、追跡された関節を表すためのellipseを追加
<Canvas Name="MainCanvas">
    <Ellipse Canvas.Left="0" Canvas.Top="0" Height="50" Name="headEllipse" Stroke="Black" Width="50" Fill="Orange" />
    <Ellipse Canvas.Left="50" Canvas.Top="0" Height="50" Name="rightEllipse" Stroke="Black" Width="50" Fill="SlateGray" />
    <Ellipse Canvas.Left="100" Canvas.Top="0" Fill="SpringGreen" Height="50" Name="leftEllipse" Stroke="Black" Width="50" />
</Canvas>

追跡された骨格の取得

  • 以下のようなLINQクエリで、捕捉した骨格を取得する。
void nui_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
{
    SkeletonFrame allSkeletons = e.SkeletonFrame;
 
    //最初に捕捉した骨格を取得
    SkeletonData skeleton = (from s in allSkeletons.Skeletons
                             where s.TrackingState == SkeletonTrackingState.Tracked
                             select s).FirstOrDefault();
}

関節の座標を得る

  • 指定した関節毎の、xyz座標は、それぞれ以下のように表現される
    • X = 水平方向に –1 から +1 の間で
    • Y = 垂直方向に –1 から +1 の間で
    • Z = kinectからのメートル距離
  • これらのXYの値は、(specific joint).ScaleTo(x pixel, y pixel)とすることでスケールしなおせる
    • よって今回は、nui_SkeletonFrameReadyより、表示したいそれぞれのjointを新しく作る関数SetEllipsePositionに送ることによって、320x240にスケールし直し、window上のそれぞれのellipseを動かす
private void SetEllipsePosition(FrameworkElement ellipse, Joint joint)
{
    var scaledJoint = joint.ScaleTo(320, 240);
    Canvas.SetLeft(ellipse, scaledJoint.Position.X);
    Canvas.SetTop(ellipse, scaledJoint.Position.Y);
}
  • そしてnui_SkeletonFrameReady内より表示したい関節を送る
SetEllipsePosition(ellipseHead, skeleton.Joints[JointID.Head]);
SetEllipsePosition(ellipseHead, skeleton.Joints[JointID.ShoulderCenter]);
...


イメージに重ねる


OpenGLで描写

  • 違う角度から