如何获取深度值,然后使用Kinect在OpenCV中转换为毫米?

时间:2012-04-27 16:39:16

标签: opencv kinect depth openni

我使用带有kniect的OpenCV 3.2.1运行VS2010。

我正在使用here

中的教程
int main( int argc, char* argv[] ){

VideoCapture capture(CV_CAP_OPENNI); // or CV_CAP_OPENNI
for(;;)
{
    Mat depthMap;
    Mat bgrImage;

    capture.grab();

    capture.retrieve( depthMap, CV_CAP_OPENNI_DEPTH_MAP ); // Depth values in mm (CV_16UC1)
    capture.retrieve( bgrImage, CV_CAP_OPENNI_BGR_IMAGE );

    cout << "rows: " << depthMap.rows << " cols: " << depthMap.cols << endl;
    cout << "depth: " << depthMap.at<int>(0,0) << endl;

    imshow("RGB image", bgrImage);

    if( waitKey( 30 ) >= 0 )
        break;
}h
return 0;

运行代码后,我得到以下结果:

靠近一米远的墙壁:

rows: 480 cols: 640
depth: 1157
rows: 480 cols: 640
depth: 1157
rows: 480 cols: 640
depth: 1157
rows: 480 cols: 640
depth: 1157 

(Kinect面向墙壁,距离一米多远)

rows: 480 cols: 640
depth: 83690629
rows: 480 cols: 640
depth: 83690629
rows: 480 cols: 640
depth: 83690629
rows: 480 cols: 640
depth: 83690629
rows: 480 cols: 640
depth: 83690629

我被告知这些值实际上是两个像素?我真的不明白。

所以到目前为止我的理解是这样的:

我抓住了一个深度框并将其存储在一个名为depthMap的矩阵中。矩阵的大小现在是640 * 480。我正在使用代码depthMap.at(0,0)从第0行第0列获取第一个深度值。但不是以毫米为单位返回结果,而是返回83690629!这是我想要的最大值10000的方式

如何将这些值转换为毫米,以便我可以使用它们?谢谢

4 个答案:

答案 0 :(得分:1)

深度图数据是单通道无符号16Bit。 尝试将int替换为CV_16UC1

答案 1 :(得分:1)

我目前正在使用kinect(+ OpenNi + OpenCv),我不知道你是否还在处理你的问题。

我尝试使用完全相同的代码,但使用depthMap.at<unsigned short>(i,j)并且效果非常好,给我的值为mm(当我距离kinect 50厘米时为502)

问题是:我不知道深度值是如何传递的,我在互联网上看到了很多矛盾的信息。为什么它是2像素?为什么要转换为Hex?

我敢肯定,我不会在这里努力理解基本原则。那么,有人在kinect深度上有一些可靠的文档吗?

(我读过有关stephane Magnenat / Nicolas Burrus的公式:11位上的kinect原始数据,添加了一些几何等等......但是OpenNi是否已经处理了这个并且提供了深度原样?)

随意发表评论。 欢呼声。

答案 2 :(得分:1)

深度值以11位存储,封装在16位变量中。 因此,当您访问矩阵时,您必须提供正确的元素数据类型。 如前所述,您可以使用depthMap.at<unsigned short>(i,j),但必须确保unsigned short在所有编译器中都是16位长。 我更喜欢使用uint16_t数据类型。

此外,根据您选择的openni PIXEL_FORMAT,存储在矩阵内的深度值可以是:

  • in millimiters - openni :: PIXEL_FORMAT_DEPTH_1_MM
  • 以十分之一毫米为单位 - openni :: PIXEL_FORMAT_DEPTH_100_UM

您可以使用void openni::VideoMode::setPixelFormat(PixelFormat)函数设置pixel_format http://www.openni.ru/wp-content/doxygen/html/classopenni_1_1_video_mode.html#af7fd37bba526fced9c7dbbbf1ab419ea

如果你想要更精确的数据(PIXEL_FORMAT_DEPTH_100_UM)以毫米为单位,你可以将其转换为浮动并将其除以10:

uint16_t redValue = depthMap.at<uint16_t>(i,j);
float myVal = ( (float) redValue ) / 10.0f;

答案 3 :(得分:0)

检查正确的数据类型,调试模式,然后检查具有矩阵的断点,然后检查文件数据类型