【问题标题】:Kinect raw depth to distance in metersKinect 原始深度到距离(以米为单位)
【发布时间】:2012-02-08 03:09:57
【问题描述】:

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

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

【问题讨论】:

  • 您使用的是 Kinect SDK 吗?深度图以毫米为单位,无需转换。请详细说明您的问题。
  • 我知道我可以直接获取“mm”的深度,但我有一些旧的深度图像,它们具有 Kinect 提供的原始深度值(它们的范围从 0 到超过 8000)。我没有使用 Kinect 或 OpenNi SDK。我只需要将这些原始值转换为它们各自在“m”中的深度值。在许多网站上,上面的函数都提到了这个转换,但是这个公式对于 1080 以上的值肯定是不正确的

标签: kinect depth


【解决方案1】:

正确答案实际上是对您的问题的评论。给出的数字实际上是以毫米为单位的距离。要获得这个数字,您要么需要使用骨架关节并调用 DepthImageFrame 的 MapFromSkeletonPoint,要么将原始短值右移 DepthImageFrame.PlayerIndexBitmaskWidth。

例如骨架

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!
    }
}

例如换班

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!
}

下面的原解决方案不再正确:

根据本文内容-http://openkinect.org/wiki/Imaging_Information

if (depthValue <= 2047) {
   depthM = 0.1236 * Math.Tan(depthValue / 2842.5 + 1.1863);
}

【讨论】:

    【解决方案2】:

    旧的不活跃问题,但无论如何这对我有用我有一个旧的 kinect 模型(1414 用于 XBOX360 + PC 减少),最近有时间进行一些代码和测量:

    1. 我的原始数据是 16 位而不是 10/11/12/13 位!!!

      所以可能您的数据非常相似。测量的最小距离为~0.95m 最大距离未知(没有足够大的区域进行测试),最小有效值为来自传感器的6408 ... ~0.95m。另一个有效值是来自用于插值的传感器的15800 ... ~2.5m

    2. 朴素(线性)转换为米

      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. 当我有更多时间时,我会检查线性度并使其更精确

      为此,我需要进行一些编程以进行更好的测量并设置工作区域以进行更精确的距离测量。如果需要,更精确的常数可能会添加余弦校正。我不知道设备/驱动程序是否自己制作或不必测量它。当我到达它时会更新我的答案,但我很懒所以可能需要一段时间......

    [编辑 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);
    

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


    raw = 0 值太接近
    raw &gt;= 32768 太远/未知值甚至是别的东西(还有更多可能性)

    【讨论】:

    • @shshadi 我将 kinect 数据存储为点列表 struct pnt3d { float x,y,z;字原始;双字 *rgb; } p;其中 x,y,z 是像素相对于 kinect 的位置,raw 是来自 RAW 深度帧的对应值,*rgb 是指向 RGB 帧中对应像素的指针 ... z 是到 kinect 的垂直距离
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-09-16
    • 1970-01-01
    • 2012-07-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-02
    • 1970-01-01
    相关资源
    最近更新 更多