2015-08-26 10 views
65

Ich versuche, 3D-Koordinaten von mehreren Punkten im Raum zu bekommen, aber ich bekomme ungerade Ergebnisse von beiden undistortPoints() und triangulatePoints().OpenCV undistortPoints und triangulatePoint geben ungerade Ergebnisse (Stereo)

Da beide Kameras unterschiedliche Auflösungen haben, ich sie einzeln kalibriert habe, erhalten RMS-Fehler von 0,34 und 0,43, verwendet dann stereoCalibrate() mehr Matrizen zu erhalten, bekam einen RMS von 0,708, und verwendet dann stereoRectify() verbleibenden Matrizen zu erhalten. Damit habe ich die Arbeit an den gesammelten Koordinaten begonnen, aber ich bekomme seltsame Ergebnisse.

beispielsweise eingegeben wird: (935, 262) und der Ausgang ist undistortPoints()(1228.709125, 342.79841) für einen Punkt, während für den anderen und es ist (934, 176)(1227.9016, 292.4686) sind. Das ist komisch, weil diese beiden Punkte sehr nah an der Bildmitte liegen, wo Verzerrungen am kleinsten sind. Ich habe nicht erwartet, dass es sie um 300 Pixel bewegt.

Bei der Übergabe an traingulatePoints() werden die Ergebnisse noch seltsamer - ich habe den Abstand zwischen drei Punkten im wirklichen Leben (mit einem Lineal) gemessen und den Abstand zwischen den Pixeln auf jedem Bild berechnet. Da diesmal die Punkte auf einer ziemlich flachen Ebene lagen, stimmten diese beiden Längen (Pixel und Real) überein, wie in | AB |/| BC | in beiden Fällen war um 4/9. Aber triangulatePoints() gibt mir Ergebnisse von den Schienen, mit | AB |/| BC | 3/2 oder 4/2 sein.

Dies ist mein Code:

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; 

Die Winkel zwischen den Punkten sind ein bisschen sorta gut, aber in der Regel nicht:

`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` 

Ich habe versucht undistort() auf den gesamten Rahmen zu verwenden, aber bekam Ergebnisse genauso seltsam. Der Abstand zwischen B und C Punkte sollten so ziemlich unverändert zu allen Zeiten, und doch ist das, was ich bekommen:

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

Frame für Frame.

Pixelabstand (unten) vs realem Abstand (oben) - sollte sehr ähnlich sein: |BC| distance

Winkel:

ABC angle

Auch sollten nicht beide undistortPoints() und undistort() das gleiche geben Ergebnisse (weitere Videos hier)?
enter image description here

+0

Können Sie den für die Kalibrierung verwendeten Code und einige Beispielbilder für den Triangulationsteil hinzufügen? – AldurDisciple

+0

Das könnte schwierig sein ... es gibt eine Menge davon. Ich werde versuchen, morgen nur relevante Teile zu posten – Petersaber

+0

Das scheint wie eine verstimmte Kalibrierung - wenn Sie 'unverzerrt' auf einem Bild von nur einer Kamera verwenden (die Stereokalibrierung ignorierend), funktioniert es? Sie sollten in der Lage sein, die Eigen- schaften jeder Kamera einzeln zu kalibrieren und sicherzustellen, dass sie in Ordnung sind, und diese Werte dann als anfängliche Schätzung an die Stereokalibrierung übergeben, indem Sie das Flag "CV_CALIB_USE_INTRINSIC_GUESS" verwenden. – abarry

Antwort

1

Die Funktion cv :: undistort macht die Verzerrung und Reprojektion auf einen Schlag.Es führt die folgende Liste von Operationen aus:

  1. undo Kameraprojektion (Multiplikation mit dem Kehrwert der Kameramatrix)
  2. das Verzerrungsmodell anwenden, um die Verzerrung
  3. Drehen durch die vorgesehene Rotationsmatrix R1/R2 rückgängig zu machen
  4. Projekt verweist auf Bild, um die vorgesehene Projektionsmatrix P1 mit/P2

Wenn Sie die Matrizen R1, P1 bzw. passieren. R2, P2 von cv :: stereoCalibrate(), die Eingabepunkte werden unverzerrt und korrigiert. Rektifikation bedeutet, dass die Bilder so transformiert werden, dass entsprechende Punkte die gleiche y-Koordinate haben. Es gibt keine eindeutige Lösung für die Bildentzerrung, da Sie jede Translation oder Skalierung auf beide Bilder anwenden können, ohne die Ausrichtung der entsprechenden Punkte zu ändern. Das besagt, cv :: stereoCalibrate() kann das Projektionszentrum ziemlich weit verschieben (z. B. 300 Pixel). Wenn Sie reine Verzerrung wünschen, können Sie eine Identity Matrix (anstelle von R1) und die ursprüngliche Kamera Matrix K (anstelle von P1) übergeben. Dies sollte zu Pixel-Koordinaten ähnlich den ursprünglichen führen.

Verwandte Themen