Kinect SDK:对齐深度和颜色框架

时间:2013-04-10 21:02:04

标签: c++ image-processing kinect kinect-sdk

我正在使用Kinect传感器,我正在尝试对齐深度和颜色框架,以便我可以将它们保存为彼此“适合”的图像。我花了很多时间浏览msdn论坛和Kinect SDK的适度文档,我完全无处可去。

基于这个答案:Kinect: Converting from RGB Coordinates to Depth Coordinates

我有以下功能,其中depthDatacolorData是从NUI_LOCKED_RECT.pBits获得的,mappedData是包含新颜色框架的输出,映射到深度坐标:

bool mapColorFrameToDepthFrame(unsigned char *depthData, unsigned char* colorData, unsigned char* mappedData)
{
    INuiCoordinateMapper* coordMapper;

    // Get coordinate mapper
    m_pSensor->NuiGetCoordinateMapper(&coordMapper);

    NUI_DEPTH_IMAGE_POINT* depthPoints = new NUI_DEPTH_IMAGE_POINT[640 * 480];

    HRESULT result = coordMapper->MapColorFrameToDepthFrame(NUI_IMAGE_TYPE_COLOR, NUI_IMAGE_RESOLUTION_640x480, NUI_IMAGE_RESOLUTION_640x480, 640 * 480, reinterpret_cast<NUI_DEPTH_IMAGE_PIXEL*>(depthData), 640 * 480, depthPoints);
    if (FAILED(result))
    {
        return false;
    }    

    int pos = 0;
    int* colorRun = reinterpret_cast<int*>(colorData);
    int* mappedRun = reinterpret_cast<int*>(mappedData);

    // For each pixel of new color frame
    for (int i = 0; i < 640 * 480; ++i)
    {
        // Find the corresponding pixel in original color frame from depthPoints
        pos = (depthPoints[i].y * 640) + depthPoints[i].x;

        // Set pixel value if it's within frame boundaries
        if (pos < 640 * 480)
        {
            mappedRun[i] = colorRun[pos];
        }
    }

    return true;
}

运行此代码时我得到的是一个未更改的颜色框,其中删除了(白色)所有像素,其中depthFrame没有信息。

5 个答案:

答案 0 :(得分:2)

OpenNI框架有一个选项调用注册。

IMAGE_REGISTRATION_DEPTH_TO_IMAGE - 深度图像被转换为​​与RGB图像具有相同的明显有利位置。

OpenNI 2.0和Nite 2.0非常适合捕获Kinect信息,还有很多教程。

你可以看一下:

Kinect with OpenNI

OpenNi在SimplerViewer中有一个合并深度和颜色的例子,你也可以看看并尝试一下。

答案 1 :(得分:0)

这可能不是您希望的快速答案,但此转换已在openFrameworks (see here)ofxKinectNui插件中成功完成。

看似ofxKinectNuiGetColorPixelCoordinatesFromDepthPixel函数定义了here。{/ p>

答案 2 :(得分:0)

我认为问题在于你实际上应该调用MapDepthFrameToColorFrame来调用MapColorFrameToDepthFrame。

吸烟枪是这行代码:

mappedRun[i] = colorRun[pos];

pos读取并写入i是向后的,因为pos = depthPoints[i]表示与i处的颜色坐标对应的深度坐标。您实际上想要迭代编写所有深度坐标并从相应的颜色坐标处的输入颜色图像中读取。

答案 3 :(得分:0)

我认为在你的代码中有不同的不正确的行。

首先,您传递给您的功能的是哪种深度图?

对于每个值使用两个字节来存储深度数据,这意味着您应该为深度数据使用的指针的正确类型 是无符号短

第二点是从我所理解的,你想要将深度框架映射到颜色框架,所以你拥有正确的功能 要从kinect sdk调用 MapDepthFrameToColorFrame 而不是MapColorFrameToDepthFrame。

最后,函数将返回一个点的映射,对于位置[i]的每个深度数据,你有位置x和位置y,该点应该 被映射。
为此,您不需要colorData指针

所以你的功能应该修改如下:

/** Method used to build a depth map aligned to color frame
    @param [in]  depthData    : pointer to your data;
    @param [out] mappedData   : pointer to your aligned depth map;
    @return true if is all ok : false whene something wrong
*/

bool DeviceManager::mapColorFrameToDepthFrame(unsigned short *depthData,  unsigned short* mappedData){
    INuiCoordinateMapper* coordMapper;
    NUI_COLOR_IMAGE_POINT* colorPoints = new NUI_COLOR_IMAGE_POINT[640 * 480]; //color points
    NUI_DEPTH_IMAGE_PIXEL* depthPoints = new NUI_DEPTH_IMAGE_PIXEL[640 * 480]; // depth pixel

    /** BE sURE THAT YOU ARE WORKING WITH THE RIGHT HEIGHT AND WIDTH*/  
    unsigned long refWidth = 0;
    unsigned long refHeight = 0;
    NuiImageResolutionToSize( NUI_IMAGE_RESOLUTION_640x480, refWidth, refHeight );
    int width  = static_cast<int>( refWidth  ); //get the image width in a right way
    int height = static_cast<int>( refHeight ); //get the image height in a right way

    m_pSensor>NuiGetCoordinateMapper(&coordMapper); // get the coord mapper
    //Map your frame;
    HRESULT result = coordMapper->MapDepthFrameToColorFrame( NUI_IMAGE_RESOLUTION_640x480, width * height, depthPoints, NUI_IMAGE_TYPE_COLOR, NUI_IMAGE_RESOLUTION_640x480, width * height, colorPoints );
    if (FAILED(result))
       return false;

    // apply map in terms of x and y (image coordinates);
    for (int i = 0; i < width * height; i++)
       if (colorPoints[i].x >0 && colorPoints[i].x < width && colorPoints[i].y>0 &&    colorPoints[i].y < height)
            *(mappedData + colorPoints[i].x + colorPoints[i].y*width) = *(depthData + i );

    // free your memory!!!
    delete colorPoints;
    delete depthPoints;
    return true;
}



确保已正确初始化mappedData,例如,如下所示。

mappedData = (USHORT*)calloc(width*height, sizeof(ushort));


请记住,kinect sdk不提供颜色和深度数据之间的精确对齐功能。

如果要在两个图像之间进行精确对齐,则应使用校准模型。 在这种情况下,我建议您使用基于Heikkilä校准模型的Kinect校准工具箱。

您可以在以下链接中找到它:
http://www.ee.oulu.fi/~dherrera/kinect/

答案 4 :(得分:-1)

首先,您必须校准您的设备。 这意味着,您应该校准RGB和IR传感器,然后找到RGB和IR之间的转换。 了解此信息后,您可以应用以下功能:

RGBPoint = RotationMatrix * DepthPoint + TranslationVector

检查OpenCV或ROS项目以获取更多详细信息。

Extrinsic Calibration

Intrinsic Calibration