Используйте Kinect для создания приложения цифрового каталога

Я создаю приложение WPF для создания цифрового каталога с помощью kinect v1.8. Я пытаюсь отслеживать только один скелет, используя следующий код: -

private void SensorSkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs skeletonFrameReadyEventArgs)
    {
        // Even though we un-register all our event handlers when the sensor
        // changes, there may still be an event for the old sensor in the queue
        // due to the way the KinectSensor delivers events.  So check again here.
        if (this.KinectSensor != sender)
        {
            return;
        }


        SkeletonFrame skeletonFrame = skeletonFrameReadyEventArgs.OpenSkeletonFrame();
        if (skeletonFrame == null)
            return;

        Skeleton[] skeletons = new Skeleton[skeletonFrame.SkeletonArrayLength];
        skeletonFrame.CopySkeletonDataTo(skeletons);

        Skeleton skeleton = (from skl in skeletons
                             where skl.TrackingState == SkeletonTrackingState.Tracked
                             select skl).FirstOrDefault();

        if (skeleton == null)
            return;

        Skeleton[] s = new Skeleton[1];
        s[0] = skeleton;

        if (SkeletonTrackingState.Tracked == s[0].TrackingState)
        {
            //s1.SkeletonStream.ChooseSkeletons(s[0].TrackingId);
            var accelerometerReading = this.KinectSensor.AccelerometerGetCurrentReading();
            this.interactionStream.ProcessSkeleton(s, accelerometerReading, skeletonFrame.Timestamp);
        }
}

Я получаю исключение, когда запускаю код, и скелет обнаруживается следующим образом: -

InvalidOperationException

в строке «this.interactionStream.ProcessSkeleton(s, accelerometerReading, SkeletonFrame.Timestamp);» Мне нужно обнаружить только один скелет и использовать его для дальнейшей обработки, например, для доступа к приложениям цифрового каталога. Заранее спасибо.


person Gaurang    schedule 15.05.2014    source источник


Ответы (2)


Я столкнулся с той же проблемой. Используя приведенный ниже код, я отслеживаю только один скелет, который находится ближе к датчику. И напрямую назначаю ближайший скелет основному потоку скелета.

 private void SensorSkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs skeletonFrameReadyEventArgs)
    {
        Skeleton[] skeletons = new Skeleton[0];

        using (SkeletonFrame skeletonFrame = skeletonFrameReadyEventArgs.OpenSkeletonFrame())
        {
            if (skeletonFrame != null && this.skeletons != null)
            {
               //Console.WriteLine(skeletonFrame.SkeletonArrayLength);
                skeletons = new Skeleton[skeletonFrame.SkeletonArrayLength];

                // Set skeleton datas from skeletonFrame
                skeletonFrame.CopySkeletonDataTo(this.skeletons);

                TrackClosestSkeleton();
                Skeleton[] singleSkeleton = new Skeleton[6];

                Skeleton skl=(from mno in this.skeletons where mno.TrackingState==SkeletonTrackingState.Tracked && mno.TrackingId==globalClosestID select mno).FirstOrDefault();
                if (skl == null)
                    return;

                //Creating an empty skkeleton
                Skeleton emptySkeleton = new Skeleton();

                singleSkeleton[0] = skl;        //Pass the Tracked skeleton with closestID
                singleSkeleton[1] = emptySkeleton;  //Passing Empty Skeleton
                singleSkeleton[2] = emptySkeleton;  //Passing Empty Skeleton
                singleSkeleton[3] = emptySkeleton;  //Passing Empty Skeleton
                singleSkeleton[4] = emptySkeleton;  //Passing Empty Skeleton
                singleSkeleton[5] = emptySkeleton;  //Passing Empty Skeleton

                this.snew.SkeletonStream.ChooseSkeletons(globalClosestID);
                var accelerometerReading = this.KinectSensor.AccelerometerGetCurrentReading();
                this.interactionStream.ProcessSkeleton(singleSkeleton, accelerometerReading, skeletonFrame.Timestamp);

            }
        }
    }

int globalClosestID = 0;
    private void TrackClosestSkeleton()
    {
        if (this.snew != null && this.snew.SkeletonStream != null)
        {
            if (!this.snew.SkeletonStream.AppChoosesSkeletons)
            {
                this.snew.SkeletonStream.AppChoosesSkeletons = true; // Ensure AppChoosesSkeletons is set
            }

            float closestDistance = 10000f; // Start with a far enough distance
            int closestID = 0;

            foreach (Skeleton skeleton in this.skeletons.Where(s => s.TrackingState != SkeletonTrackingState.NotTracked))
            {
                if (skeleton.Position.Z < closestDistance)
                {
                    closestID = skeleton.TrackingId;
                    closestDistance = skeleton.Position.Z;
                }
            }

            if (closestID > 0)
            {
                this.snew.SkeletonStream.ChooseSkeletons(closestID); // Track this skeleton
                globalClosestID = closestID;
            }
        }
    }

проверьте приведенный выше код, он работает для меня. Это может быть полезно для вас. Здесь snew - это Kinectsensor.

person madan    schedule 29.05.2014

Вы должны попытаться отследить ближайший скелет, используя этот метод из MSDN.

private void TrackClosestSkeleton()
  {
    if (this.kinect != null && this.kinect.SkeletonStream != null)
        {
        if (!this.kinect.SkeletonStream.AppChoosesSkeletons)
        {
        this.kinect.SkeletonStream.AppChoosesSkeletons = true; // Ensure AppChoosesSkeletons is set
        }

        float closestDistance = 10000f; // Start with a far enough distance
        int closestID = 0;

        foreach (Skeleton skeleton in this.skeletonData.Where(s => s.TrackingState != SkeletonTrackingState.NotTracked))
        {
        if (skeleton.Position.Z < closestDistance)
        {
          closestID = skeleton.TrackingId;
          closestDistance = skeleton.Position.Z;
        }
      }

      if (closestID > 0)
      {
        this.kinect.SkeletonStream.ChooseSkeletons(closestID); // Track this skeleton
      }
    }
  }

И затем в вашем SkeletonFrameReady

private void SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
        {
            Skeleton[] skeletons = new Skeleton[0];

            using (SkeletonFrame skeletonFrame = e.OpenSkeletonFrame())
            {
                if (skeletonFrame != null && this.skeletonData != null)
                {
                    skeletons = new Skeleton[skeletonFrame.SkeletonArrayLength];

                    // Set skeleton datas from skeletonFrame
                    skeletonFrame.CopySkeletonDataTo(this.skeletonData);

                    TrackClosestSkeleton();
                }
            }
                //Do some stuff here
        }
person Florent Gz    schedule 15.05.2014
comment
Спасибо за ответ.. Скажите, пожалуйста, где использовать ваш код? - person Gaurang; 15.05.2014
comment
Скелет[] скелеты = новый Скелет[0]; Какова длина массива - person Gaurang; 15.05.2014
comment
затем он перезаписывается скелетами = new Skeleton[skeletonFrame.SkeletonArrayLength]; - person Florent Gz; 15.05.2014