I am trying to convert Kinect depth map to distance in meters. The problem is that for depthmap value '1080' and around it, distance is too large because the term in denominator becomes very close to '0'. and for values above '1090', distance is negative.
if (depthValue < 2047)
{
depthM = 1.0 / (depthValue*-0.0030711016 + 3.3309495161);
}
The correct answer is actually a comment on your question. The number given is actually a distance in millimetres. To get this number, you either need to use a skeleton joint and call DepthImageFrame's MapFromSkeletonPoint or shift the raw short value right by DepthImageFrame.PlayerIndexBitmaskWidth.
E.g. Skeleton
using (var skeletonFrame= e.OpenSkeletonFrame())
using (var depthFrame = e.OpenDepthImageFrame())
{
skeletonFrame.CopySkeletonDataTo(skeletons);
var skeletons = new Skeleton[skeletonFrame.SkeletonArrayLength];
foreach (var skeleton in skeletons)
{
if (skeleton.TrackingState != SkeletonTrackingState.Tracked) continue;
var head = skeleton.Joints[JointType.Head];
if (head.TrackingState == JointTrackingState.NotTracked) continue;
var depthImagePoint = depthFrame.MapFromSkeletonPoint(head.Position);
int depthInMillimeters = depthImagePoint.Depth; // TADA!
}
}
E.g. shift
using (var depthFrame = e.OpenDepthImageFrame())
{
var depthArray = new short[depthFrame.PixelDataLength];
depthFrame.CopyPixelDataTo(depthArray);
for (int i = 0; i < depthArray.Length; i++) {
int depthInMillimeters =
depthArray[i] >> DepthImageFrame.PlayerIndexBitmaskWidth;
// TADAx2!
}
The original solution below is no longer correct:
Based on the contents of this article - http://openkinect.org/wiki/Imaging_Information:
if (depthValue <= 2047) {
depthM = 0.1236 * Math.Tan(depthValue / 2842.5 + 1.1863);
}