C#Kinect骨架跟踪

时间:2012-12-03 21:56:43

标签: c# kinect

使用SDK v1.5和VS2012,我在使用Kinect For Windows正常运行骨架跟踪方面遇到了一些麻烦。我正在构建来自https://github.com/EvilClosetMonkey/Fizbin.Kinect.Gestures的源代码,但是当屏幕上有多个人时,跟踪会完全误入歧途。我接着看了这里的代码(http://social.msdn.microsoft.com/Forums/en-US/kinectsdknuiapi/thread/459012d7-d51e-460d-aa6a-a1b80c27626c/),我试图整合“AppChoosesSkeletons”功能(下面的代码):

using System.Windows;
using System.Windows.Data;
using Microsoft.Kinect;
using Microsoft.Kinect.Toolkit;
using Microsoft.Samples.Kinect.WpfViewers;
using System.Diagnostics;
using System.ComponentModel;
using System.Linq;
using System;

namespace Fizbin.Kinect.Gestures.Demo
{
public partial class MainWindow : Window, INotifyPropertyChanged
{
    private readonly KinectSensorChooser sensorChooser = new KinectSensorChooser();

    private Skeleton[] skeletons = new Skeleton[0];

    // skeleton gesture recognizer
    private GestureController gestureController;

    public MainWindow()
    {
        DataContext = this;

        InitializeComponent();

        // initialize the Kinect sensor manager
        KinectSensorManager = new KinectSensorManager();
        KinectSensorManager.KinectSensorChanged += this.KinectSensorChanged;

        // locate an available sensor
        sensorChooser.Start();

        // bind chooser's sensor value to the local sensor manager
        var kinectSensorBinding = new Binding("Kinect") { Source = this.sensorChooser };
        BindingOperations.SetBinding(this.KinectSensorManager, KinectSensorManager.KinectSensorProperty, kinectSensorBinding);
    }

    #region Kinect Discovery & Setup

    private void KinectSensorChanged(object sender, KinectSensorManagerEventArgs<KinectSensor> args)
    {
        if (null != args.OldValue)
            UninitializeKinectServices(args.OldValue);

        if (null != args.NewValue)
            InitializeKinectServices(KinectSensorManager, args.NewValue);
    }

    /// <summary>
    /// Kinect enabled apps should customize which Kinect services it initializes here.
    /// </summary>
    /// <param name="kinectSensorManager"></param>
    /// <param name="sensor"></param>
    private void InitializeKinectServices(KinectSensorManager kinectSensorManager, KinectSensor sensor)
    {
        // Application should enable all streams first.

        // configure the color stream
        kinectSensorManager.ColorFormat = ColorImageFormat.RgbResolution640x480Fps30;
        kinectSensorManager.ColorStreamEnabled = true;

        // configure the depth stream
        kinectSensorManager.DepthStreamEnabled = true;

        kinectSensorManager.TransformSmoothParameters =
            new TransformSmoothParameters
            {
                Smoothing = 0.5f,
                Correction = 0.5f,
                Prediction = 0.5f,
                JitterRadius = 0.05f,
                MaxDeviationRadius = 0.04f
            };

        // configure the skeleton stream
        sensor.SkeletonFrameReady += FramesReady;
        kinectSensorManager.SkeletonStreamEnabled = true;
        sensor.SkeletonStream.TrackingMode = SkeletonTrackingMode.Seated;
        // initialize the gesture recognizer
        gestureController = new GestureController();
        gestureController.GestureRecognized += OnGestureRecognized;

        kinectSensorManager.KinectSensorEnabled = true;

        if (!kinectSensorManager.KinectSensorAppConflict)
        {
            // addition configuration, as needed
        }
    }

    /// <summary>
    /// Kinect enabled apps should uninitialize all Kinect services that were initialized in InitializeKinectServices() here.
    /// </summary>
    /// <param name="sensor"></param>
    private void UninitializeKinectServices(KinectSensor sensor)
    {

    }

    #endregion Kinect Discovery & Setup

    #region Properties

    public static readonly DependencyProperty KinectSensorManagerProperty =
        DependencyProperty.Register(
            "KinectSensorManager",
            typeof(KinectSensorManager),
            typeof(MainWindow),
            new PropertyMetadata(null));

    public KinectSensorManager KinectSensorManager
    {
        get { return (KinectSensorManager)GetValue(KinectSensorManagerProperty); }
        set { SetValue(KinectSensorManagerProperty, value); }
    }

    /// <summary>
    /// Gets or sets the last recognized gesture.
    /// </summary>
    private string _gesture;
    public String Gesture
    {
        get { return _gesture; }

        private set
        {
            if (_gesture == value)
                return;

            _gesture = value;

            Debug.WriteLine("Gesture = " + _gesture);

            if (this.PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs("Gesture"));
        }
    }

    #endregion Properties

    #region Events

    /// <summary>
    /// Event implementing INotifyPropertyChanged interface.
    /// </summary>
    public event PropertyChangedEventHandler PropertyChanged;

    #endregion Events

    #region Event Handlers

    /// <summary>
    ///
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e">Gesture event arguments.</param>
    private void OnGestureRecognized(object sender, GestureEventArgs e)
    {
        Debug.WriteLine(e.GestureType);

        switch (e.GestureType)
        {
            case GestureType.Menu:
                Gesture = "Menu";
                break;
            case GestureType.WaveRight:
                Gesture = "Wave Right";
                break;
            case GestureType.WaveLeft:
                Gesture = "Wave Left";
                break;
            case GestureType.JoinedHands:
                Gesture = "Joined Hands";
                break;
            case GestureType.SwipeLeft:
                Gesture = "Swipe Left";
                break;
            case GestureType.SwipeRight:
                Gesture = "Swipe Right";
                break;
            case GestureType.ZoomIn:
                Gesture = "Zoom In";
                break;
            case GestureType.ZoomOut:
                Gesture = "Zoom Out";
                break;

            default:
                break;
        }
    }

