2016-03-16 15 views
5

Ich benutze eine Stereoanlage und so versuche ich, Welt Koordinaten von einigen Punkten durch Triangulation zu bekommen.OpenCV - Gekippte Kamera und Triangulation Wahrzeichen für Stereo Vision

Meine Kameras zeigen einen Winkel, die Richtung der Z-Achse (Richtung der Tiefe) ist nicht normal zu meiner Oberfläche. Deshalb, wenn ich flache Oberfläche beobachte, bekomme ich keine konstante Tiefe, sondern eine "lineare" Variation, richtig? Und ich möchte die Tiefe von der Basislinie aus ... Wie kann ich neu projizieren?

enter image description here

Ein Stück meines Code mit meinen projektiven Arrays und triangulieren Funktion:

#C1 and C2 are the cameras matrix (left and rig) 
#R_0 and T_0 are the transformation between cameras 
#Coord1 and Coord2 are the correspondant coordinates of left and right respectively 
P1 = np.dot(C1,np.hstack((np.identity(3),np.zeros((3,1))))) 

P2 =np.dot(C2,np.hstack(((R_0),T_0))) 

for i in range(Coord1.shape[0]) 
    z = cv2.triangulatePoints(P1, P2, Coord1[i,],Coord2[i,]) 

-------- EDIT SPäTER -----------

Danke scribblesink, also habe ich versucht, Ihren Vorschlag zu bewerben. Aber ich denke, ich habe einen Fehler, weil es nicht gut funktioniert, wie Sie unten sehen können. Und die Punktwolken scheinen verzerrt und zu den Bildrändern gekrümmt zu sein.

enter image description here

U, S, Vt = linalg.svd(F) 
V = Vt.T 

#Right epipol 
U[:,2]/U[2,2] 

# The expected X-direction with C1 camera matri and C1[0,0] the focal length 
vecteurX = np.array([(U[:,2]/U[2,2])[0],(U[:,2]/U[2,2])[1],C1[0,0]]) 
vecteurX_unit = vecteurX/np.sqrt(vecteurX[0]**2 + vecteurX[1]**2 + vecteurX[2]**2) 


# The expected Y axis : 
height = 2048 
vecteurY = np.array([0, height -1, 0]) 
vecteurY_unit = vecteurY/np.sqrt(vecteurY[0]**2 + vecteurY[1]**2 + vecteurY[2]**2) 


# The expected Z direction : 
vecteurZ = np.cross(vecteurX,vecteurY) 
vecteurZ_unit = vecteurZ/np.sqrt(vecteurZ[0]**2 + vecteurZ[1]**2 + vecteurZ[2]**2) 

#Normal of the Z optical (the current Z direction) 
Zopitcal = np.array([0,0,1]) 

cos_theta = np.arccos(np.dot(vecteurZ_unit, Zopitcal)/np.sqrt(vecteurZ_unit[0]**2 + vecteurZ_unit[1]**2 + vecteurZ_unit[2]**2)*np.sqrt(Zopitcal[0]**2 + Zopitcal[1]**2 + Zopitcal[2]**2)) 

sin_theta = (np.cross(vecteurZ_unit, Zopitcal))[1] 

#Definition of the Rodrigues vector and use of cv2.Rodrigues to get rotation matrix 
v1 = Zopitcal 
v2 = vecteurZ_unit 

v_rodrigues = v1*cos_theta + (np.cross(v2,v1))*sin_theta + v2*(np.cross(v2,v1))*(1. - cos_theta) 
R = cv2.Rodrigues(v_rodrigues)[0] 
+0

Können Sie eine Projektionsmatrix verwenden, um Ihre Punkte zu transformieren? –

+0

Ich füge Komplemente hinzu;) – user3601754

+0

Ich weiß nicht, ob es möglich ist – user3601754

Antwort

5

