An interesting issue when using the Microsoft Kinect SDK examples is that the depth image saved by the Depth Basics example is actually an 8-bit PNG without the actual depth information. This is rather awkward especially for beginners who want to start off learning development using the Kinect SDK as the basics. While the depth images from Kinect can be saved easily in Matlab [1], saving in C# is not so straight forward.
Since the 8-bit depth images can only store values upto 0-255, the actual depth data is lost when the image is saved. This means that since the maximum value that the Kinect can return is 8,000mm , to convert it into grayscale, the values are scaled to 256 parts. So each grayscale value represents 8000/255 = 31.25 mm of depth. For 16-bit PNG images, the original depth acquired per pixel is saved in the PNG format directly.

The issue is that WPF cannot display 16-bit image data on screen (i believe due to GDI+ restrictions as mentioned in a StackOverflow question).

In this post, we will see how we can modify the original Depth Basics example from the SDK to save the 16-bit depth images to disk.

TL;DR version:

  1. WriteableBitmap item with PixelFormats.Gray16 needs to be declared, instead of the PixelFormats.Gray8
  2. Two separate WritePixels need to be called, one for displaying the image in (byte) format and another for saving the depth image in 16-bit (ushort) format
  3. Lastly, the depth data acquired needs to be processed twice, once in a byte array for displaying on screen, and once in ushort array for saving.

Note that the above can be modified as required (or for performance reasons if req) but for me, this works just fine and i can display the depth images and save the raw depth data aswell.

The complete code:

First, we need to initialize another WriteableBitmap variable and a ushort[] matrix for saving the data.

Next, in the MainWindow() function, we create a bitmap to display (whith will be 8-bit) and a bitmap to save (which will be 16-bit).

In ProcessDepthFrameData function, assign the values:

In RenderDepthPixels function, create the two images:

And lastly, in ScreenshotButton_Click function, save the file:

The results can be verified by loading the depth image in Matlab. Imread shows a Uint16 image format and the depth values are retained in the matrix. Or by just checking the png file properties 🙂

The complete Visual Studio solution can be downloaded HERE.