7

我正在使用 OpenCV 处理给定的数据集,而我身边没有任何 Kinect。我想将给定的深度数据映射到它的 RGB 对应物(这样我就可以获得实际的颜色和深度)

由于我使用的是 OpenCV 和 C++,并且没有 Kinect,遗憾的是我无法使用官方 Kinect API 中的 MapDepthFrameToColorFrame 方法。

根据给定相机的内在和失真系数,我可以将深度映射到世界坐标,然后根据此处提供的算法返回 RGB

Vec3f depthToW( int x, int y, float depth ){
    Vec3f result;
    result[0] = (float) (x - depthCX) * depth / depthFX;
    result[1] = (float) (y - depthCY) * depth / depthFY;
    result[2] = (float) depth;
    return result;
}

Vec2i wToRGB( const Vec3f & point ) {
    Mat p3d( point );
    p3d = extRotation * p3d + extTranslation;

    float x = p3d.at<float>(0, 0);
    float y = p3d.at<float>(1, 0);
    float z = p3d.at<float>(2, 0);

    Vec2i result;
    result[0] = (int) round( (x * rgbFX / z) + rgbCX );
    result[1] = (int) round( (y * rgbFY / z) + rgbCY );
    return result;
}

void map( Mat& rgb, Mat& depth ) {
    /* intrinsics are focal points and centers of camera */
    undistort( rgb, rgb, rgbIntrinsic, rgbDistortion );
    undistort( depth, depth, depthIntrinsic, depthDistortion );

    Mat color = Mat( depth.size(), CV_8UC3, Scalar(0) );
    ushort * raw_image_ptr;

    for( int y = 0; y < depth.rows; y++ ) {
        raw_image_ptr = depth.ptr<ushort>( y );

        for( int x = 0; x < depth.cols; x++ ) {
            if( raw_image_ptr[x] >= 2047 || raw_image_ptr[x] <= 0 )
                continue;

            float depth_value = depthMeters[ raw_image_ptr[x] ];
            Vec3f depth_coord = depthToW( y, x, depth_value );
            Vec2i rgb_coord   = wToRGB( depth_coord );
            color.at<Vec3b>(y, x) = rgb.at<Vec3b>(rgb_coord[0], rgb_coord[1]);
        }
    }

但结果似乎是错位的。我无法手动设置翻译,因为数据集是从 3 个不同的 Kinect 获得的,并且每个都在不同的方向上未对齐。您可以在下面看到其中一个(左:未失真的 RGB,中:未失真的深度,右:将 RGB 映射到深度)

在此处输入图像描述

我的问题是,此时我该怎么办?在尝试将深度投影到世界或将世界投影回 RGB 时,我是否错过了一步?任何有立体相机经验的人都可以指出我的失误吗?

4

4 回答 4

1

我假设您需要使用 RGB 数据校准深度传感器,就像校准立体相机一样。OpenCV 有一些你可以利用的功能(和教程)。

其他一些可能有用的东西

  1. http://www.ros.org/wiki/kinect_calibration/technical
  2. https://github.com/robbeofficial/KinectCalib
  3. http://www.mathworks.com/matlabcentral/linkexchange/links/2882-kinect-calibration-toolbox 这包含有关如何做到这一点的论文。
于 2013-06-10T06:15:16.120 回答
0

OpenCV 没有将深度流与彩色视频流对齐的功能。但我知道“Kinect for Windows SDK”中有一个特殊的功能。MapDepthFrameToColorFrame

例如,我没有代码,但希望这是一个很好的起点。

更新: 这是使用带有 OpenCV 接口的 KinectSDK 将彩色图像映射到深度的相同示例(不是我的代码)。

于 2013-06-10T05:15:24.557 回答
0

看起来您在解决方案中没有考虑两个相机之间的外在因素。

于 2016-07-14T12:24:09.683 回答
0

是的,你没有考虑 RGB 和 Depth 之间的转换。但是您可以使用 cvStereoCalibrate() 方法计算此矩阵,该方法只需将 RGB 和深度的图像序列以及棋盘角传递给它。您可以在 OpecvCV 文档中找到详细信息:http: //docs.opencv.org/2.4/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html#double stereoCalibrate(InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints1, InputArrayOfArrays imagePoints2, InputOutputArray cameraMatrix1, InputOutputArray distCoeffs1, InputOutputArray cameraMatrix2, InputOutputArray distCoeffs2, Size imageSize, OutputArray R, OutputArray T, OutputArray E, OutputArray F, TermCriteria criteria, int flags)

这背后的整个方法思想是:

color uv <- color normalize <- color space <- DtoC transformation <- depth space <- depth normalize <- depth uv (uc,vc) <- <- ExtrCol * (pc) <- stereo calibrate MAT <- ExtrDep^- 1 * (pd) <- <(ud - cx)*d / fx, (vd-cy)*d/fy, d> <- (ud, vd)

如果要为 RGB 添加失真,只需按照以下步骤操作: http: //docs.opencv.org/2.4/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html

于 2016-09-20T17:33:38.387 回答