Bradley Bricknell
Bradley Bricknell

Reputation: 1

Mapping skeleton joints to create a skeleton

I have been researching this for several days now with no success, looking at other questions being stack overflow being one of my sources. I am creating a program using the Kinect for Windows which will track a user's joints and draw a skeleton on a separate 'screen', I have already mapped the joints themselves and I'm using an image (a red dot) to demonstrate the location of the mapped joint.

My next step is to construct the skeleton itself by drawing a line from one joint to another, the issue I am having is how to draw the line...I have a tendency to overcomplicate things so I'm wondering if I am just making things difficult for myself rather than the just finding the simplest solution.

I feel I am 99% of the way there but there is still one error I am encountering which I cannot get my head around, please find below the error message and related C# code.

"cannot convert from 'Microsoft.Kinect.SkeletonPoint' to 'System.Windows.Point"

code:

private void DrawBone (Joint jointFrom, Joint jointTo)
{
    Brush centerPointBrush;
    Pen trackedBonePen = new Pen(Brushes.White, TrackedBoneThickness);
    inferredBonePen = new Pen(Brushes.Gray, InferredBoneThickness);
    DrawingVisual visual = new DrawingVisual();
    DrawingContext context = visual.RenderOpen();

    centerPointBrush = Brushes.Red;

    if (jointFrom.TrackingState == JointTrackingState.NotTracked
        || jointTo.TrackingState == JointTrackingState.NotTracked)
    {
        return;
    }

    if (jointFrom.TrackingState == JointTrackingState.Inferred
        || jointTo.TrackingState == JointTrackingState.Inferred)
    {       
        context.DrawLine(inferredBonePen,jointFrom.Position, jointTo.Position);
    }

    if (jointFrom.TrackingState == JointTrackingState.Tracked
        || jointTo.TrackingState == JointTrackingState.Tracked)
    {
        context.DrawLine(trackedBonePen, jointFrom.Position, jointTo.Position);
    }
}

The error related to the lines starting context.DrawLine, as these are the not correct arguments for a DrawLine function, I am getting an accompanying error of:

Error 4 The best overloaded method match for
'System.Windows.Media.DrawingContext.DrawLine(System.Windows.Media.Pen,
System.Windows.Point, System.Windows.Point)' has some invalid arguments

Upvotes: 0

Views: 1851

Answers (4)

jubueche
jubueche

Reputation: 793

Don't reinvent the wheel. The guys from Microsoft did a great job there. Maybe this code helps you:

private void DrawBonesAndJoints(Skeleton skeleton, DrawingContext drawingContext)
        {
            // Render Torso
            this.DrawBone(skeleton, drawingContext, JointType.Head, JointType.ShoulderCenter);
            this.DrawBone(skeleton, drawingContext, JointType.ShoulderCenter, JointType.ShoulderLeft);
            this.DrawBone(skeleton, drawingContext, JointType.ShoulderCenter, JointType.ShoulderRight);
            this.DrawBone(skeleton, drawingContext, JointType.ShoulderCenter, JointType.Spine);
            this.DrawBone(skeleton, drawingContext, JointType.Spine, JointType.HipCenter);
            this.DrawBone(skeleton, drawingContext, JointType.HipCenter, JointType.HipLeft);
            this.DrawBone(skeleton, drawingContext, JointType.HipCenter, JointType.HipRight);

            // Left Arm
            this.DrawBone(skeleton, drawingContext, JointType.ShoulderLeft, JointType.ElbowLeft);
            this.DrawBone(skeleton, drawingContext, JointType.ElbowLeft, JointType.WristLeft);
            this.DrawBone(skeleton, drawingContext, JointType.WristLeft, JointType.HandLeft);

            // Right Arm
            this.DrawBone(skeleton, drawingContext, JointType.ShoulderRight, JointType.ElbowRight);
            this.DrawBone(skeleton, drawingContext, JointType.ElbowRight, JointType.WristRight);
            this.DrawBone(skeleton, drawingContext, JointType.WristRight, JointType.HandRight);

            // Left Leg
            this.DrawBone(skeleton, drawingContext, JointType.HipLeft, JointType.KneeLeft);
            this.DrawBone(skeleton, drawingContext, JointType.KneeLeft, JointType.AnkleLeft);
            this.DrawBone(skeleton, drawingContext, JointType.AnkleLeft, JointType.FootLeft);

            // Right Leg
            this.DrawBone(skeleton, drawingContext, JointType.HipRight, JointType.KneeRight);
            this.DrawBone(skeleton, drawingContext, JointType.KneeRight, JointType.AnkleRight);
            this.DrawBone(skeleton, drawingContext, JointType.AnkleRight, JointType.FootRight);


            // Render Joints
            foreach (Joint joint in skeleton.Joints)
            {
                Brush drawBrush = null;

                if (joint.TrackingState == JointTrackingState.Tracked)
                {
                    drawBrush = this.trackedJointBrush;                    
                }
                else if (joint.TrackingState == JointTrackingState.Inferred)
                {
                    drawBrush = this.inferredJointBrush;                    
                }

                if (drawBrush != null)
                {
                    drawingContext.DrawEllipse(drawBrush, null, this.SkeletonPointToScreen(joint.Position), JointThickness, JointThickness);
                }
            }
        }

