2013-08-05 137 views
5

我一直在研究這個問題已經有相當長的一段時間了,並且在我的創造力的最後,所以希望別人能幫助我指出正確的方向。我一直在使用Kinect並嘗試將數據捕獲到MATLAB。幸運的是有很多方法可以做到這一點(我目前使用http://www.mathworks.com/matlabcentral/fileexchange/30242-kinect-matlab)。當我試圖將捕獲的數據投影到3D時,我的傳統方法給出了較差的重建結果。簡而言之,我最終編寫了一個用於matlab的Kinect SDK包裝器,用於執行重構和對齊。重建工程就像一個夢,但是......爲什麼kinect顏色和深度不能正確對齊?

我有噸的麻煩與定位,你可以在這裏看到:

enter image description here

請不要在模型過於密切關注: (

正如你所看到的,對齊不正確。我不知道爲什麼是這樣的話,我讀過很多論壇在別人有比我更成功以相同的方法。

我目前的管道正在使用Ki nect Matlab(使用Openni)捕獲數據,使用Kinect SDK進行重構,然後使用Kinect SDK(NuiImageGetColorPixelCoordinateFrameFromDepthPixelFrameAtResolution)進行對齊。我懷疑這可能是由於Openni造成的,但我在使用Kinect SDK創建mex函數調用捕獲方面幾乎沒有成功。

如果有人能指出我應該深入研究的方向,那將是非常感謝。

編輯:

圖我應該發佈一些代碼。這是我用來對齊的代碼:

/* The matlab mex function */ 
    void mexFunction(int nlhs, mxArray *plhs[], int nrhs, 
      const mxArray *prhs[]){ 

     if(nrhs < 2) 
     { 
      printf("No depth input or color image specified!\n"); 
      mexErrMsgTxt("Input Error"); 
     } 

     int width = 640, height = 480; 

     // get input depth data 

     unsigned short *pDepthRow = (unsigned short*) mxGetData(prhs[0]); 
     unsigned char *pColorRow = (unsigned char*) mxGetData(prhs[1]); 

     // compute the warping 

     INuiSensor *sensor = CreateFirstConnected(); 
     long colorCoords[ 640*480*2 ]; 
     sensor->NuiImageGetColorPixelCoordinateFrameFromDepthPixelFrameAtResolution(
       NUI_IMAGE_RESOLUTION_640x480, NUI_IMAGE_RESOLUTION_640x480, 
       640*480, pDepthRow, 640*480*2, colorCoords); 
     sensor->NuiShutdown(); 
     sensor->Release(); 

     // create matlab output; it's a column ordered matrix ;_; 

     int Jdimsc[3]; 
     Jdimsc[0]=height; 
     Jdimsc[1]=width; 
     Jdimsc[2]=3; 

     plhs[0] = mxCreateNumericArray(3, Jdimsc, mxUINT8_CLASS, mxREAL); 
     unsigned char *Iout = (unsigned char*)mxGetData(plhs[0]); 

     for(int x = 0; x < width; x++) 
      for(int y = 0; y < height; y++){ 

       int idx = (y*width + x)*2; 
       long c_x = colorCoords[ idx + 0 ]; 
       long c_y = colorCoords[ idx + 1 ]; 

       bool correct = (c_x >= 0 && c_x < width 
         && c_y >= 0 && c_y < height); 
       c_x = correct ? c_x : x; 
       c_y = correct ? c_y : y; 

       Iout[ 0*height*width + x*height + y ] = 
         pColorRow[ 0*height*width + c_x*height + c_y ]; 
       Iout[ 1*height*width + x*height + y ] = 
         pColorRow[ 1*height*width + c_x*height + c_y ]; 
       Iout[ 2*height*width + x*height + y ] = 
         pColorRow[ 2*height*width + c_x*height + c_y ]; 

      } 

    } 
+0

你應該讓別人知道你的問題的答案是否相關,他們是否解決了你的問題。如果不是那麼爲什麼?這就是這個社區的工作原理 – masad

+0

對於masad:是的謝謝你的回覆。我還沒有機會確認你的答案是否有效,但我現在正在這樣做。會讓你知道一點。 – vsector

回答

5

這是一個衆所周知的立體視覺系統問題。我以前遇到過同樣的問題。我發佈的原始問題可以在here找到。我試圖做的是有點類似於這個。然而,經過大量研究後,我得出結論:捕獲的數據集不容易對齊。

另一方面,在記錄數據集時,您可以輕鬆使用函數調用來對齊RGB和深度數據。此方法在OpenNI和Kinect SDK中均可用(功能相同,但函數調用的名稱各不相同)

看起來您正在使用Kinect SDK來捕獲數據集,以便將數據與Kinect SDK進行對齊可以使用MapDepthFrameToColorFrame

既然你也提到使用OpenNI,看看AlternativeViewPointCapability

我有Kinect的SDK沒有經驗,但與OpenNI V1.5這整個問題是通過使下面的函數調用,登記記錄節點之前解決:

depth.GetAlternativeViewPointCap().SetViewPoint(image); 

其中image是圖像生成器節點depth是深度生成器節點。這是用OpenNI 2.0 SDK取代的舊SDK。因此,如果您使用的是最新的SDK,那麼函數調用可能會有所不同,但整體過程可能相似。

我還加入一些實例圖像:

在不使用上述對準功能呼籲RGB深度邊緣當使用該函數調用的深度邊緣被完全對準(無不是對齊 Without Alignment

是其表現出一定的邊緣部分紅外陰影區,但它們只是無效深度的區域) With Alignment

+0

謝謝你的回覆。我已經嘗試對齊,但沒有成功。事實證明,我正在使用正確的電話,但Kinect有一個額外的「陷阱」。在「常見NUI問題和常見問題」(http://social.msdn.microsoft.com/Forums/en-US/4da8c75e-9aad-4dc3-bd83-d77ab4cd2f82/common-nui-problems-and-faq)中,它列出從Kinect獲得的深度值必須按位移3,因爲玩家的索引也存儲在深度值中。調整後,使用我原來的代碼對齊工作正常。沒有你的鏈接,我不會發現這一點:)。 – vsector

+1

我將設置您的回答作爲答案,因爲它還提供了重要的背景,示例和代碼來解決問題。 – vsector

1

enter image description here depth.GetAlternativeViewPointCap()SetViewPoint(圖像)。

效果很好,但問題在於它縮小了深度圖像(通過FOCAL_rgb/FOCAL_kinect)並且通過視差d =焦點* B/z移動深度像素;根據出廠設置,也可能會有輕微的旋轉。

因此,如果不撤消這些轉換,就無法恢復所有3個真實世界座標。這就是說,不依賴於準確的x,y並且僅考慮z(例如分割)的方法即使在移位後的移位圖中也可以很好地工作。此外,他們可以利用顏色和深度來進行更好的分割。

1

通過使用Kinect SDK讀取U,V紋理映射參數,您可以輕鬆地調整深度幀和顏色幀。對於深度幀D(i,j)的每個像素座標(i,j),彩色幀的相應像素座標由(U(i,j),V(i,j))給出,由C(U(i,j),V(i,j))。

U,V功能包含在每個Kinect的硬件中,它們與Kinect和Kinect不同,因爲深度相機與視頻相機不同,因爲在工廠的硬件板上粘貼時存在微小的差異。但是如果您從Kinect SDK讀取U,V,則不必擔心。

下面我給你的圖像例,並使用超高動力學SDK中的Java與J4K open source library一個實際的源代碼示例:

public class Kinect extends J4KSDK{ 

    VideoFrame videoTexture; 

public Kinect() { 
    super(); 
    videoTexture=new VideoFrame(); 
} 

@Override 
public void onDepthFrameEvent(short[] packed_depth, int[] U, int V[]) { 
    DepthMap map=new DepthMap(depthWidth(),depthHeight(),packed_depth); 
    if(U!=null && V!=null) map.setUV(U,V,videoWidth(),videoHeight()); 
} 

@Override 
public void onVideoFrameEvent(byte[] data) {  
    videoTexture.update(videoWidth(), videoHeight(), data); 
} } 

示出相同的深度視頻對準的幀的3個不同角度的圖像例如: enter image description here

我希望這可以幫助你!