2013-08-05 12 views
5

Ich arbeite seit einiger Zeit an diesem Problem und bin am Ende meiner Kreativität, also hoffentlich kann jemand anderes mir helfen, in die richtige Richtung zu zeigen. Ich habe mit der Kinect gearbeitet und versucht, Daten in MATLAB zu erfassen. Glücklicherweise gibt es eine ganze Reihe von Möglichkeiten (ich verwende derzeit http://www.mathworks.com/matlabcentral/fileexchange/30242-kinect-matlab). Als ich versuchte, die aufgenommenen Daten in 3D zu projizieren, ergaben meine traditionellen Methoden schlechte Rekonstruktionsergebnisse.Warum kinect Farbe und Tiefe werden nicht richtig ausgerichtet?

Um es kurz zu machen, ich habe am Ende einen Kinect SDK Wrapper für Matlab geschrieben, der die Rekonstruktion und die Ausrichtung durchführt. Die Rekonstruktion funktioniert wie ein Traum, aber ...

Ich Tonnen Probleme mit der Ausrichtung, wie Sie hier sehen können:

enter image description here

Bitte nicht zu eng am Modell aussehen kann: (.

Wie Sie sehen können, die Ausrichtung nicht korrekt ist. ich bin nicht sicher, warum das der Fall ist. ich habe viele Foren gelesen, wo andere mehr Erfolg hatten, als ich mit den gleichen Methoden.

Meine aktuelle Pipeline verwendet Ki Mit Matlab (mit Openni) können Sie Daten erfassen, mit dem Kinect SDK rekonstruieren und dann mit dem Kinect SDK (von NuiImageGetColorPixelCoordinateFrameFromDepthPixelFrameAtResolution) ausrichten. Ich vermutete, dass es vielleicht an Openni lag, aber ich hatte wenig Erfolg beim Erstellen von mex-Funktionsaufrufen, um mit dem Kinect SDK zu erfassen.

Wenn mir jemand in eine Richtung zeigen kann, in die ich tiefer eindringen sollte, wäre es sehr geschätzt.

Bearbeiten:

Abbildung Ich sollte etwas Code veröffentlichen. Dies ist der Code, den ich für die Ausrichtung verwende:

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

Sie sollten andere wissen lassen, ob die Antworten auf Ihre Frage relevant waren und haben sie das Problem gelöst, das Sie waren. Wenn nicht, warum? So funktioniert diese Community – masad

+0

To masad: Ja danke für deine Antwort. Ich hatte keine Gelegenheit zu bestätigen, ob deine Antwort noch funktioniert, aber ich mache es jetzt. Lass es dich ein bisschen wissen. – vsector

Antwort

5

Dies ist ein bekanntes Problem für Stereo-Vision-Systeme. Ich hatte das gleiche Problem vor einiger Zeit. Die ursprüngliche Frage, die ich gepostet habe, kann here gefunden werden. Was ich versuchte, war dem ähnlich. Nach vielen Recherchen bin ich jedoch zu dem Schluss gekommen, dass ein erfasster Datensatz nicht einfach ausgerichtet werden kann.

Auf der anderen Seite, während der Aufzeichnung des Datensatzes können Sie einfach einen Funktionsaufruf verwenden, um sowohl die RGB-und Depth-Daten auszurichten. Diese Methode ist sowohl in OpenNI als auch in Kinect SDK verfügbar (die Funktionalität ist gleich, die Namen des Funktionsaufrufs sind jedoch unterschiedlich)

Es sieht so aus, als ob Sie Kinect SDK zum Erfassen des Datasets verwenden, um Daten mit dem Kinect SDK auszurichten kann MapDepthFrameToColorFrame verwenden.

Da Sie auch OpenNI erwähnt haben, werfen Sie einen Blick auf AlternativeViewPointCapability.

Ich habe keine Erfahrung mit Kinect SDK, jedoch mit OpenNI v1.5 das ganze Problem, indem die folgende Funktionsaufruf gelöst wurde, bevor Sie den Recorder Knoten Registrierung:

depth.GetAlternativeViewPointCap().SetViewPoint(image); 

wo image der Generator Knoten Bild ist und depth ist der Tiefengeneratorknoten. Dies war mit älteren SDK, die durch OpenNI 2.0 SDK ersetzt wurde. Wenn Sie also das neueste SDK verwenden, ist der Funktionsaufruf möglicherweise anders, die Vorgehensweise ist jedoch möglicherweise ähnlich.

ich auch einige Beispielbilder Zugabe:

ohne Verwendung der obigen Ausrichtungsfunktion, die Tiefe Kante auf RGB nennen wurden Without Alignment

nicht ausgerichtet, wenn der Funktionsaufruf unter Verwendung der Tiefenkante perfekt ausgerichtet wird (es sind einige Infrarot-Schattenbereiche, die einige Kanten zeigen, aber sie sind nur ungültige Tiefenbereiche) With Alignment

+0

Vielen Dank für die Antwort. Ich habe bereits eine Ausrichtung versucht, war aber nicht erfolgreich. Wie sich herausstellte, benutzte ich den richtigen Anruf, aber Kinect hat ein zusätzliches "Gotcha". In den "Common NUI Probleme und FAQs" (http://social.msdn.microsoft.com/Forums/en-US/4da8c75e-9aad-4dc3-bd83-d77ab4cd2f82/common-nui-problems-and-faq), Es listet auf, dass der von Kinect erhaltene Tiefenwert um 3 Bit verschoben werden muss, da der Spielerindex ebenfalls im Tiefenwert gespeichert ist. Nach der Anpassung funktioniert die Ausrichtung mit meinem ursprünglichen Code einwandfrei. Ich hätte das ohne deine Links nicht herausgefunden :). – vsector

+1

Ich werde Ihre Antwort als die Antwort festlegen, da sie auch einen signifikanten Hintergrund, Beispiel und Code für das Problem der Ausrichtung bietet. – vsector

1

enter image description here depth.GetAlternativeViewPointCap() SetViewPoint (Bild).

funktioniert gut, aber das Problem ist, dass es das Tiefenbild (von FOCAL_rgb/FOCAL_kinect) verkleinert und Tiefenpixel nach Disparität verschiebt d = fokal * B/z; Je nach Werkseinstellung kann es auch zu einer leichten Drehung kommen.

So kann man nicht mehr alle 3 Real World-Koordinaten wiederherstellen, ohne diese Transformationen rückgängig zu machen. Das heißt, die Methoden, die nicht von genauen x, y abhängen und nur z berücksichtigen (wie Segmentierung), können sogar in verschoben verschobenen Karten gut funktionieren. Darüber hinaus können sie sowohl Farbe als auch Tiefe nutzen, um eine bessere Segmentierung durchzuführen.

1

Sie können Tiefenrahmen und Farbrahmen leicht ausrichten, indem Sie die U/V-Texturabbildungsparameter mit dem Kinect SDK lesen. Für jede Pixelkoordinate (i, j) des Tiefenrahmens D (i, j) ist die entsprechende Pixelkoordinate des Farbrahmens gegeben durch (U (i, j), V (i, j)), so dass die Farbe gegeben ist durch C (U (i, j), V (i, j)). Die U- und V-Funktionen sind in der Hardware jeder Kinect enthalten und unterscheiden sich von Kinect bis Kinect, da die Depth-Kameras in Bezug auf die Videokameras aufgrund winziger Unterschiede unterschiedlich ausgerichtet sind, wenn sie werkseitig auf die Hardwarekarte geklebt werden . Aber Sie müssen sich darüber keine Gedanken machen, wenn Sie U, V aus dem Kinect SDK lesen.

Im Folgenden gebe ich Ihnen ein Bild Beispiel und eine tatsächliche Quellcode Beispiel das Kinect SDK in Java mit dem J4K open source library mit:

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

Bildbeispiel zeigt drei verschiedene Perspektiven der gleichen Tiefe-Video ausgerichtet Rahmen: enter image description here

Ich hoffe, dass dies Ihnen hilft!

Verwandte Themen