Upvotes: 1

carlos palma
carlos palma

Reputation: 782

Maybe I didn't understand correctly, but why would you want to do something that's already been done?. Here's a sample code from Kinect Developer Toolkit 1.8.

    private void DrawBone(Skeleton skeleton, DrawingContext drawingContext, JointType jointType0, JointType jointType1)
    {
        Joint joint0 = skeleton.Joints[jointType0];
        Joint joint1 = skeleton.Joints[jointType1];

        // If we can't find either of these joints, exit
        if (joint0.TrackingState == JointTrackingState.NotTracked || joint1.TrackingState == JointTrackingState.NotTracked)
        {
            return;
        }

        // Don't draw if both points are inferred
        if (joint0.TrackingState == JointTrackingState.Inferred && joint1.TrackingState == JointTrackingState.Inferred)
        {
            return;
        }

        // We assume all drawn bones are inferred unless BOTH joints are tracked
        Pen drawPen = this.inferredBonePen;

        if (joint0.TrackingState == JointTrackingState.Tracked && joint1.TrackingState == JointTrackingState.Tracked)
        {
            drawPen = this.trackedBonePen;
        }

        drawingContext.DrawLine(drawPen, this.SkeletonPointToScreen(joint0.Position), this.SkeletonPointToScreen(joint1.Position));
    }

Upvotes: 0

Nicholas Pappas
Nicholas Pappas

Reputation: 10624

As Miky Dinescu points out, your immediate issue is the need to translate a Microsoft.Kinect.Joint.Position to a System.Windows.Point.

You likely do not care about the Z value (depth) and therefor need to normalize the X and Y to the size of you window. Depending on how you are wanting the drawn skeleton to behave this may be as simple as always placing the JointType.Spine in the center of the window; or you may have to do additional math in order to translate where in the window the skeleton needs to appear based on where the player is in the Kinect's FOV.

Drawing a skeleton based off the Kinect's input is demonstrated in multiple examples, available from the Kinect for Windows Toolkit. The "Skeleton Basics" and "Shape Game" examples are two that come to mind immediately. You can also find code only at the Kinect for Windows Samples CodePlex page (these examples are coded for SDK 1.6, which will all work just fine in SDK 1.7).

Here is the MainWindow.xaml.cs for the "Skeleton Basics" examples. Take note of the DrawBonesAndJoints' andDrawBone' functions to demonstrate what you are wanting to do.

Upvotes: 0

Mike Dinescu
Mike Dinescu

Reputation: 55760

The error message says it all. Instead of using the jointFrom.Position directly you will need to create a System.Windows.Point to represent the coordinates of the jointFrom and pass that to DrawLine instead.

The same goes for jointTo

The complication is that the skeleton position, and thus fromJoint.Position, represents a 3D coordinate whereas the point used to draw lines is a 2D coordinate. So a direct conversion is not possible. Rather you will need to project the joint position in 2D and use the projected point to draw the line.

Your other option would be to use 3D drawing in WPF rather than just drawing to a visual.

Upvotes: 0

Related Questions