Search code examples
wpfkinectkinect-sdk

Use Kinect to create a digital catalog application


I am creating a WPF application to create digital catalog using kinect v1.8. I am trying to track only a single skeleton using following code:-

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);
        }
}

I am getting an exception when I run the code and skeleton gets detected as follows:-

InvalidOperationException

on the line "this.interactionStream.ProcessSkeleton(s, accelerometerReading, skeletonFrame.Timestamp);" I need to detect only one skeleton and use it for further processing like to access the digital catalog applications. Thanks in advance.


Solution

  • I have Faced Same Problem By using below code I have track only one skeleton Which is closer to the sensor.and directly assign the closest skeleton to the main skeleton stream.

     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;
                }
            }
        }
    

    check the above code it works for me.It may helpful to you.Here snew is the Kinectsensor.