【问题标题】:3D Mapping depth to RGB (Kinect OpenNI Depthmap to OpenCV RGB Cam)3D Mapping depth to RGB (Kinect OpenNI Depthmap to OpenCV RGB Cam)
【发布时间】:2013-06-28 20:19:03
【问题描述】:

我正在尝试将我的 OpenNI (1.5.4.0) Kinect 4 Windows Depthmap 映射到 OpenCV RGB 图像。

我的深度图为 640x480,深度为 mm,我正在尝试像 Burrus 一样进行映射: http://burrus.name/index.php/Research/KinectCalibration

我跳过了失真部分,否则我做了我想做的一切:

//with depth camera intrinsics, each pixel (x_d,y_d) of depth camera can be projected
//to metric 3D space. with fx_d, fy_d, cx_d and cy_d the intrinsics of the depth camera. 

P3D.at<Vec3f>(y,x)[0] = (x - cx_ir) * depth/fx_ir;
P3D.at<Vec3f>(y,x)[1] = (y - cy_ir) * depth/fy_ir;
P3D.at<Vec3f>(y,x)[2] = depth;


//P3D' = R.P3D + T:
RTMat = (Mat_<float>(4,4) << 0.999388, -0.00796202, -0.0480646, -3.96963,
0.00612322, 0.9993536, 0.0337474, -22.8512,
0.0244427, -0.03635059, 0.999173, -15.6307,
0,0,0,1);

perspectiveTransform(P3D, P3DS, RTMat);

//reproject each 3D point on the color image and get its color:  
depth = P3DS.at<Vec3f>(y,x)[2];
x_rgb =  (P3DS.at<Vec3f>(y,x)[0] * fx_rgb/ depth + cx_rgb;
y_rgb = (P3DS.at<Vec3f>(y,x)[1] * fy_rgb/ depth + cy_rgb;

但是根据我对 Kinect 的 RGB 摄像头和红外摄像头的估计校准值,我的结果在各个方向都失败了,并且不能仅通过更改外部 T 参数来修复。

我有几个怀疑:

  • OpenNi 是否已经将 IR Depthmap 映射到 Kinect?
  • 我应该使用以米为单位的深度和/或将像素转换为 毫米? (我尝试乘以 pixel_size * 0.001 但我得到了 结果相同)

真的希望有人可以帮助我。 提前谢谢。

【问题讨论】:

    标签: opencv mapping kinect openni


    【解决方案1】:

    AFAIK OpenNI 自己注册(出厂设置),您也可以切换注册。如果您已经构建了支持 OpenNI 的 OpenCV,那么就这么简单:

    capture.set(CV_CAP_PROP_OPENNI_REGISTRATION,1);
    

    正如 here 所解释的,还有一个最小的 OpenNI/OpenCV 示例 here。 所以一个最小的工作样本应该是这样的:

    #include "opencv2/core/core.hpp"
    #include "opencv2/highgui/highgui.hpp"
    
    #include <iostream>
    
    using namespace cv;
    using namespace std;
    
    int main(){
        VideoCapture capture;
        capture.open(CV_CAP_OPENNI);
        //registration
        if(capture.get( CV_CAP_PROP_OPENNI_REGISTRATION ) == 0) capture.set(CV_CAP_PROP_OPENNI_REGISTRATION,1);
    
        if( !capture.isOpened() ){
            cout << "Can not open a capture object." << endl;
            return -1;
        }
        cout << "ready" << endl;
    
        for(;;){
            Mat depthMap,depthShow;
            if( !capture.grab() ){
                cout << "Can not grab images." << endl;
                return -1;
            }else{
                if( capture.retrieve( depthMap, CV_CAP_OPENNI_DEPTH_MAP ) ){
                    const float scaleFactor = 0.05f;
                    depthMap.convertTo( depthShow, CV_8UC1, scaleFactor );
                    imshow("depth",depthShow);
                }
            }
            if( waitKey( 30 ) == 27 )    break;//esc to exit
        }
    
    }
    

    如果你没有构建支持 OpenNI 的 OpenCV,你应该可以使用 GetAlternativeViewPointCap()

    【讨论】:

    • 嗨..谢谢你的回答。看起来深度图自动映射到 RGB Kinect 相机。如果我理解正确,那也是你所说的。我没有使用 opencv 来获取我的深度图,并且我尝试使用 GetAlternativeViewPointCap() 来更改它(它受支持),但是当我尝试将其设置为 IR 相机时,我得到:“该值无效!”代码:IRGenerator ir; context.FindExistingNode(XN_NODE_TYPE_IR, ir); depth.GetAlternativeViewPointCap().SetViewPoint(ir);
    • 通常你会使用深度贴图和 rgb 贴图。您打算如何使用 IR 地图?
    • 不,我使用深度图。但由于它是用红外相机(深度图)拍摄的,所以我认为我使用红外相机的内在参数和外在参数将深度图映射到我第二张的 rgb 图像上非 kinect 相机..
    • 如果您想使用第二台非 kinect RGB 相机,是的,您需要进行手动校准。看看RGBDemo 或者更好的是RGBDToolkit。根据您最初的问题,我无法确定您在 kinect 旁边使用了另一台相机
    • 感谢您的回答。虽然这对我来说不是问题,但现在已经解决了..(校准方法中的一个错误,主要观点是映射在 x 轴上的距离太远了)
    猜你喜欢
    • 2014-08-29
    • 1970-01-01
    • 2017-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多