2013-08-05 16 views
5

Ho lavorato a questo problema per un po 'di tempo e sono alla fine della mia creatività, quindi spero che qualcun altro possa aiutarmi a indicarmi la giusta direzione. Ho lavorato con Kinect e ho tentato di acquisire dati in MATLAB. Fortunatamente ci sono diversi modi per farlo (attualmente sto usando http://www.mathworks.com/matlabcentral/fileexchange/30242-kinect-matlab). Quando ho provato a proiettare i dati catturati in 3D, i miei metodi tradizionali hanno dato risultati di ricostruzione mediocri.Perché il colore e la profondità di kinect non si allineano correttamente?

Per farla breve, ho finito per scrivere un wrapper Kinect SDK per matlab che esegue la ricostruzione e l'allineamento. La ricostruzione funziona come un sogno, ma ...

Sto avendo un sacco di problemi con l'allineamento, come potete vedere qui:

enter image description here

Si prega di non guardare troppo da vicino il modello: (.

Come si può vedere, l'allineamento non è corretto. non so perché questo è il caso. ho letto un sacco di forum dove gli altri hanno avuto più successo di quanto io con gli stessi metodi.

La mia pipeline attuale utilizza Ki nect Matlab (usando Openni) per acquisire i dati, ricostruire utilizzando l'SDK Kinect, quindi eseguire l'allineamento utilizzando il Kinect SDK (di NuiImageGetColorPixelCoordinateFrameFromDepthPixelFrameAtResolution). Sospettavo che forse fosse dovuto a Openni, ma ho avuto scarso successo nel creare chiamate a funzioni di messaggistica da acquisire usando l'SDK Kinect.

Se qualcuno può indicarmi una direzione nella quale dovrei approfondire, sarebbe molto apprezzato.

Modifica:

Figura Dovrei pubblicare del codice. Questo è il codice che uso per l'allineamento:

/* 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

dovresti far sapere agli altri se le risposte alla tua domanda erano pertinenti e hanno risolto il problema che eri. se no allora perché? è così che funziona questa comunità – masad

+0

Per il masad: sì grazie per la risposta. Non ho avuto la possibilità di confermare se la tua risposta funziona ancora, ma lo sto facendo ora. Ti farò sapere un po '. – vsector

risposta

5

Questo è un problema ben noto per i sistemi di visione stereo. Ho avuto lo stesso problema un po 'di tempo fa. La domanda originale che ho postato può essere trovata here. Quello che stavo cercando di fare era un po 'simile a questo. Tuttavia, dopo molte ricerche sono giunto alla conclusione che un set di dati catturato non può essere facilmente allineato.

D'altra parte, durante la registrazione del set di dati è possibile utilizzare facilmente una chiamata di funzione per allineare sia i dati RGB che quelli di profondità. Questo metodo è disponibile in OpenNI e Kinect SDK (la funzionalità è uguale, mentre i nomi della chiamata di funzione sono diversi per ciascuno)

Sembra che si stia utilizzando Kinect SDK per acquisire il set di dati, per allineare i dati con Kinect SDK che si possibile utilizzare MapDepthFrameToColorFrame.

Dato che hai anche menzionato l'uso di OpenNI, dai un'occhiata a AlternativeViewPointCapability.

ho esperienza con Kinect SDK, ma con v1.5 OpenNI tutto questo problema è stato risolto con la seguente chiamata di funzione, prima di registrare il nodo registratore:

depth.GetAlternativeViewPointCap().SetViewPoint(image); 

dove image è il nodo generatore di immagini e depth è il nodo del generatore di profondità. Questo era con il vecchio SDK che è stato sostituito da OpenNI 2.0 SDK. Pertanto, se si utilizza l'SDK più recente, la chiamata alla funzione potrebbe essere diversa, tuttavia la procedura generale potrebbe essere simile.

Sono anche aggiungendo alcune immagini di esempio:

Senza utilizzare la funzione di allineamento sopra chiamare il bordo approfondite su RGB non erano allineati Without Alignment

Quando si utilizza la chiamata di funzione del bordo di profondità viene perfettamente allineato (ci sono alcune regioni d'ombra infrarossi che mostrano alcuni bordi, ma sono limitata profondità solo validi) With Alignment

+0

Grazie per la risposta. Ho già tentato l'allineamento, ma non ho avuto successo. A quanto pare, stavo usando la chiamata giusta, ma Kinect ha un "trucco" in più. Nella sezione "Problemi comuni e domande frequenti su NUI" (http://social.msdn.microsoft.com/Forums/en-US/4da8c75e-9aad-4dc3-bd83-d77ab4cd2f82/common-nui-problems-and-faq), indica che il valore di profondità ottenuto da Kinect deve essere spostato di bit di 3 poiché l'indice del giocatore viene anche memorizzato nel valore di profondità. Dopo la regolazione, l'allineamento usando il mio codice originale funziona correttamente. Non avrei trovato questo senza i tuoi link :). – vsector

+1

Ho impostato la risposta come risposta in quanto fornisce anche uno sfondo, un esempio e un codice significativi al problema dell'allineamento. – vsector

1

enter image description here depth.GetAlternativeViewPointCap() SetViewPoint (immagine).;

funziona bene ma il problema è che riduce l'immagine di profondità (di FOCAL_rgb/FOCAL_kinect) e sposta i pixel di profondità per disparità d = focale * B/z; a seconda delle impostazioni di fabbrica potrebbe esserci anche una leggera rotazione.

Quindi non è possibile ripristinare tutte e 3 le coordinate di Real World senza annullare queste trasformazioni. Detto questo, i metodi che non dipendono dall'accurata x, y prendono solo z (come la segmentazione) possono funzionare bene anche nella shifted map spostata. Inoltre possono sfruttare il colore e la profondità per ottenere una migliore segmentazione.

1

È possibile allineare facilmente telai di profondità e cornici a colori leggendo i parametri di mappatura della trama U, V utilizzando l'SDK Kinect. Per ogni coordinata di pixel (i, j) del fotogramma di profondità D (i, j) la coordinata di pixel corrispondente della cornice di colore è data da (U (i, j), V (i, j)) così il colore è dato di C (U (i, j), V (i, j)).

U, funzioni V sono contenuti nel hardware di ogni Kinect e si differenziano da Kinect Kinect quanto le telecamere profondità sono diversamente allineati rispetto alle telecamere video a causa di piccole differenze quando incollato sulla scheda hardware in fabbrica . Ma non devi preoccuparti di questo se leggi U, V dal Kinect SDK.

Qui di seguito vi do un esempio di immagine e un esempio reale di codice sorgente utilizzando il Kinect SDK in Java con l'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); 
} } 

esempio Immagine che mostra 3 diversi punti di vista dello stesso telaio allineato Profondità-Video: enter image description here

Spero che questo ti aiuti!