Kinect原始深度转换为米数

3

我正在尝试将Kinect深度图转换为米数距离。问题在于,对于深度图值“1080”及其周围的值,分母中的项变得非常接近“0”,因此距离过大。而对于大于“1090”的值,距离则为负数。

if (depthValue < 2047) 
{
  depthM = 1.0 / (depthValue*-0.0030711016 + 3.3309495161);
}

3
你是否在使用Kinect SDK?那里的深度图以毫米为单位,无需转换。请提供更多关于你问题的详细信息。 - juergen d
我知道我可以直接获取“mm”深度,但我有一些旧的深度图像,其中包含Kinect提供的原始深度值(它们范围从0到8000以上)。我没有使用Kinect或OpenNi SDK。我只需要将这些原始值转换为它们相应的“m”深度值。在许多网站上,都提到了上述函数用于此转换,但对于大于1080的值,该公式绝对不正确。 - Saad
2个回答

5

正确答案实际上是对您问题的评论。给出的数字实际上是毫米单位的距离。要获取此数字,您需要使用骨架关节并调用DepthImageFrame的MapFromSkeletonPoint方法,或者将原始短值向右移DepthImageFrame.PlayerIndexBitmaskWidth位。

例如: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!
    }
}

例如,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!
}

以下的原解决方案已经不再正确:

根据这篇文章所述的内容:


请问还有其他需要翻译的吗?
if (depthValue <= 2047) {
   depthM = 0.1236 * Math.Tan(depthValue / 2842.5 + 1.1863);
}

3

虽然这是一个旧问题,但对我有用的是我有一款旧版的 kinect (XBOX360 + PC reduction 的1414型号)。最近我有时间编写了一些代码和测量:

  1. my raw data is 16 bit not 10/11/12/13 bit !!!

    so probably your data is very similar. Min distance measured is ~0.95m max distance unknown (have not big enough area for testing) and min valid value is 6408 ... ~0.95m from sensor . Another valid value is 15800 ... ~2.5m from sensor for interpolation

  2. naive (linear) transformation to meters

    float z,m=(2.5-0.9)/(15800.0-6408.0);
    WORD raw;
    
    raw=... raw depth form camera/image;
    z=0.0;
    if ((raw>=6408)&&(raw< 0xFFF0)) 
     z=0.9+(float(raw-6408)*m);
    // here z is range in [m] or 0 for invalid depth
    
  3. when I will have more time then I will check the linearity and make it more precise

    to do that I need to make some programing for better measurement and setup working area for more precise distance measurements. More precise constants maybe add cosine correction if its needed. I do not know if device/driver make it itself or not have to measure it. When I get to it will update my answer but I am very lazy so it can be a while ...

[编辑1] 进行了一些几何测量设置和代码更改
因此,这里有一些新的更精确的结论:

if (raw==0x0000) z=0.0;
else if (p.raw>=0x8000) p.z=4.0;
else p.z=0.8+(float(p.raw-6576)*0.00012115165336374002280501710376283);

原始数据已经通过驱动程序或kinect本身进行余弦校正,因此原始表示与传感器垂直的距离。 原始数据与垂直距离成线性关系(至少在0.8-2.0米的范围内),经过更精确的测量,深度范围为<0.8-4.0>[m]。之前的测量不准确。


原始 = 0是太近的值
原始 >= 32768是太远/未知的值,甚至可能是其他东西(还有更多可能性)


@shshadi 我将Kinect数据存储为点的列表,结构体pnt3d { float x,y,z; WORD raw; DWORD rgb; } p; 其中x,y,z是像素相对于Kinect的位置,raw是来自RAW深度帧的相应值,rgb是指向RGB帧中相应像素的指针... z是从Kinect垂直距离。 - Spektre

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接