none
Real world dimension problems RRS feed

  • Question

  • Sorry to be starting yet another topic on this, but I cannot for the life of me understand where to go next with my code (C#):

     

    void nui_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
            {
                
                SkeletonFrame allSkeletons = e.SkeletonFrame;
    
                //get the first tracked skeleton
                SkeletonData skeleton = (from s in allSkeletons.Skeletons
                                         where s.TrackingState == SkeletonTrackingState.Tracked
                                         select s).FirstOrDefault();
    
    
                if(skeleton != null)
                {
                    //set position
                    //SetEllipsePosition(headEllipse, skeleton.Joints[JointID.Head]);
                    SetEllipsePosition(leftEllipse, skeleton.Joints[JointID.HandLeft]);
                    //SetEllipsePosition(rightEllipse, skeleton.Joints[JointID.HandRight]);
    
    
                    Point jointPos;
                    Joint head;
                    float depthX, depthY;
                    int row, col;
                    //int trkDepth = 0;
                    short dVal;
    
    
                    foreach (SkeletonData data in allSkeletons.Skeletons)
                    {
                        if (SkeletonTrackingState.Tracked == data.TrackingState)
                        {
                            head = data.Joints[JointID.Head];
                            jointPos = new Point(head.Position.X, head.Position.Y);
                            nui.SkeletonEngine.SkeletonToDepthImage(head.Position, out depthX, out depthY, out dVal);
                            dVal = (short)(dVal >> 3); //only if using player data, which I am
                            row = (int)(depthY * 240);
                            col = (int)(depthX * 320);
                            //int i16 = (int)(row * 320 + col) * 2; //since it is a two byte array, shifts should be by 2?
                            //trkDepth = (int)(depthFrame16[i16 + 1] << 5) | (depthFrame16[i16] >> 3);
    
    
                            string text1 = ("(X): " + depthX + ", (Y): " + depthY + " (Z): " + dVal);
                            using (System.IO.StreamWriter file = new System.IO.StreamWriter(@"C:\Temp\WriteText1.txt", true))
                            {
                                file.WriteLine(text1); // [0,1]
                            }                      
                            
                        }
                    }
    
                }
            }
    
            private void SetEllipsePosition(FrameworkElement ellipse, Joint joint)
            {
                string text2 = ("(X): " + joint.Position.X + ", (Y): " + joint.Position.Y + " (Z): " + joint.Position.Z);
                using (System.IO.StreamWriter file = new System.IO.StreamWriter(@"C:\Temp\WriteText2.txt", true))
                {
                    file.WriteLine(text2); // [-1,1]
                }
    
    
                var scaledJoint = joint.ScaleTo(640, 480, .5f, .5f);
    
                Canvas.SetLeft(ellipse, scaledJoint.Position.X);
                Canvas.SetTop(ellipse, scaledJoint.Position.Y); 
                
            }
    

     


    What I have works absolutely fine, I get two text file outputs.  One with an x,y range of [0,1] and one with an x,y range of [-1,1].

    My problem is understanding which output I take now to convert into a metric coordinate system that I have seen people talking about whereby the ranges are:

     

    • Values of x can range from approximately –2.2 to 2.2.
    • Values of y can range from approximately –1.6 to 1.6.
    • Values of z can range from 0.0 to 4.0. (Obviously this (z) isn't an issue as the raw output is in meters.)

    What I want to do is map movement of a player as they move from one side of the screen to the other, measuring true distance in meters so I can then calculate a velocity and direction of movement.

     

     

    I really hope someone could please help as I have been scratching my head at this one for over two months now with no luck, it's driving me insane!!!!


    • Edited by Raiden2387 Tuesday, January 24, 2012 10:52 PM
    Tuesday, January 24, 2012 10:48 PM

Answers

  • When you receive a skeleton frame, all of the information about the joint positions are already in 3D metric space (with the dimensions that you pointed out).  So if you want to know how far someone has walked from time t0 to time t1, then you just find the distance between two positions and use that.

    Choosing a joint as an example, you could take the position of the head joint at t0, then also at t1.  Then you do a function like shown in this thread.  That should give you what you are looking for!

    • Marked as answer by Raiden2387 Wednesday, January 25, 2012 8:21 PM
    Wednesday, January 25, 2012 6:04 AM

All replies

  • When you receive a skeleton frame, all of the information about the joint positions are already in 3D metric space (with the dimensions that you pointed out).  So if you want to know how far someone has walked from time t0 to time t1, then you just find the distance between two positions and use that.

    Choosing a joint as an example, you could take the position of the head joint at t0, then also at t1.  Then you do a function like shown in this thread.  That should give you what you are looking for!

    • Marked as answer by Raiden2387 Wednesday, January 25, 2012 8:21 PM
    Wednesday, January 25, 2012 6:04 AM
  • Thanks for the help, I seem to be getting near consistent readings between my outstretched arms now at 2m and 3m depth from the sensor which is acceptable.

     

    The final code I have is:

    void nui_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
            {
                
                SkeletonFrame allSkeletons = e.SkeletonFrame;
    
                //get the first tracked skeleton
                SkeletonData skeleton = (from s in allSkeletons.Skeletons
                                         where s.TrackingState == SkeletonTrackingState.Tracked
                                         select s).FirstOrDefault();
    
    
                if(skeleton != null)
                {
                    //set position
                    SetEllipsePosition(headEllipse, skeleton.Joints[JointID.Head]);
                    SetEllipsePosition(leftEllipse, skeleton.Joints[JointID.HandLeft]);
                    SetEllipsePosition(rightEllipse, skeleton.Joints[JointID.HandRight]);
    
    
                    Point jointPos;
                    Joint head;
                    float depthX, depthY;
                    double HandDistance;
                    int row, col;
                    //int trkDepth = 0;
                    short dVal;
    
    
                    foreach (SkeletonData data in allSkeletons.Skeletons)
                    {
                        if (SkeletonTrackingState.Tracked == data.TrackingState)
                        {
                            head = data.Joints[JointID.Head];
                            jointPos = new Point(head.Position.X, head.Position.Y);
                            nui.SkeletonEngine.SkeletonToDepthImage(head.Position, out depthX, out depthY, out dVal);
                            dVal = (short)(dVal >> 3); //only if using player data, which I am
                            row = (int)(depthY * 240);
                            col = (int)(depthX * 320);
                            //int i16 = (int)(row * 320 + col) * 2; //since it is a two byte array, shifts should be by 2?
                            //trkDepth = (int)(depthFrame16[i16 + 1] << 5) | (depthFrame16[i16] >> 3);
    
                            HandDistance = Math.Sqrt(
                                        Math.Pow((data.Joints[JointID.HandLeft].Position.X - data.Joints[JointID.HandRight].Position.X), 2) +
                                        Math.Pow((data.Joints[JointID.HandLeft].Position.Y - data.Joints[JointID.HandRight].Position.Y), 2) +
                                        Math.Pow((data.Joints[JointID.HandLeft].Position.Z - data.Joints[JointID.HandRight].Position.Z), 2)
                                        );
    
                            
    
                            string text1 = ("(X): " + depthX + ", (Y): " + depthY + ", (Z): " + dVal + ", Distance = " + HandDistance);
                            using (System.IO.StreamWriter file = new System.IO.StreamWriter(@"C:\Temp\WriteText1.txt", true))
                            {
                                file.WriteLine(text1); // [0,1]
                            }
    
                        
                            
                        }
                    }
    
                }
            }
    
            private void SetEllipsePosition(FrameworkElement ellipse, Joint joint)
            {
                string text2 = ("(X): " + joint.Position.X + ", (Y): " + joint.Position.Y + " (Z): " + joint.Position.Z);
                using (System.IO.StreamWriter file = new System.IO.StreamWriter(@"C:\Temp\WriteText2.txt", true))
                {
                    file.WriteLine(text2); // [-1,1]
                }
    
    
                var scaledJoint = joint.ScaleTo(640, 480, .5f, .5f);
    
                Canvas.SetLeft(ellipse, scaledJoint.Position.X);
                Canvas.SetTop(ellipse, scaledJoint.Position.Y); 
                
            }
    

    Thanks again for your help =)

    Wednesday, January 25, 2012 11:50 AM