画像系の最後として、スケルトンを表示してみましょう。
スケルトンの表示方法もBeta2に比べて簡単になっています。
コード
それではコードを見てみましょう。全体のコードはこちらにあります。
XAML
<Window x:Class="SkeletonSample.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Skeleton" Height="521" Width="663"> <Grid> <Image Name="imageRgbCamera" Stretch="Uniform" /> <Image Name="imageDepthCamera" Stretch="Uniform" Opacity="0.7" /> <Canvas Name="canvas1" /> </Grid> </Window>
CS
using System; using System.Windows; using System.Windows.Media; using System.Windows.Shapes; using Coding4Fun.Kinect.Wpf; using Microsoft.Kinect; namespace SkeletonSample { /// <summary> /// MainWindow.xaml の相互作用ロジック /// </summary> public partial class MainWindow : Window { KinectSensor kinect; public MainWindow() { InitializeComponent(); try { if ( KinectSensor.KinectSensors.Count == 0 ) { throw new Exception( "Kinectが接続されていません" ); } // Kinectインスタンスを取得する kinect = KinectSensor.KinectSensors[0]; // すべてのフレーム更新通知をもらう kinect.AllFramesReady += new EventHandler<AllFramesReadyEventArgs>( kinect_AllFramesReady ); // Color,Depth,Skeletonを有効にする kinect.ColorStream.Enable(); kinect.DepthStream.Enable(); kinect.SkeletonStream.Enable(); // Kinectの動作を開始する kinect.Start(); } catch ( Exception ex ) { MessageBox.Show( ex.Message ); Close(); } } // すべてのデータの更新通知を受け取る void kinect_AllFramesReady( object sender, AllFramesReadyEventArgs e ) { imageRgbCamera.Source = e.OpenColorImageFrame().ToBitmapSource(); imageDepthCamera.Source = e.OpenDepthImageFrame().ToBitmapSource(); // 骨格位置の表示 ShowSkeleton( e ); } private void ShowSkeleton( AllFramesReadyEventArgs e ) { // キャンバスをクリアする canvas1.Children.Clear(); // スケルトンフレームを取得する SkeletonFrame skeletonFrame = e.OpenSkeletonFrame(); if ( skeletonFrame != null ) { // スケルトンデータを取得する Skeleton[] skeletonData = new Skeleton[skeletonFrame.SkeletonArrayLength]; skeletonFrame.CopySkeletonDataTo( skeletonData ); // プレーヤーごとのスケルトンを描画する foreach ( var skeleton in skeletonData ) { if ( skeleton.TrackingState == SkeletonTrackingState.Tracked ) { // 骨格を描画する foreach ( Joint joint in skeleton.Joints ) { // 骨格の座標をカラー座標に変換する ColorImagePoint point = kinect.MapSkeletonPointToColor( joint.Position, kinect.ColorStream.Format ); // 円を書く canvas1.Children.Add( new Ellipse() { Margin = new Thickness( point.X, point.Y, 0, 0 ), Fill = new SolidColorBrush( Colors.Black ), Width = 20, Height = 20, } ); } } } } } } }
すこし変えてみました。
フレーム更新イベントをAllFramesReadyを使ってひとまとめにしました。AllFramesReadyはRGB,Depth,Skeletonをまとめて通知してくれるイベントです。
// すべてのフレーム更新通知をもらう kinect.AllFramesReady += new EventHandler<AllFramesReadyEventArgs>( kinect_AllFramesReady );
kinect_AllFramesReadyでは、RGB,Depth,Skeletonをそれぞれ描画します。Skeletonは少し手間なので、メソッドに切り出しました。
// すべてのデータの更新通知を受け取る void kinect_AllFramesReady( object sender, AllFramesReadyEventArgs e ) { imageRgbCamera.Source = e.OpenColorImageFrame().ToBitmapSource(); imageDepthCamera.Source = e.OpenDepthImageFrame().ToBitmapSource(); // 骨格位置の表示 ShowSkeleton( e ); }
スケルトンの描画です。
- 最初にOpenSkeletonFrameを取得します。
- 続いてSkeletonを取得します。Skeletonの数はSkeletonFrame.SkeletonArrayLengthで取得できるので、容量分の配列を確保しSkeletonFrame.CopySkeletonDataToで取得します。
- あとはSkeletonおよびJointで回して描画します。Skeletonの座標をRGBの座標に変換するために、KinectSensor.MapSkeletonPointToColorを使っています。
- KinectSensor.MapSkeletonPointToColorで取得された、SkeletonのRGB座標を利用して、Canvasに円を書いています
private void ShowSkeleton( AllFramesReadyEventArgs e ) { // キャンバスをクリアする canvas1.Children.Clear(); // スケルトンフレームを取得する SkeletonFrame skeletonFrame = e.OpenSkeletonFrame(); if ( skeletonFrame != null ) { // スケルトンデータを取得する Skeleton[] skeletonData = new Skeleton[skeletonFrame.SkeletonArrayLength]; skeletonFrame.CopySkeletonDataTo( skeletonData ); // プレーヤーごとのスケルトンを描画する foreach ( var skeleton in skeletonData ) { if ( skeleton.TrackingState == SkeletonTrackingState.Tracked ) { // 骨格を描画する foreach ( Joint joint in skeleton.Joints ) { // 骨格の座標をカラー座標に変換する ColorImagePoint point = kinect.MapSkeletonPointToColor( joint.Position, kinect.ColorStream.Format ); // 円を書く canvas1.Children.Add( new Ellipse() { Margin = new Thickness( point.X, point.Y, 0, 0 ), Fill = new SolidColorBrush( Colors.Black ), Width = 20, Height = 20, } ); } } } } }
このようにBeta2とそれほど変わらずに、すこし簡単になっているスケルトンでした。