読者です 読者をやめる 読者になる 読者になる

Natural Software

KinectなどのDepthセンサーを中心に活動しています

Kinect for Windows SDK beta で遊んでみた 〜 Kinect Toolkitでジェスチャーを検出する 〜 #shibuya_ni

Kinect

MS Kinect SDKはこれまでのOpenNI相当で、ジェスチャーを検出するNITE相当の機能はありませんでした。
それを解消するライブラリが先日リリースされたようなので少し触ってみました。実はWPFをまともに触るのは初めてなのですが、先日のWindowsPhoneのセミナーで少し触ったので、なんとかなりましたw

参考

調べてる過程で、Kinect.Toolkitのサンプルアプリ集のサイトを見つけました(フランスのMS?)。ただしToolkitのバージョンが古いようで、Codeprexで配布されているライブラリとは若干インタフェースが違うようです
Kinect pour Windows SDK - Démos
その中からいくつかやってみました

必要な環境

これは何?

Kinect.ToolkitはC#(WPF+XNA)のライブラリで以下の機能があるようです

  • SwipeGestureDetectorによるスワイプの検出(手の左右移動)
    1. SwipeToLeft(左に移動)
    2. SwipeToRight(右に移動)
  • TemplateGestureDetectorによるテンプレートジェスチャーの検出(主に円)
  • PostureDetectorによるポーズの検出
    1. None(ポーズなし)
    2. HandsJoined(両手を合わせた?)
    3. LeftHandOverHead(左手が頭の上)
    4. RightHandOverHead(右手が頭の上)
    5. LeftHello(左手でこんにちは)
    6. RightHello(右手でこんにちは)
  • SkeletonDisplayManagerやGestureDetectorsによる描画のサポート
  • ColorStreamManagerやDepthStreamManagerによる描画のサポート
  • ケルトンの記録と再生
  • BindableNUICameraによるチルトのデータバインディングサポート

サンプルソース


サンプルなど参考に、こんなのを作ってみました。ただし、ポーズの検出はできますが、ジェスチャーの検出が難しくて1回しかできてません

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Research.Kinect.Nui;
using Kinect.Toolkit;
using System.Diagnostics;

namespace kinect_toolkit
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        Runtime kinectRuntime;
        readonly ColorStreamManager colorStreamManager = new ColorStreamManager();          // カメラ画像の描画サポート
        readonly GestureDetector rightHandGestureRecognizer = new SwipeGestureDetector();   // ジェスチャーの検出器
        readonly BarycenterHelper barycenterHelper = new BarycenterHelper(30);              // 重心
        readonly PostureDetector postureRecognizer = new PostureDetector();                 // ポーズの検出器

        SkeletonDisplayManager skeletonDisplayManager;                                      // ジェスチャーの描画サポート


        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            // Init Kinect
            try
            {
                kinectRuntime = new Runtime();
                kinectRuntime.Initialize(RuntimeOptions.UseDepthAndPlayerIndex | RuntimeOptions.UseSkeletalTracking | RuntimeOptions.UseColor);
                kinectRuntime.VideoStream.Open(ImageStreamType.Video, 2, ImageResolution.Resolution640x480, ImageType.Color);
                kinectRuntime.DepthStream.Open(ImageStreamType.Depth, 2, ImageResolution.Resolution320x240, ImageType.DepthAndPlayerIndex);

                kinectRuntime.SkeletonFrameReady += kinectRuntime_SkeletonFrameReady;
                kinectRuntime.VideoFrameReady += kinectRuntime_ColorFrameReady;

                kinectRuntime.SkeletonEngine.TransformSmooth = true;

                var parameters = new TransformSmoothParameters
                {
                    Smoothing = 0.7f,
                    Correction = 0.3f,
                    Prediction = 0.4f,
                    JitterRadius = 1.0f,
                    MaxDeviationRadius = 0.5f
                };
                kinectRuntime.SkeletonEngine.SmoothParameters = parameters;

                skeletonDisplayManager = new SkeletonDisplayManager(kinectRuntime.SkeletonEngine, skeletonCanvas);

                // Events
                rightHandGestureRecognizer.OnGestureDetected += rightHandGestureRecognizer_OnGestureDetected;
            }
            catch(Exception ex )
            {
                MessageBox.Show(ex.Message);
                Close();
                kinectRuntime = null;
            }
        }

        void rightHandGestureRecognizer_OnGestureDetected(SupportedGesture gesture)
        {
            switch (gesture)
            {
                case SupportedGesture.SwipeToLeft:
                    Gesture.Content = "GestureDetected:SwipeToLeft";
                    break;
                case SupportedGesture.SwipeToRight:
                    Gesture.Content = "GestureDetected:SwipeToRight";
                    break;
            }
        }

        void kinectRuntime_ColorFrameReady(object sender, ImageFrameReadyEventArgs e)
        {
            // カメラ画像の描画
            ColorImage.Source = colorStreamManager.Update(e);
        }

        void kinectRuntime_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
        {
            SkeletonFrame skeletonFrame = e.SkeletonFrame;

            foreach (SkeletonData data in skeletonFrame.Skeletons)
            {
                if (data.TrackingState != SkeletonTrackingState.Tracked)
                    continue;

                barycenterHelper.Add(data.Position.ToVector3(),data.TrackingID);
                if (!barycenterHelper.IsStable(data.TrackingID))
                    continue;

                foreach (Joint joint in data.Joints)
                {
                    if (joint.Position.W < 0.8f || joint.TrackingState != JointTrackingState.Tracked)
                        continue;

                    if (joint.ID == JointID.HandRight)
                    {
                        rightHandGestureRecognizer.Add(joint.Position, kinectRuntime.SkeletonEngine);
                        Trace.WriteLine(Gesture.Content = "HandRight.Add");
                    }
                }

                // ポーズの検出
                postureRecognizer.TrackPostures(data);
            }

            // スケルトンの描画
            skeletonDisplayManager.Draw(e.SkeletonFrame);

            labelPose.Content = "Pose: " + postureRecognizer.CurrentPosture.ToString();
        }
    }
}