0

i want to map an ellipse to the hand joint.And the ellipse has to move as my hand joint will move.

Please provide me some reference links that help me in doing programs using kinect Sdk 1.5. Thank you

ravithejag
  • 588
  • 11
  • 23
  • 1
    Have you at least initialized kinect, and just wondering how to retrieve skeleton objects? or you need a full-tutorial on kinect? – Heisenbug Aug 07 '12 at 11:13

2 Answers2

3

Although what @Heisenbug would work, there is a much simpler way in WPF. You can find a tutorial on it at Channel 9's Skeleton Fundamentals. Basically you need a Canvas, and however many ellipses you want. Here is the code XAML

 <Window x:Class="SkeletalTracking.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="600" Width="800" Loaded="Window_Loaded"  
    Closing="Window_Closing" WindowState="Maximized">       
<Canvas Name="MainCanvas">
    <Ellipse Canvas.Left="0" Canvas.Top="0" Height="50" Name="leftEllipse"  Width="50" Fill="#FF4D298D" Opacity="1" Stroke="White" />
    <Ellipse Canvas.Left="100" Canvas.Top="0" Fill="#FF2CACE3" Height="50" Name="rightEllipse" Width="50" Opacity="1" Stroke="White" />
    <Image Canvas.Left="66" Canvas.Top="90" Height="87" Name="headImage" Stretch="Fill" Width="84" Source="/SkeletalTracking;component/c4f-color.png" />
    <Ellipse Canvas.Left="283" Canvas.Top="233" Height="23" Name="leftknee" Stroke="Black" Width="29" />
    <Ellipse Canvas.Left="232" Canvas.Top="233" Height="23" Name="rightknee" Stroke="Black" Width="30" />
</Canvas>
</Window>

Here I am using 4 ellipses (knees, hands) and an image (head). The essential code for this is right here:

    private void ScalePosition(FrameworkElement element, Joint joint)
    {
        //convert the value to X/Y
        //Joint scaledJoint = joint.ScaleTo(1280, 720); 

        //convert & scale (.3 = means 1/3 of joint distance)
        //note you need to have Coding4Fun
        Joint scaledJoint = joint.ScaleTo(1280, 720, .3f, .3f);

        Canvas.SetLeft(element, scaledJoint.Position.X);
        Canvas.SetTop(element, scaledJoint.Position.Y);
    }

This is the key to this program. It takes the location from the joint and changes the elements location to there. The next part is also important, you will do something like this:

    void GetCameraPoint(Skeleton first, AllFramesReadyEventArgs e)
    {

        using (DepthImageFrame depth = e.OpenDepthImageFrame())
        {
            if (depth == null ||
                kinectSensorChooser1.Kinect == null)
            {
                return;
            }


            //Map a joint location to a point on the depth map
            //head
            DepthImagePoint headDepthPoint =
                depth.MapFromSkeletonPoint(first.Joints[JointType.Head].Position);
            //left hand
            DepthImagePoint leftDepthPoint =
                depth.MapFromSkeletonPoint(first.Joints[JointType.HandLeft].Position);
            //right hand
            DepthImagePoint rightDepthPoint =
                depth.MapFromSkeletonPoint(first.Joints[JointType.HandRight].Position);


            //Map a depth point to a point on the color image
            //head
            ColorImagePoint headColorPoint =
                depth.MapToColorImagePoint(headDepthPoint.X, headDepthPoint.Y,
                ColorImageFormat.RgbResolution640x480Fps30);
            //left hand
            ColorImagePoint leftColorPoint =
                depth.MapToColorImagePoint(leftDepthPoint.X, leftDepthPoint.Y,
                ColorImageFormat.RgbResolution640x480Fps30);
            //right hand
            ColorImagePoint rightColorPoint =
                depth.MapToColorImagePoint(rightDepthPoint.X, rightDepthPoint.Y,
                ColorImageFormat.RgbResolution640x480Fps30);


            //Set location
            CameraPosition(headImage, headColorPoint);
            CameraPosition(leftEllipse, leftColorPoint);
            CameraPosition(rightEllipse, rightColorPoint);
        }
    }

The above code maps the the skeleton point to the depth frame then to the color frame.

    Skeleton GetFirstSkeleton(AllFramesReadyEventArgs e)
    {
        using (SkeletonFrame skeletonFrameData = e.OpenSkeletonFrame())
        {
            if (skeletonFrameData == null)
            {
                return null;
            }


            skeletonFrameData.CopySkeletonDataTo(allSkeletons);

            //get the first tracked skeleton
            Skeleton first = (from s in allSkeletons
                              where s.TrackingState == SkeletonTrackingState.Tracked
                              select s).FirstOrDefault();

            return first;

        }
    }

