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)
{
}
UI
- UIのXAMLには、キャンバス上に、追跡された関節を表すためのellipseを追加
<Canvas Name="MainCanvas">
<Ellipse CanvasLeft="0" CanvasTop="0" Height="50" Name="headEllipse" Stroke="Black" Width="50" Fill="Orange" />
<Ellipse CanvasLeft="50" CanvasTop="0" Height="50" Name="rightEllipse" Stroke="Black" Width="50" Fill="SlateGray" />
<Ellipse CanvasLeft="100" CanvasTop="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で描写