Page 1 of 3
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.
UPDATE: A new version of the entire series for SDK 1.0 is being prepared and should be published soon.
The first part is Getting started with Windows Kinect SDK 1.0
If you don't want to miss it subscribe to the RSS feed, follow us on Google+, Twitter, Linkedin or Facebook or sign up for our weekly newsletter.
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.
Drawing on a Bitmap
In the previous examples we have just used direct manipulation of the bit array to set pixels. This is fine when you only want to work with a few pixels and it has the advantage of not involving any other objects. However once you need to start drawing lines to form a skeleton then things are too difficult to work with via direct manipulation.
At this point you have to use what ever graphics facilities the framework you are using provides. The problem is that there is a split between Windows Forms and WPF. For this example we are going to use Windows Forms and the GDI because it is closer to the same facility in C++.
The key idea in the way that Windows Forms provides the facilities of the GDI is the Graphics object. This is a wrapper around the underlying operating system graphics used to draw everything you see on the screen.To make use of it you need to create a Graphics object which provides all of the methods you need to draw on that object. Clearly not all objects can be drawn on and not all objects can be associated with a Graphics object - but a Bitmap can.
So if you have converted the bit array into a Bitmap
you can obtain a Graphic object to enable you to draw on the Bitmap using:
Graphics g = Graphics.FromImage(bmap);
Now you can use the drawing methods provided by Graphics to draw on the Bitmap. So for example:
new Rectangle(x - 10, y - 10, 20, 20));
will draw an ellipse on the bitmap as specified by the Pen and the Rectangle which contains the ellipse.
Now that you have seen how this works you can look up the drawing methods of the Graphics object and use them to draw almost anything on the Bitmap.
The only methods that we will use in addition to the DrawEllipse method is:
which draws a line in the specified Pen from x1,y1 to x2,y2 and
which draws a line from Point1 to Point2.
Notice that all of the co-ordinates are in pixels and so as long as we convert Kinect co-ordinates to pixel co-ordinates in the video Bitmap we can just use them to draw.
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.
Make sure you have loaded a reference to the Kinect DLL and add:
To the start of the program. In the Form's constructor we create a Runtime object so that we can use the Kinect:
nui = Runtime.Kinects;
The nui variable is global allowing us to get a the Kinect from anywhere in the program - not good design but simpler for an example.
Next we have to setup the Kinect and this is more or less the same for each program, differing in only the facilities we are going to use. In this case we make use of all of the facilities:
Next we open the video stream:
The Kinect will now return video images from the video camera and skeleton data. To process this data the simplest thing to do is use the two events associated with data ready in each case:
nui.SkeletonFrameReady += new
nui.VideoFrameReady += new