Tuesday, February 04, 2014

Comparing Kinect v1 and v2 Depth Data

In this post I show how the new Kinect v2 stacks up against the previous sensor. I’ve been blogging about the new Kinect as part of the Kinect for Windows Developer Preview. First and foremost, I have to get this legal disclaimer out of the way…

This is an early preview of the new Kinect for Windows, so the device, software and documentation are all preliminary and subject to change.

As part of this post, I thought it would be fun to build an application that targets both versions of the device and toggle back and forth between them for comparison sake. There’s a little bit of magic involved as both have the same namespaces and assembly name. Here’s you how you can do the same.

  1. Make a copy of the v1.8 Microsoft.Kinect.dll as Microsoft.Kinect.v1.dll
  2. In your project, add a reference this assembly and change the alias from global to v1.
  3. Do the same for v2.
  4. Add the following code above your using statements.
extern alias v1;
extern alias v2;

using KinectV1 = v1::Microsoft.Kinect;
using KinectV2 = v2::Microsoft.Kinect;

What’s changed between versions?

The first and perhaps most surprising difference is that the frame resolution of the depth data is 512 x 424. Don’t panic. Yes, the Kinect v1 supports a higher resolution of 640x480 resolution, but don’t get caught up on that. This apparently is the native resolution of the camera and although Microsoft may expose other resolutions in a later release, the differences between Time of Flight and Structured Light more than make up for this difference.

As I understand it, Structured Light (the depth technology in v1) reconstructs the depth data by analyzing deformations of a projected IR pattern. This produces approximations for pixels between the projected points. Time of Flight (used in Kinect v2) however blasts the scene with IR and measures how quickly the light comes back to the sensor. This produces better results as each pixel has a unique value. Time of Flight sensors also tend to have lower resolutions, so 512 x 424 is actually pretty impressive compared to other TOF sensors.

The second main change is the field of view and focal length for the camera. The Kinect can see more of the area and can detect objects much closer.

Side by Side Comparisons

The following table shows the observable differences in the depth frame data between versions.

  Kinect V1 Kinect V2
Height 480 424
Width 640 512
Aspect Ratio 4:3 6:5
Horizontal FOV 58.5 70.6
Vertical FOV 45.6 60
Diagonal FOV 70 89.5
Min Depth 0.8 m 0.5 m
Max Depth 4.0 m 4.5 m

The following snapshots are taken from two Kinect devices sitting side by side:

WP_20140203_001

Kinect V1

As part of the structured light algorithm, parts of the depth data are approximated. The subject must be at least 800mm from the camera.

KinectScreenshot-ColorMap-09-27-48

Kinect V2

The new Time of Flight sensor provides greater depth qualities per pixel and a much improved signal to noise ratio despite having an odd 6:5 aspect ratio (512 x 424 px). The increased field of view allows the camera to see more of the scene.

KinectScreenshot-ColorMap-09-28-02

submit to reddit

1 comments:

Adam Russell said...

Can you share your example code? I am desperate to achieve the same 'live switching at runtime' result but so far have only been able to do it at compile time. Even when I tried to replicate your extern alias strategy and renamed copies of the Kinect.dll, I get a conflict when the app starts up - it automatically resolves the ambiguity by just loading the most recent version number of the dll, and then all the Kinect1 calls fail to dynamically link :(

Thanks for showing that this is possible!