2013-06-26 117 views
0

我试图将我的OpenNI(1.5.4.0)Kinect 4 Windows深度图映射到OpenCV RGB图像。三维映射深度到RGB(Kinect OpenNI深度图到OpenCV RGB凸轮)

我有深度图640×480,在毫米深度的试图做这样巴瑞斯的映射: 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; 

但我的估计的RGB摄像机和Kinect的红外摄像机的校准值,我的结果在每个方向都失败了,不能仅仅通过改变外部T参数来固定。

我有几个suspisions:

  • 没有OpenNi已经红外深度图映射到 的Kinect的RGB摄像头?
  • 我应该使用深度以米为单位还是将像素转换为 毫米? (我试图乘以pixel_size * 0.001但我得到了 相同的结果)

真的希望有人能帮助我。 Thx提前。

回答

1

AFAIK OpenNI是否自己注册(出厂设置),您也可以切换注册。如果你已经建立的OpenCV与OpenNI支持它是如此简单:

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 
    } 

} 

如果你没有跟OpenCV的支持OpenNI建,你应该能够使用GetAlternativeViewPointCap()

+0

您好.. THX你的答案。它看起来像深度图自动映射到RGB Kinect相机。如果我正确地理解了你,那你也是这么说的。 我没有使用opencv来获得我的深度图,我试图用GetAlternativeViewPointCap()(它支持)来改变它,但是当我尝试将它设置为红外摄像机时,我得到:“该值无效!” 代码:IRGenerator ir; context.FindExistingNode(XN_NODE_TYPE_IR,ir); depth.GetAlternativeViewPointCap()。SetViewPoint(ir); – ddd

+0

通常你会使用深度图和rgb图。您如何计划使用IR映射? –

+0

不,我使用深度图..但因为它是用红外摄像机(深度图)拍摄的,所以我用红外摄像机内在函数和外部参数来映射我的第二个非运动相机的RGB图像上的深度图。 – ddd