2015-08-26 16 views
65

Sto cercando di ottenere le coordinate 3D di diversi punti nello spazio, ma sto ottenendo risultati strani da entrambi undistortPoints() e triangulatePoints().OpenCV undistortPoints e triangulatePoint danno risultati strani (stereo)

Dal momento che entrambe le fotocamere hanno una risoluzione diversa, li ho calibrato separatamente, ha ottenuto gli errori RMS di 0,34 e 0,43, poi utilizzato stereoCalibrate() per ottenere più matrici, ha ottenuto un RMS di 0,708, e poi utilizzato stereoRectify() per ottenere matrici rimanenti. Con quello in mano ho iniziato il lavoro sulle coordinate raccolte, ma ottengo risultati strani.

Ad esempio, l'ingresso è: (935, 262), e l'uscita è undistortPoints()(1228.709125, 342.79841) per un punto, mentre un'altra è (934, 176) e (1227.9016, 292.4686) rispettivamente. Il che è strano, perché entrambi questi punti sono molto vicini al centro dell'inquadratura, dove le distorsioni sono le più piccole. Non mi aspettavo che li spostasse di 300 pixel.

Passando a traingulatePoints(), i risultati diventano ancora più strani: ho misurato la distanza tra tre punti nella vita reale (con un righello) e calcolato la distanza tra i pixel su ciascuna immagine. Poiché questa volta i punti erano su un piano piuttosto piatto, queste due lunghezze (pixel e reale) corrispondevano, come in | AB |/| BC | in entrambi i casi era intorno al 4/9. Tuttavia, triangulatePoints() mi dà risultati fuori dai binari, con | AB |/| BC | essere 3/2 o 4/2.

Questo è il mio codice:

double pointsBok[2] = { bokList[j].toFloat()+xBok/2, bokList[j+1].toFloat()+yBok/2 }; 
cv::Mat imgPointsBokProper = cv::Mat(1,1, CV_64FC2, pointsBok); 

double pointsTyl[2] = { tylList[j].toFloat()+xTyl/2, tylList[j+1].toFloat()+yTyl/2 }; 
//cv::Mat imgPointsTyl = cv::Mat(2,1, CV_64FC1, pointsTyl); 
cv::Mat imgPointsTylProper = cv::Mat(1,1, CV_64FC2, pointsTyl); 

cv::undistortPoints(imgPointsBokProper, imgPointsBokProper, 
     intrinsicOne, distCoeffsOne, R1, P1); 
cv::undistortPoints(imgPointsTylProper, imgPointsTylProper, 
     intrinsicTwo, distCoeffsTwo, R2, P2); 

cv::triangulatePoints(P1, P2, imgWutBok, imgWutTyl, point4D); 

double wResult = point4D.at<double>(3,0); 
double realX = point4D.at<double>(0,0)/wResult; 
double realY = point4D.at<double>(1,0)/wResult; 
double realZ = point4D.at<double>(2,0)/wResult; 

Gli angoli tra i punti sono un pò sorta buona, ma di solito non:

`7,16816 168,389 4,44275` vs `5,85232 170,422 3,72561` (degrees) 
`8,44743 166,835 4,71715` vs `12,4064 158,132 9,46158` 
`9,34182 165,388 5,26994` vs `19,0785 150,883 10,0389` 

Ho cercato di utilizzare undistort() su tutto il telaio, ma ha ottenuto risultati altrettanto strano. La distanza tra B e punti C dovrebbe essere più o meno invariata in tutti i tempi, e tuttavia questo è ciò che ottengo:

7502,42  
4876,46 
3230,13 
2740,67 
2239,95 

fotogramma per fotogramma.

distanza Pixel (in basso) vs distanza reale (in alto) - dovrebbe essere molto simile: |BC| distance

Angolo:

ABC angle

Inoltre, dovrebbe non entrambi undistortPoints() e undistort() dare lo stesso risultati (un'altra serie di video qui)?
enter image description here

+0

Potrebbe includere il codice utilizzato per la calibrazione e alcune immagini di esempio per la parte di triangolazione? – AldurDisciple

+0

Questo potrebbe essere difficile ... ce n'è molto. Cercherò di postare solo le parti rilevanti domani – Petersaber

+0

Questa sembra una calibrazione incasinata - se si usa 'undistort' su un'immagine da una sola telecamera (ignorando la calibrazione stereo), funziona? Dovresti essere in grado di calibrare le intrinseche di ciascuna telecamera individualmente e assicurarti che siano OK e quindi passare quei valori alla calibrazione stereo come ipotesi iniziale usando il flag 'CV_CALIB_USE_INTRINSIC_GUESS'. – abarry

risposta

1

La funzione cv :: undistort esegue una distorsione e una riproiezione in una volta sola.Si esegue il seguente elenco di operazioni:

  1. di annullamento fotocamera proiezione (moltiplicazione con l'inversa della matrice telecamera)
  2. applicare il modello distorsione per annullare la distorsione
  3. rotazione dalla matrice di rotazione fornito R1/R2
  4. punti progetto di immagine utilizzando la condizione P1 matrice della proiezione/P2

Se passate le matrici R1, P1 resp. R2, P2 da cv :: stereoCalibrate(), i punti di input saranno non distorti e rettificati. La rettifica significa che le immagini vengono trasformate in modo tale che i punti corrispondenti abbiano la stessa coordinata y. Non esiste una soluzione unica per la correzione delle immagini, poiché è possibile applicare qualsiasi conversione o ridimensionamento a entrambe le immagini, senza modificare l'allineamento dei punti corrispondenti. Detto questo, cv :: stereoCalibrate() può spostare un po 'il centro di proiezione (ad esempio 300 pixel). Se vuoi pura distorsione puoi passare una Matrix di identità (invece di R1) e la telecamera originale Matrix K (invece di P1). Questo dovrebbe portare a coordinate di pixel simili a quelle originali.

Problemi correlati