The second project in our "skeleton week" takes us a little further down the path of understanding and using this feature of the Kinect for Windows SDK
Getting started with Microsoft Kinect SDK - The Full Skeleton
So far in this series we've covered the visual and depth inputs and started to look at skeletonization. In this part we get down to the bare bones of the skeleton.
Other Articles in this Series
- Getting started with Microsoft Kinect SDK
- Player index
- Depth and Video space
- The Full Skeleton (this article)
While there is a very good example of how to draw a complete skeleton in the SDK it isn't explained in detail and, in common with most examples, it does things in clever and correct ways. This makes it a piece of code to admire but only if you can work out what it is doing and how. In this article the objective is not only to create a full skeleton graphic but to make it perfectly clear how it is done.
First a small digression into GDI graphics.
Getting started with the full Skeleton
As explained in the previous article, the Kinect doesn't return a skeleton, just a set of joints that it has detected. It is entirely up to us what to do with this set of joints. One of the problems with the example skeleton viewer is that at first look you might think that something clever was going on that relied on the way that the Kinect returns the data.
Let's try and draw a skeleton in a step-by-step way that shows how it all works. The instructions that follow just get you to the point where the SkeletonFrameReady methods is called as described in the previous article.
Start a new C# Windows Forms project.
Now to display the image we simply need to write the code for the FrameReady event handler. However we are going to want to modify the video returned from the camera by adding a small cross at the position of the players head. To do this we will store the video frame in a global variable and allow the SkeletonFrameReady event handler to actually do the displaying of the video frame.
So the FrameReady method is:void FrameReady(object sender,
The videoimage variable is just a global PlanarImage:PlanarImage videoimage;
Now we need to define the SkeletonFrameReady event handler to simply show the video. It has to check first to make sure that an image has been stored in the videoimage:void SkeletonFrameReady(object sender,
if (videoimage.Bits == null) return;
We can't display a PlanarImage in, say, a PictureBox unless we first convert it to an Image object. How to do this was covered in Part 1 of this series, so the method that does the job PImageToBitmap is simply quoted:
Drawing the Body
Now that we have the video frame as a bitmap we can start to draw the skeleton on it. First we need a Graphics object:
Graphics g = Graphics.FromImage(bmap);
Our next problem is to find the positions of each of the joints that makeup the "body" of the skeleton. If you look at the diagram that gives the names of the joints you can see that we need the positions of the Head, Shoulder Center, Spine and Hip Center.
Drawing a Bone
it should be obvious that what we have to do next is draw a line between ShoulderCenter and Spine. Clearly this is just a repeat of what we have already done so this suggests another helper function:void DrawBone(JointID j1,
Point p2 = GetJoint(j2, data);
g.DrawLine(Pens.Red, p1, p2);
This will draw a line between the two specified Joints. So to draw the body all we need is:
Now if you run the program you will see a complete skeleton plot.
You can argue that there are better ways to organize the code but you have to have a list of the joints you want to draw lines between somewhere.
If you want to try taking it further why not change the drawing of the head for an ellipse and a rectangle for the body. It is all fairly easy.