Kinect2: Von Bild- zu Weltkoordinaten transformieren



  • Hey!

    Ich weiß, das Thema gab's schon mal: https://www.c-plusplus.net/forum/282268-full
    Dabei hab ich die Lösung leider nicht verstanden.

    Also ich kann mittels Kinect ein 3D-Bild aufnehmen (zu jedem (x/y) Pixel gibts die entsprechende Tiefe von Tiefensensor... also z-Richtung dazu)

    Nun ist die z-Richtung in Meter angegeben. Die x und y Koordinaten jedoch in Pixel. Wie kann ich diese x und y Pixel-Koordinaten in Meter umrechnen?

    Ich denke es gibt dazu auch schon implementierte Funktionen in der SDK von Microsoft. Jedoch hab ich sie nicht gefunden. Wenn jemand hier Erfahrung hat (vor allem für die Kinect v2!) in C++ freue ich mich sehr!

    Lg Luki


  • Mod

    Ohne weitere Information (Auflösung und Bildformat der Kamera, Brennweite des Objektivs) gar nicht. Die noch nötigen Angaben sind natürlich durchaus beschaffbar, danach ist der Rest simple Geometrie. Oder du kannst die nötigen Faktoren selber messen, indem du einen Zollstock fotografierst. Gibt doch auch tausende von Treffern bei Google zu dieser Frage, so dass du das gar nicht selber tun brauchst:
    Google: kinect world coordinates



  • Hey!

    Hab mir das nochmal angeschaut und komme einfach nicht auf die Lösung. Anscheinend ist mein Weg einfach der falsche...

    Hab mich an folgende mathematische Vorgehensweise gehalten:

    x- und y- Koordinaten eines Punktes ist gegeben (in Pixel)
    z- Koordinate eines Punktes ist gegeben (in Meter)
    Ziel: Umrechnen von Pixel auf Meter der x- und y-Koordinaten

    FOV_vertikal = 60°; (Field of view)
    FOV_horizontal = 70°;
    h = 424 (Höhe in Pixel);
    w = 512 (Breite in Pixel);

    f = h / (2tan(60/2)); (Focal length - vertikal)
    f2 = w / (2
    tan(70/2)); (Focal length - horizontal)

    NUN die Transformation in Weltkoordinaten (von Pixel in Meter):
    xw = zw * xv / f2;
    yw = zw * yv / f;

    xw und yw sollen die Koordinaten in Meter sein... Seht ihr in der Vorgehensweise einen Fehler, oder stimmt das so? Ich habe durch 4 Punkte 3 Vektoren aufgestellt (Ein Ursprung + 3 Punkte die die jeweiligen Achsen eines Koordinatensystems widerspiegeln sollen) und komme dabei auf falsche Werte (die Achsen haben keine 90° zueinander). Vielleicht könnt ihr mir einen Tipp geben?

    Lg,
    Lukas



  • ... hab's gerade gelöst!

    Die Lösung war die x-y-Pixel der einzelnen Punkte zu "zentrieren".
    Also:
    xv = (512/2)-xv;
    yv = (424/2)-yv;

    Jetzt klappts!


  • Mod

    Lucanics_Bywalker12 schrieb:

    Ich habe durch 4 Punkte 3 Vektoren aufgestellt (Ein Ursprung + 3 Punkte die die jeweiligen Achsen eines Koordinatensystems widerspiegeln sollen) und komme dabei auf falsche Werte (die Achsen haben keine 90° zueinander).

    Erzähl mal mehr!



  • Lucanics_Bywalker12 schrieb:

    ... hab's gerade gelöst!

    Die Lösung war die x-y-Pixel der einzelnen Punkte zu "zentrieren".
    Also:
    xv = (512/2)-xv;
    yv = (424/2)-yv;

    Dier Punkt, den Du da verwendet, hat auch eine besondere Bedeutung. Man nennt ihn Hauptpunkt oder im Englischen auch "Principal Point". Normalerweise liegt der auch in der Nähe der Bildmitte, also wird das sicher eine einigermaßen brauchbare Näherung sein. Physikalisch ist der Punkt – ausgehend vom Lochkameramodell – der Punkt in der Bildebene, der entsteht, wenn man vom Projektionszentrum ein Lot auf die Bildfläche fällt.

    Es gibt natürlich Kalibriermethoden, die auch den Hauptpunkt bestimmen können. Also, wenn Dir die 3D Koordinaten nicht passen, solltest Du Dich vielleicht ein bisschen mit dem Thema Kamerakalibrierung beschäftigen. Das kann beliebig komplex werden, wenn man z.B. auch noch die Linsenverzerrungen berücksichtigen will. 🙂

    Etwas nicht all zu kompliziertes ist das DLT-Verfahren. Da steckt man Punktkorrespondenzen rein, also Paare von 2D und 3D Koordinaten. Man benötigt mindestens 6, glaub'ich; denn je Korrespondenz ergeben sich zwei unabhängige Gleichungen, wobei der Lösungsraum 11-dimensional ist. Das müsste in OpenCV implementiert sein. Die resultierende DLT-Matrix, lässt sich dann in zwei Matritzen so faktorisieren:

    | f_x   s   p_x |          
    |  0   f_y  p_y | * [R|t]
    |  0    0    1  |
    

    wobei das erste die "Kameramatrix" ist, die einem die Brennweite f in Pixeln angibt, einen Scherfaktor s (falls das Pixelgitter nicht orthogonal ist) und den Hauptpunkt p. R und t sind dann Rotationsmatrix und Translationsvector und ergeben zusammen eine 3x4 Matrix. Da stecken also die 11 Freiheitsgrade drin: 2 für die Brennweiten (falls die pixel nicht quadratisch sind), einen für den Scherfaktor, zwei für den Hauptpunkt, drei für die Rotationsmatrix und nochmal 3 für den Translationsvector. Allerdings ist es sinnvoll, das weiter einzuschränken. Man kann nämlich bei den digitalen Kameras davon ausgehen, dass das Pixelgitter orthogonal ist (s=0). Außerdem weiß man auch das Seitenverhältnis der Pixel schon vorher, meist quadratisch (f_x = f_y). Dann bleiben noch 9 Freiheitsgrade übrig. 🙂


Anmelden zum Antworten