2016-03-16 24 views
5

Używam systemu stereo, więc staram się uzyskać współrzędne światowe niektórych punktów przez triangulację.OpenCV - przechylona kamera i punkt orientacyjny triangulacji dla widzenia stereo

Moje kamery przedstawiają kąt, kierunek osi Z (kierunek głębokości) nie jest normalny dla mojej powierzchni. Dlatego gdy obserwuję płaską powierzchnię, nie otrzymuję stałej głębokości, ale "liniową" zmianę, prawda? I chcę głębokość od linii bazowej ... Jak mogę przeprojektować?

enter image description here

Kawałek mojego kodu z moich rzutowych tablic i triangulacji funkcja:

#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,]) 

-------- później edytować -----------

Dzięki scribbleink, więc starałem się zastosować twoją propozycję. Ale myślę, że mam błąd, ponieważ nie działa dobrze, jak widać poniżej. Chmury punktów wydaje się być wypaczone i zakrzywione w kierunku krawędzi obrazu.

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

Czy możesz użyć macierzy projekcji do przekształcenia swoich punktów? –

+0

Dodaję uzupełnienia;) – user3601754

+0

Nie wiem, czy to możliwe – user3601754

Odpowiedz

5

Planowane oo kierunek jest arbitralne metody rekonstrukcji. Generalnie macie macierz rotacji, która obraca lewą kamerę od pożądanego kierunku. Możesz łatwo zbudować tę macierz R. Następnie wszystko, co musisz zrobić, to pomnożyć zrekonstruowane punkty przez transponowanie R.

+0

Użyłem R_0, który jest iloczynem macierzy obrotu 1 i 2 dostałem z każdą kalibracją kamery w celu triangulacji, ale nie wiem jak zbudować tę matrycę R ... Próbowałem zidentyfikować sztywne ruchy ciała przez dopasowanie planu w przypadku płaskiej próbki, ale to nie działa dobrze ... – user3601754

5

Aby dodać do odpowiedzi fireant, oto jedno rozwiązanie kandydata, zakładając, że oczekiwane X - kierunek pokrywa się z linią łączącą centra projekcji dwóch kamer.

  1. Obliczyć długości ogniskowe f_1 i f_2 (za pomocą kalibracji modelu otworkowego).
  2. Rozwiąż problem z lokalizacją epipolu kamery 2 w ramce kamery 1. W tym celu można użyć podstawowej matrycy (F) lub Essential matrix (E) pary kamer stereo. W szczególności, lewy i prawy epipoles leżą w przestrzeni zerowej F, więc możesz użyć Singular Value Decomposition. Aby uzyskać solidne teoretyczne odniesienie, patrz Hartley i Zisserman, drugie wydanie, Tabela 9.1 "Podsumowanie podstawowych właściwości matrycy" na stronie 246().
  3. Środek rzutowania kamery 1, tj. (0, 0, 0) i położenie prawego epipola, tj. (E_x, e_y, f_1) razem definiują promień, który jest wyrównany z linią łączącą centra kamery. Można go użyć jako oczekiwanego kierunku X. Nazwij ten wektor v_x.
  4. Przyjmując, że oczekiwana oś Y jest skierowana w dół w płaszczyźnie obrazu, tj. Od (0, 0, f_1) do (0, wysokość -1, f_1), gdzie f to długość ogniskowej. Nazwij ten wektor jako v_y.
  5. Oczekiwany kierunek Z jest teraz produktem krzyżowym wektorów v_x i v_y.
  6. Korzystając z oczekiwanego kierunku Z wraz z osią optyczną (oś Z) kamery 1, można obliczyć macierz obrotu z dwóch wektorów 3D za pomocą, powiedzmy, metody wymienionej w this other stackoverflow post.

Praktyczna uwaga: Spodziewając się płaski przedmiot dokładnie wyrównać z wyjściowo stereo jest mało prawdopodobne bez znacznego wysiłku, w moim doświadczeniu praktycznym. Konieczna byłaby pewna ilość dopasowania płaszczyzny i dodatkowego obrotu.

Jednorazowy nakład: To zależy od tego, czy trzeba to zrobić raz, na przykład do jednorazowej kalibracji, w takim przypadku po prostu dokonaj tego procesu szacowania w czasie rzeczywistym, a następnie obróć parę kamer stereo, aż zminimalizujesz wariancję mapy głębokości. Następnie zablokuj pozycję kamery i módl się, aby ktoś nie wpadł na nią później.

Powtarzalność: Jeśli trzeba zachować wyrównując planowanej mapy głębi naprawdę arbitralne Z-osi, które zmieniają się w każdej nowej ramki zrobione, to należy wziąć pod uwagę czas inwestowania w metodzie samolot-estymacji i czyni go bardziej wytrzymałe .

+0

Dzięki dla twojej pomocy jest to interesujące! spróbuję tego :) – user3601754