    void FramesReady(object sender, AllFramesReadyEventArgs e, KinectSensor sensor)
    {
        Skeleton skeleton = FindSkeleton(e);
        if (skeleton != null)
        {
            gestureController.UpdateAllGestures(skeleton);
        }
    }

    private int CurrentTrackingId = 0;

    Skeleton FindSkeleton(AllFramesReadyEventArgs e)
    {
        Skeleton skeleton = null;

        using (SkeletonFrame SFrame = e.OpenSkeletonFrame())
        {
            if (SFrame == null)
            {
                return null;
            }

            if (skeletons == null)
            {
                skeletons = new Skeleton[SFrame.SkeletonArrayLength];
            }

            SFrame.CopySkeletonDataTo(skeletons);

            if (CurrentTrackingId != 0)
            {
                // We've been tracking someone; see if they're still here

                skeleton =
                    (from s in skeletons
                     where s.TrackingState == SkeletonTrackingState.Tracked &&
                           s.Joints[JointType.Head].TrackingState == JointTrackingState.Tracked &&
                           s.TrackingId == CurrentTrackingId
                     select s).FirstOrDefault();

                if (skeleton == null)
                {
                    CurrentTrackingId = 0;
                    sensor.SkeletonStream.AppChoosesSkeletons = false;
                }
            }
            else
            {
                // Try to find someone new

                skeleton =
                    (from s in skeletons
                     where s.TrackingState == SkeletonTrackingState.Tracked &&
                           s.Joints[JointType.Head].TrackingState == JointTrackingState.Tracked
                     select s).FirstOrDefault();

                if (skeleton != null)
                {
                    CurrentTrackingId = skeleton.TrackingId;
                    sensor.SkeletonStream.AppChoosesSkeletons = true;
                    sensor.SkeletonStream.ChooseSkeletons(CurrentTrackingId);
                }
            }
        }

        return skeleton;
    }

    #endregion Event Handlers

   }
}

但是,我从VS2012收到错误:

1)'FramesReady'没有重载匹配委托'System.EventHandler'

2)'传感器'不存在(很可能是因为它没有被导入,但是从我尝试过的,将传感器传递到方法会导致更多错误)

如果有人可以帮助解决这个问题,或者甚至指出正确的方向来解决这个问题,那就太棒了!重申一下,主要目标是将Kinect锁定在它找到的第一个人身上,并保持锁定,让多个人在视线中四处移动。

1 个答案:

答案 0 :(得分:1)

如果您计划继续使用KinectSensorManager,可以使用KinectSkeletonChooser来帮助您挑选所需的骨架。此辅助函数也包含在KinectWpfViewers项目中。您无需在后面的代码中添加任何其他代码即可使用它。

最简单的方法就是将其添加到您的XAML中。更新星期二图书馆除外的演示代码,它看起来像是:

<Window x:Class="Fizbin.Kinect.Gestures.Demo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:kv="clr-namespace:Microsoft.Samples.Kinect.WpfViewers;assembly=Microsoft.Samples.Kinect.WpfViewers"
        Title="MainWindow" Height="350" Width="525">
    <Grid>        
        <Grid HorizontalAlignment="Right" VerticalAlignment="Bottom" Width="320" Height="240">
            <kv:KinectSkeletonChooser KinectSensorManager="{Binding KinectSensorManager}" SkeletonChooserMode="Sticky1Player" />
            <kv:KinectDepthViewer x:Name="DepthViewer" KinectSensorManager="{Binding KinectSensorManager}" />
            <Canvas>
                <kv:KinectSkeletonViewer
                                    KinectSensorManager="{Binding KinectSensorManager}"
                                    Width="{Binding ElementName=DepthViewer, Path=ActualWidth}"
                                    Height="{Binding ElementName=DepthViewer, Path=ActualHeight}"
                                    ShowBones="True" ShowJoints="True" ShowCenter="True" ImageType="Depth" />
            </Canvas>
        </Grid>

        <TextBlock Text="{Binding Gesture}" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="48" FontWeight="Bold" Margin="-2,0,0,0"/>
        <TextBlock Text="{Binding Gesture}" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="48" FontWeight="Bold" Margin="2,0,0,0"/>
        <TextBlock Text="{Binding Gesture}" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="48" FontWeight="Bold" Margin="0,-2,0,0"/>
        <TextBlock Text="{Binding Gesture}" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="48" FontWeight="Bold" Margin="0,2,0,0"/>
        <TextBlock Text="{Binding Gesture}" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="48" FontWeight="Bold" Foreground="White"/>

    </Grid>
</Window>

请注意第8行的新KinectSkeletonChooser标记。

其他可用选项可参见SkeletonChooserMode枚举:

public enum SkeletonChooserMode
{
    /// <summary>
    /// Use system default tracking
    /// </summary>
    DefaultSystemTracking,

    /// <summary>
    /// Track the player nearest to the sensor
    /// </summary>
    Closest1Player,

    /// <summary>
    /// Track the two players nearest to the sensor
    /// </summary>
    Closest2Player,

    /// <summary>
    /// Track one player based on id
    /// </summary>
    Sticky1Player,

    /// <summary>
    /// Track two players based on id
    /// </summary>
    Sticky2Player,

    /// <summary>
    /// Track one player based on most activity
    /// </summary>
    MostActive1Player,

    /// <summary>
    /// Track two players based on most activity
    /// </summary>
    MostActive2Player
}