2013-05-10 55 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