Getting and Displaying Color Data in C#
Kinect for Windows 1.5, 1.6, 1.7, 1.8
Overview
This How-To topic describes user tasks from the ColorBasics C# sample, which demonstrates how to capture data and save the color stream data in a bitmap.
Code It
To get and display color data, you must first initialize the sensor. Here are the tasks for initializing the sensor to generate color data.
Once you have initialized the sensor, you are ready to get the next frame of data.
- Register an event that fires when data is ready
- Implement an event handler
- Allocate storage for the data
- Get the data
After getting the next frame of data, these tasks store the data.
Register an event that fires when data is ready
A Kinect streams data out continuously, one frame at a time, until you tell it to stop streaming. One method your application can use to get each frame of data, is to set the runtime to notify your application each time a frame is ready by raising an event.
if (this.sensor != null) { this.sensor.ColorFrameReady += this.SensorColorFrameReady; }
Do this by adding a ColorFrameReady event to the KinectSensor class. This will cause the Kinect to raise the event each time a new frame of data is ready.
Implement an event handler
In this example, each time the sensor has a new frame of color data available, the KinectSensor object raises a ColorFrameReady event. The event handler implements code to store the color data in temporary storage. Use the ColorImageFrameReady event arguments to pass information about the object that raised the event to the event handler.
private void SensorColorFrameReady(object sender, ColorImageFrameReadyEventArgs e) { using (ColorImageFrame colorFrame = e.OpenColorImageFrame()) { if (colorFrame != null) { colorFrame.CopyPixelDataTo(this.colorPixels); ... } } }
In the event handler, use the OpenColorImageFrame method to create a ColorImageFrame to give you access to the frame of color data returned in the event argument. Then use the CopyPixelDataTo method to copy the data to your local memory. The sender object is the KinectSensor that fired the event.
This event handler runs each time a new frame of color data is available from the sensor. Since it runs frequently, this code maximizes performance by doing the minimum processing necessary to get the new data and copy it to local memory. The using statement automatically takes care of disposing of the ColorImageFrame object when you are done using it.
Allocate storage for the data
private byte[] colorPixels; this.colorPixels = new byte[this.sensor.ColorStream.FramePixelDataLength];
First, declare a member variable to store the pixel data and then allocate the memory array. Each byte will store the data from one pixel. Get the size of the array to allocate from the FramePixelDataLength property.
For the best performance, allocate the memory for the data outside the event handler, since the event handler runs every frame. For example, allocate the array when you start the application.
Get the data
using (ColorImageFrame colorFrame = e.OpenColorImageFrame()) { if (colorFrame != null) { colorFrame.CopyPixelDataTo(this.colorPixels); ... } }
Create a bitmap to store the data
Create a bitmap to store the pixel data.
private WriteableBitmap colorBitmap; this.colorBitmap = new WriteableBitmap(this.sensor.ColorStream.FrameWidth, this.sensor.ColorStream.FrameHeight, 96.0, 96.0, PixelFormats.Bgr32, null);
A WriteableBitmap is a Windows Presentation Foundation (WPF) construct, available in .NET Framework 4, that allows access to the bitmap bits. You could create a Bitmap every frame, but you will get much better performance creating a WriteableBitmap only when the pixel format changes, such as when you start the application.
Store the data in the bitmap
After getting the color data and saving it in the WriteableBitmap, draw the WriteableBitmap.
if (colorFrame != null) { // Write the pixel data into our bitmap this.colorBitmap.WritePixels( new Int32Rect(0, 0, this.colorBitmap.PixelWidth, this.colorBitmap.PixelHeight), this.colorPixels, this.colorBitmap.PixelWidth * sizeof(int), 0); }
Use the WriteableBitmap.WritePixels method to copy the data from the local array to the WriteableBitmap.