我如何将kinect跟踪转换为另一种形式 [英] How can i pass kinect tracking into another form

查看:63
本文介绍了我如何将kinect跟踪转换为另一种形式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在wpf中有一个kinect项目,它使用骨架流来跟踪其用户的左右手,并允许我将鼠标悬停在按钮上.

I have a kinect project in wpf and it uses skeleton stream that tracks the left and right hand of its users and allows me to hover over buttons.

我试图制作一个新表格,只是复制并粘贴所有内容,以便我可以创建一个新页面,但是它没有用,我想我可能不得不引用主页中使用的方法,但是我不确定.

I tried making a new form and just copying and pasting everything so i can create a new page but it didnt work, i think i may have to reference the methods used in the main page, but i am unsure.

我希望能够在新窗口中将骨架流与悬停方法一起使用

I want to be able to use the skeleton stream alongside the hovering method in a new window

任何帮助将不胜感激-如果这对我是初学者来说没有道理,我深表歉意

Any help would be appreciated - i apologize if this does not make sense i am a beginner

代码

 public partial class MainWindow : Window
    {
        private KinectSensor _Kinect;
        private WriteableBitmap _ColorImageBitmap;
        private Int32Rect _ColorImageBitmapRect;
        private int _ColorImageStride;
        private Skeleton[] FrameSkeletons;

        List<Button> buttons;
        static Button selected;

        float handX;
        float handY;

        public MainWindow()
        {
            InitializeComponent();

            InitializeButtons();
            kinectButton.Click += new RoutedEventHandler(kinectButton_Click);

            this.Loaded += (s, e) => { DiscoverKinectSensor(); };
            this.Unloaded += (s, e) => { this.Kinect = null; };
        }

        //initialize buttons to be checked
        private void InitializeButtons()
        {
            buttons = new List<Button> { button1, button2, quitButton};
        }

        //raise event for Kinect sensor status changed
        private void DiscoverKinectSensor()
        {
            KinectSensor.KinectSensors.StatusChanged += KinectSensors_StatusChanged;
            this.Kinect = KinectSensor.KinectSensors.FirstOrDefault(x => x.Status == KinectStatus.Connected);
        }

        private void KinectSensors_StatusChanged(object sender, StatusChangedEventArgs e)
        {
            switch (e.Status)
            {
                case KinectStatus.Connected:
                    if (this.Kinect == null)
                    {
                        this.Kinect = e.Sensor;
                    }
                    break;
                case KinectStatus.Disconnected:
                    if (this.Kinect == e.Sensor)
                    {
                        this.Kinect = null;
                        this.Kinect = KinectSensor.KinectSensors.FirstOrDefault(x => x.Status == KinectStatus.Connected);
                        if (this.Kinect == null)
                        {
                            MessageBox.Show("Sensor Disconnected. Please reconnect to continue.");
                        }
                    }
                    break;
            }
        }

        public KinectSensor Kinect
        {
            get { return this._Kinect; }
            set
            {
                if (this._Kinect != value)
                {
                    if (this._Kinect != null)
                    {
                        UninitializeKinectSensor(this._Kinect);
                        this._Kinect = null;
                    }
                    if (value != null && value.Status == KinectStatus.Connected)
                    {
                        this._Kinect = value;
                        InitializeKinectSensor(this._Kinect);
                    }
                }
            }
        }

        private void UninitializeKinectSensor(KinectSensor kinectSensor)
        {
            if (kinectSensor != null)
            {
                kinectSensor.Stop();
                kinectSensor.ColorFrameReady -= Kinect_ColorFrameReady;
                kinectSensor.SkeletonFrameReady -= Kinect_SkeletonFrameReady;
            }
        }

        private void InitializeKinectSensor(KinectSensor kinectSensor)
        {
            if (kinectSensor != null)
            {
                ColorImageStream colorStream = kinectSensor.ColorStream;
                colorStream.Enable();
                this._ColorImageBitmap = new WriteableBitmap(colorStream.FrameWidth, colorStream.FrameHeight,
                    96, 96, PixelFormats.Bgr32, null);
                this._ColorImageBitmapRect = new Int32Rect(0, 0, colorStream.FrameWidth, colorStream.FrameHeight);
                this._ColorImageStride = colorStream.FrameWidth * colorStream.FrameBytesPerPixel;
                videoStream.Source = this._ColorImageBitmap;

                kinectSensor.SkeletonStream.Enable(new TransformSmoothParameters()
                {
                    Correction = 0.5f,
                    JitterRadius = 0.05f,
                    MaxDeviationRadius = 0.04f,
                    Smoothing = 0.5f
                });

                kinectSensor.SkeletonFrameReady += Kinect_SkeletonFrameReady;
                kinectSensor.ColorFrameReady += Kinect_ColorFrameReady;
                kinectSensor.Start();
                this.FrameSkeletons = new Skeleton[this.Kinect.SkeletonStream.FrameSkeletonArrayLength];

            }
        }

        private void Kinect_ColorFrameReady(object sender, ColorImageFrameReadyEventArgs e)
        {
            using (ColorImageFrame frame = e.OpenColorImageFrame())
            {
                if (frame != null)
                {
                    byte[] pixelData = new byte[frame.PixelDataLength];
                    frame.CopyPixelDataTo(pixelData);
                    this._ColorImageBitmap.WritePixels(this._ColorImageBitmapRect, pixelData,
                        this._ColorImageStride, 0);
                }
            }
        }

        private void Kinect_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
        {
            using (SkeletonFrame frame = e.OpenSkeletonFrame())
            {
                if (frame != null)
                {
                    frame.CopySkeletonDataTo(this.FrameSkeletons);
                    Skeleton skeleton = GetPrimarySkeleton(this.FrameSkeletons);

                    if (skeleton == null)
                    {
                        kinectButton.Visibility = Visibility.Collapsed;
                    }
                    else
                    {
                        Joint primaryHand = GetPrimaryHand(skeleton);
                        TrackHand(primaryHand);

                    }
                }
            }
        }

        //track and display hand
        private void TrackHand(Joint hand)
        {
            if (hand.TrackingState == JointTrackingState.NotTracked)
            {
                kinectButton.Visibility = System.Windows.Visibility.Collapsed;
            }
            else
            {
                kinectButton.Visibility = System.Windows.Visibility.Visible;

                DepthImagePoint point = this.Kinect.MapSkeletonPointToDepth(hand.Position, DepthImageFormat.Resolution640x480Fps30);
                handX = (int)((point.X * LayoutRoot.ActualWidth / this.Kinect.DepthStream.FrameWidth) -
                    (kinectButton.ActualWidth / 2.0));
                handY = (int)((point.Y * LayoutRoot.ActualHeight / this.Kinect.DepthStream.FrameHeight) -
                    (kinectButton.ActualHeight / 2.0));
                Canvas.SetLeft(kinectButton, handX);
                Canvas.SetTop(kinectButton, handY);

                if (isHandOver(kinectButton, buttons)) kinectButton.Hovering();
                else kinectButton.Release();
                if (hand.JointType == JointType.HandRight)
                {
                    kinectButton.ImageSource = "/Images/RightHand.png";
                    kinectButton.ActiveImageSource = "/Images/RightHand.png";
                }
                else
                {
                    kinectButton.ImageSource = "/Images/LeftHand.png";
                    kinectButton.ActiveImageSource = "/Images/LeftHand.png";
                }
            }
        }

        //detect if hand is overlapping over any button
        private bool isHandOver(FrameworkElement hand, List<Button> buttonslist)
        {
            var handTopLeft = new Point(Canvas.GetLeft(hand), Canvas.GetTop(hand));
            var handX = handTopLeft.X + hand.ActualWidth / 2;
            var handY = handTopLeft.Y + hand.ActualHeight / 2;

            foreach (Button target in buttonslist)
            {
                Point targetTopLeft = new Point(Canvas.GetLeft(target), Canvas.GetTop(target));
                if (handX > targetTopLeft.X &&
                    handX < targetTopLeft.X + target.Width &&
                    handY > targetTopLeft.Y &&
                    handY < targetTopLeft.Y + target.Height)
                {
                    selected = target;
                    return true;
                }
            }
            return false;
        }

        //get the hand closest to the Kinect sensor
        private static Joint GetPrimaryHand(Skeleton skeleton)
        {
            Joint primaryHand = new Joint();
            if (skeleton != null)
            {
                primaryHand = skeleton.Joints[JointType.HandLeft];
                Joint rightHand = skeleton.Joints[JointType.HandRight];
                if (rightHand.TrackingState != JointTrackingState.NotTracked)
                {
                    if (primaryHand.TrackingState == JointTrackingState.NotTracked)
                    {
                        primaryHand = rightHand;
                    }
                    else
                    {
                        if (primaryHand.Position.Z > rightHand.Position.Z)
                        {
                            primaryHand = rightHand;
                        }
                    }
                }
            }
            return primaryHand;
        }

        //get the skeleton closest to the Kinect sensor
        private static Skeleton GetPrimarySkeleton(Skeleton[] skeletons)
        {
            Skeleton skeleton = null;
            if (skeletons != null)
            {
                for (int i = 0; i < skeletons.Length; i++)
                {
                    if (skeletons[i].TrackingState == SkeletonTrackingState.Tracked)
                    {
                        if (skeleton == null)
                        {
                            skeleton = skeletons[i];
                        }
                        else
                        {
                            if (skeleton.Position.Z > skeletons[i].Position.Z)
                            {
                                skeleton = skeletons[i];
                            }
                        }
                    }
                }
            }
            return skeleton;
        }

        void kinectButton_Click(object sender, RoutedEventArgs e)
        {
            selected.RaiseEvent(new RoutedEventArgs(Button.ClickEvent, selected));
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            message.Content = "Button 1 clicked!";
        }

        private void button2_Click(object sender, RoutedEventArgs e)
        {
            message.Content = "Button 2 clicked!";
        }

        private void quitButton_Click(object sender, RoutedEventArgs e)
        {
            Application.Current.Shutdown();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {

        }
    }

推荐答案

您可以通过两种不同的方法来完成此操作,然后可以使用下面的更多方法.

You can do this in a couple of different ways, and more ways then what is below.

您可以在创建新窗口时将对传感器本身的引用传递给新窗口:

You could pass a reference to the sensor itself to the new window when it is created:

public MainWindow()
{
    // init code for window and Kinect

    // show the second window
    SecondWindow mySecondWindow = new SecondWindow(_Kinect);
    mySecondWindow.Show();

    // other stuff...
}

public class SecondWindow : Window
{
    public SecondWindow(KinectSensor sensor)
    {
        // ... stuff

        sensor.SkeletonFrameReady += SkeletonFrameReadyCallback;

        // ... more stuff
    }
}

然后在第二个窗口中订阅SkeletonFrameReady回调.如果您正在与秒窗口中的 进行交互,这可能会适合您的情况.

Then subscribe to the SkeletonFrameReady callback in your second window. This might work for your situation if you are interacting with items in the seconds window.

另一种方法是在第二个窗口内创建一个公共回调,并将其预订为SkeletonFrameReady事件.

Another way would be to create a public callback inside your second window and subscribe it to the SkeletonFrameReady event.

public MainWindow()
{
    // init code for window and Kinect

    // show the second window
    SecondWindow mySecondWindow = new SecondWindow(_Kinect);
    mySecondWindow.Show();

    _Kinect.SkeletonFrameReady += mySecondWindow.SkeletonFrameReadyCallback;
}

我还在您的代码中注意到您正在触发事件.如果您想对另一个窗口中的一个窗口中的事件进行操作,则可以按上述相同的方式订阅这些自定义事件.

I also notice in your code that you are firing events. If you are wanting to act on events from one window in a different window, you can subscribe to those custom events in the same mentioned above.

这篇关于我如何将kinect跟踪转换为另一种形式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