如何将 Kinect 2.0 的深度数据转换为距离值?

Posted

技术标签:

【中文标题】如何将 Kinect 2.0 的深度数据转换为距离值?【英文标题】:How to convert the depth data from a Kinect 2.0 to a distance value? 【发布时间】:2016-05-03 10:01:38 【问题描述】:

我想利用 Kinect 2.0 SDK 的深度传感器,但不是以图像格式绘制或显示该数据,而是以整数或类似格式显示。例如,如果我的手非常靠近 Kinect,我会得到一个整数值,告诉我相机和障碍物之间的大致范围。 也许是这样的。随着障碍物的移动,Kinect 会重新计算距离并可能每隔一秒或半秒更新一次。

The distance between the kinect and the obstacle is 20 cm
The distance between the kinect and the obstacle is 10 cm 
The distance between the kinect and the obstacle is 100 cm

这可能吗? 我搜索了教程,但我发现的只是表示通常使用点云或黑白深度图像。

【问题讨论】:

“黑白深度图像”可能会为您提供 Kinect 与其他一些被编码为像素亮度的对象之间的距离。你能解释一下为什么这些信息不适合你的目的吗? 我不知道如何将图像数据中的数据移动到距离 kinect 仅一段距离且只有一个障碍物的位置?任何教程或示例代码都会有所帮助。谢谢 推荐教程与(主要)SO 无关。您应该尝试自己找到一些东西,跟踪它,研究您可能遇到的任何问题,然后如果仍然没有解决具体问题,请返回。您可能可以在相关聊天中要求一些教程指针等,不确定。您可能需要研究图像处理或计算机视觉,以将点云/深度图像转换为有意义的场景表示。 潜在的研究途径:如果您知道场景中只有一个对象(即深度图像只是对象或背景),您应该能够使用 i>segmentation 算法从深度图像中提取对象的区域(即使是基本的阈值也可能起作用)。然后,将该区域的颜色值(可能是最小值,也可能是平均值)转换为距离。 您使用的是哪个版本的 Microsoft Kinect SDK? (即您使用的是哪个版本的 Kinect 设备?Kinect for Xbox One 或 Kinect for Xbox 360?) 【参考方案1】:

尽管这个问题已经问过一段时间了,而且提问的人很可能自己解决了这个问题,但我只是想给其他可能有同样问题/问题的人提供 C++ 代码来解决这个问题。

注意:该解决方案基于 Kinect 2.0 SDK,如果我没记错的话,我取自 SDK Browser 2.0 中提供的示例之一,该示例随 Kinect 2.0 SDK 一起提供。我删除了我所做的所有特殊修改,只留下了最重要的方面(因此,您很可能必须修改 void 并为其提供某种返回参数)。

m_pDepthFrameReader 与初始化 IDepthFrameReader* 一样

void KinectFusionProcessor::getDistance() 
IDepthFrame* frame = NULL;
if (SUCCEEDED(m_pDepthFrameReader->AcquireLatestFrame(&frame))) 
    int width = 512;
    int height = 424;
    unsigned int sz=(512*424);
    unsigned short buf[525 * 424] = 0;
    frame->CopyFrameDataToArray(sz,buf);

    const unsigned short* curr = (const unsigned short*)buf;
    const unsigned short* dataEnd = curr + (width*height);

    while (curr < dataEnd) 
        // Get depth in millimeters
        unsigned short depth = (*curr++);
    

if (frame) frame->Release();

【讨论】:

【参考方案2】:

Kinect 确实使用了点云。并且点云中的每个像素都有一个无符号短整数值,表示距离 Kinect 的距离(以毫米为单位)。据我所知,相机已经能够进行补偿,或者其视图侧面的物体比前面的物体更远,因此所有数据都表示这些物体远离 Kinects 相机正在观看的平面的深度。 Kinect 最多可以查看 8m 左右,但只有 4-5m 之间的可靠数据,并且无法看到小于 0.5m 的任何东西。 由于听起来您将其用作障碍物检测系统,因此我建议监视点云中的所有数据点,并对与其他数据点分开的分组数据点进行平均,并将它们解释为具有近似距离的自己的对象。 Kinect 还以每秒 30 帧的速度更新(假设您的硬件可以处理密集的数据流)。因此,您只需不断地监控您的点云,了解物体距离的变化。

如果您从下载 SDK 和 Kinect Studio 开始,您可以使用深度/IR 编程示例和工作室来更好地了解如何使用数据。

【讨论】:

【参考方案3】:

这很简单。我不知道C++ 中的确切代码,但在 C# 中,一旦你有了深度框架,你需要执行以下操作: 我假设您已经知道要评估深度值的 Y 和 X 点。

一旦知道了,就需要先将深度帧的每个字节转换成ushort。

之后,您需要计算与您的 X 和 Y 点对应的 depthPixels 内的索引。通常这是使用的等式:

// Get the depth for this pixel
ushort depth = frameData[y * depthFrameDescription.Height + x];

我希望这会有所帮助。

【讨论】:

如果我没记错的话,我相信它实际上是 ' (y * width) + x '。

以上是关于如何将 Kinect 2.0 的深度数据转换为距离值?的主要内容,如果未能解决你的问题,请参考以下文章

处理深度数据 - Kinect

2将图像转换为点云

kinect2.0 基础篇第3篇 用C#在Visual Studio上编写把深度图像转换成彩色图像

Kinect V2 中原始数据的单位是啥?

Kinect结合Unity基础使用(一)

你好,问一下,现在你知道如何保存kinect的深度图像-并用pcl转化为点云pcd格式了吗