This just gets the code for the skeleton you will select. Then in AllFrameReadyEventArgs you will do this to bring it all together.

    void sensor_AllFramesReady(object sender, AllFramesReadyEventArgs e)
    {
        if (closing)
        {
            return;
        }

        //Get a skeleton
        Skeleton first = GetFirstSkeleton(e);

        if (first == null)
        {
            return;
        }



        //set scaled position
        ScalePosition(headImage, first.Joints[JointType.Head]);
        ScalePosition(leftEllipse, first.Joints[JointType.HandLeft]);
        ScalePosition(rightEllipse, first.Joints[JointType.HandRight]);
        ScalePosition(leftknee, first.Joints[JointType.KneeLeft]);
        ScalePosition(rightknee, first.Joints[JointType.KneeRight]);

        GetCameraPoint(first, e);
    }

Your results will look the best if you have a color image behind, but I decided to skip that part for now. Hope this helps!

Liam McInroy
  • 4,339
  • 5
  • 32
  • 53
  • 2
    good to know :) . I played a little bit kinect several months ago. I didn't find any extensive documentation on it, so I just try to came up with some working code, making tries and look at other people's code. – Heisenbug Aug 07 '12 at 15:45
  • Yeah, but it is nice to know how to do it in XNA – Liam McInroy Aug 07 '12 at 23:20
2

Basically somewhere in the code you will have a class to interact with Kinect SDK:

private KinectSensor kinectSensor;

You can initilazied KinectSensor this way:

public void kinectInit()
{
    KinectSensor.KinectSensors.StatusChanged += (object sender, StatusChangedEventArgs e) =>
    {
        if (e.Sensor == kinectSensor)
        {
            if (e.Status != KinectStatus.Connected)
            {
                SetSensor(null);
            }
        }else if ((kinectSensor == null) && (e.Status == KinectStatus.Connected))
        {
            SetSensor(e.Sensor);
        }
    };

    foreach (var sensor in KinectSensor.KinectSensors)
    {
        if (sensor.Status == KinectStatus.Connected)
        {
            SetSensor(sensor);
         }
    }
}

Basically you are defining a delegate to handle KinectSensor's status changed. Where SetSensor method could be something like this:

private void SetSensor(KinectSensor newSensor)
{
    if (kinectSensor != null)
    {
        kinectSensor.Stop();
    }

    kinectSensor = newSensor;

    if (kinectSensor != null)
    {
        kinectSensor.SkeletonStream.Enable();
        kinectSensor.SkeletonFrameReady += OnSkeletonFrameReady;
        kinectSensor.Start();
     }
}

Now, OnSkeletonFrameReady it's the "update function". It will be called continuosly at each Kinect sensor update. From inside it you can retrieve information about the joints and render what you want.

private void OnSkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
{

    skelFrame = e.OpenSkeletonFrame();
    skeletons = new Skeleton[kinectSensor.SkeletonStream.FrameSkeletonArrayLength];          

    if (skelFrame != null)
    {
        skelFrame.CopySkeletonDataTo(skeletons);
        foreach (Skeleton skel in skeletons) {
        if (skel.TrackingState >= SkeletonTrackingState.Tracked)
        {
            //here's get the joints for each tracked skeleton
            SkeletonPoint rightHand = skel.Joints[JointType.HandRight].Position;
            ....    
         }
    }
}

Since your are using C# and Kinect, the simple library you could use for rendering you ellipse is XNA.

Heisenbug
  • 38,762
  • 28
  • 132
  • 190
  • good for on using the new SDK. Everyone around the internet still uses the beta SDK. I have a question. How can I set the position? Intellisense tells me when I type myjoint.position.X that it gets and sets the X in position. How can I set it though?? All I find is with ScaleTo() which is removed in the newer SDK – John Demetriou Nov 15 '12 at 11:25
  • @macrian: why do you want to modify Position? Position is data that you are acquiring through Kinect, I can't see the utility of modify them. SkeletonPoint is a structure. You can access single elements of that structure, for example rightHand.X = 5f; Of course you are modifying a local copy of rigthHand structure. – Heisenbug Nov 15 '12 at 11:48
  • Ok the code I have is beta sdk code that has scaleto function. I do not seem to understand how I can scale a joint with the new sdk (I am converting a project from beta sdk to the new one – John Demetriou Nov 15 '12 at 11:51
  • I don't know what Scale method does, never used beta SDK. What's the meaning of Scale? Could you provide an explanation or an example? – Heisenbug Nov 15 '12 at 11:56
  • well I haven't used it either and I have a semester project and the code uses the beta SDK. Anw the scaleto method all you are doing is defining where in the real-word (ala: the Kinect coordinates) equals the left, right, top and bottom of your screen. You are just telling your application that "this Kinect coordinate is equal to this screen pixel". the code I have is this Joint scaledRight = jointRight.ScaleTo((int)SystemParameters.PrimaryScreenWidth, (int)SystemParameters.PrimaryScreenHeight, SkeletonMaxX, SkeletonMaxY); I need a way to do the same with the new sdk – John Demetriou Nov 15 '12 at 12:34