2013-05-10 97 views
1

我正在使用OpenNI 1.5.4.0和OpenCV 2.4.5,加上用于可视化目的(仅RGB图像)的Qt。 基本上,我是从一个超高动力学检索深度和RGB帧,并将它们存储在硬盘驱动器上,利用转换:cv :: Mat和XnDepthPixel之间的转换*

/* Depth conversion */ 

cv::Mat depth = cv::Mat(2, sizes, CV_16UC1, (void*) pDepthMap); //XnDepthPixel *pDepthMap 

/* RGB conversion */ 

///image is a QImage* , pImageMap is a XnUInt8* 

for(int i = 0; i < height; ++i) 
{ 
    for (unsigned y = 0; y < height; ++y) 
    { 
     uchar *imagePtr = (*image).scanLine(y); 
     for (unsigned x=0; x < width; ++x) 
     { 
      imagePtr[0] = pImageMap[2]; 
      imagePtr[1] = pImageMap[1]; 
      imagePtr[2] = pImageMap[0]; 
      imagePtr[3] = 0xff; 
      imagePtr+=4; 
      pImageMap+=3; 
     } 
    } 
} 

现在,我想加载从硬盘驱动器的那些图像,以计算3D点云作为后处理计算。 我加载深度图如下:

depth_image = cv::imread(m_rgb_files.at(w).toStdString(), CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR); 

但应用公式:

depth = depth_image.at<int>(j,i); //depth_image is stored as 16bit 
p.z = (float)depth * 0.001f; //converting from millimeters to meters 
p.x = (float)(i - m_params.center_x) * depth * m_params.focal_length; //focal_length read using OpenNI function 
p.y = (float)(j - m_params.center_y) * depth * m_params.focal_length; 

得到的点云是一个烂摊子。

如果我通过直接使用原生XnDepthPixel *数据进行“在线”处理,结果是完美的,使用前面写的公式。 有人可以给我一个关于我的错的“暗示”吗?

在此先感谢

编辑:我也跟随这resource,但它不为我工作,因为XnDepthPixel包含以毫米为现实世界的数据

+0

确定sorry..i我还是新来的平台 – madduci 2013-05-13 14:52:09

回答

0

我认为这里有一个可能出现的问题:

depth = depth_image.at<int>(j,i); //depth_image is stored as 16bit 

如果深度图像确实 16位,如果真的是:

depth = depth_image.at<short>(j,i); //depth_image is stored as 16bit 

因为int是32位,而不是16

+0

深度图实际上是10位+ 1位的有效性检查,但被存储到16位结构的无符号整型(称为XnDepthMap,它是uint16_t的重命名)。 我会尝试按照建议使用。我对uint16_t *和unsigned char *(不幸的是,它是cv :: Mat的默认构造函数)之间的转换(在保存步骤中)存在怀疑,这可能会影响结果。 感谢您的建议 – madduci 2013-05-12 08:44:55

+1

depth = depth_image.at (j,i); 做到了。 非常感谢 – madduci 2013-05-13 14:49:02

0

,正如另外,如果你已经建立的OpenCV与OpenNI支持,您可以检索深度图像作为cv::Mat您可以轻松地与cv::imwrite保存 这里有一个小例子:

#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); 

    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) == 115) {//s to save 
        imwrite("your_depth_naming_convention_here.png",depthShow); 
       } 
      } 
     } 
     if(waitKey(30) == 27) break;//esc to exit 
    } 

} 
+0

我没有直接使用OpenCV检索深度图,因为我使用了多个Kinect,并没有列举出其他设备,这就是为什么我切换到OpenNI纯API。无论如何,感谢您的建议 – madduci 2013-05-12 08:40:34

+0

您可以使用多个与OpenCV的kinects,我试过[此](http://stackoverflow.com/questions/14983248/how-to-initialize-multiple-openni-sensors-with-opencv)之前 – 2013-05-12 10:28:34

+0

感谢提示,但我已经尝试过目前为止,并没有为我工作。它无法枚举设备(我有修订版1473,两个PointCloudLibrary都无法检测到多个kinect)。 – madduci 2013-05-12 14:48:00