ist Ihre erwartete z-Richtung auf den Rekonstruktionsverfahren beliebig. Im Allgemeinen haben Sie eine Rotationsmatrix, die die linke Kamera aus Ihrer gewünschten Richtung dreht. Sie können diese Matrix, R einfach erstellen. Dann müssen Sie nur Ihre rekonstruierten Punkte mit der Transponierten von R multiplizieren.

+0

Ich habe R_0 verwendet, die das Produkt der Rotationsmatrix 1 und 2 ist habe mit jeder Kamera Kalibrierung, um zu triangulieren, aber ich weiß nicht, wie man diese Matrix R ... Ich habe versucht, eine Starrkörper Bewegungen durch die Anpassung eines Plans im Falle von flachen Probe, aber es funktioniert nicht gut ... – user3601754

5

Um die fireant Antwort hinzuzufügen, hier ist eine mögliche Lösung, unter der Annahme, dass die erwartete X Die Richtung stimmt mit der Linie überein, die die Projektionszentren der beiden Kameras verbindet.

  1. Die Brennweiten f_1 und f_2 (über Pinhole Model Kalibrierung) berechnen.
  2. Lösen Sie die Position des Kamera-2-Epipols im Rahmen der Kamera 1. Dazu können Sie entweder die Fundamental-Matrix (F) oder die Essential-Matrix (E) des Stereokamerapaars verwenden. Insbesondere liegen die linken und rechten Epipole im Nullraum von F, so dass Sie Singular Value Decomposition verwenden können. Für einen soliden theoretischen Bezug siehe Hartley und Zisserman, Zweite Auflage, Tabelle 9.1 "Zusammenfassung der grundlegenden Matrixeigenschaften" auf Seite 246 (freely available PDF of the chapter). Das Zentrum der Projektion der Kamera 1, d. H. (0, 0, 0), und der Ort des rechten Epipols, d. H. (E_x, e_y, f_1), definieren zusammen einen Strahl, der mit der Linie der Kamerazentren ausgerichtet ist. Dies kann als die erwartete X-Richtung verwendet werden. Nennen Sie diesen Vektor v_x.
  3. Angenommen, dass die erwartete Y-Achse in der Bildebene nach unten weist, d. H. Von (0, 0, f_1) bis (0, Höhe-1, f_1), wobei f die Brennweite ist. Nenne diesen Vektor als v_y.
  4. Die erwartete Z-Richtung ist jetzt das Kreuzprodukt der Vektoren v_x und v_y.
  5. Mit der erwarteten Z-Richtung zusammen mit der optischen Achse (Z-Achse) von Kamera 1 können Sie dann eine Rotationsmatrix aus zwei 3D-Vektoren berechnen, z. B. die in this other stackoverflow post aufgelistete Methode.

Praktische Anmerkung: das Objekt planar Erwartung zu genau mit der Stereo-Basis ist ohne großen Aufwand, in meiner praktischen Erfahrung unwahrscheinlich auszurichten. Ein gewisses Maß an Flugzeuganpassung und zusätzlicher Rotation wäre erforderlich.

Einmaliger Aufwand: Es hängt davon ab, ob Sie dies einmal tun müssen, z. für die einmalige Kalibrierung, in diesem Fall einfach diesen Schätzungsprozess in Echtzeit durchführen, dann drehen Sie Ihr Stereokamerapaar, bis die Varianz der Tiefenkarte minimiert ist. Sperren Sie dann Ihre Kamerapositionen und beten Sie, dass jemand später nicht darauf stößt.

Wiederholbarkeit: Wenn Sie Ihre geschätzten Tiefenkarten wirklich beliebige Z-Achsen halten müssen ausrichten, die erfasst für jeden neuen Rahmen zu ändern, dann sollten Sie Zeit in der Ebene-Schätzverfahren investieren und es robuster .

+0

Vielen Dank Für Ihre Hilfe ist es interessant! Ich werde das versuchen :) – user3601754

Verwandte Themen