8

Ich habe 5 Kameramatrizen berechnet (c1, ... c5), Kameramatrizen werden berechnet, indem ein 3D-Objekt an 5 verschiedenen Positionen platziert und für jede Position habe ich Kameramatrix berechnet (und Kamera ist konstant). Die Kameramatrix wird mit der SVD-Methode berechnet.Wie benutze ich Opencv Bundle Anpassung

Jetzt möchte ich Bündelanpassung in opencv verwenden, um eine optimale Kameramatrix zu erhalten. Ich fand die Dokumentation here

Aber Dokumentation ist nicht klar und auch ich konnte keinen Beispielcode finden. Kann mir jemand erklären, wie kann ich opencv Bundle-Anpassung verwenden, um die optimal camera matrix zu bekommen?

+0

Ihre Frage macht wenig Sinn, weil die Bündelanpassungstechnik normalerweise verwendet wird, um gemeinsam die Pose (dh T = [R | t], die die Orientierung und Position beschreibt) mehrerer Kameras und die 3D-Position einiger Beobachtungen zu schätzen Punkte. Um die Kameramatrix (dh K, die Matrix der intrinsischen Parameter) zu schätzen, würden Sie normalerweise ein Kalibrierungsverfahren verwenden, wie das hier [http://docs.opencv.org/2.4/doc/tutorials/calib3d/] camera_calibration/camera_calibration.html # cameracalibrationopencv). – AldurDisciple

+0

@AldurDisciple Bundle-Anpassung ist nicht auf verfeinern Pose beschränkt, könnten Sie definitiv die Gleichungen für die Verfeinerung K auch hinzufügen. Der OpenCV-Code tut dies. Es gibt zwar eine Maske, mit der Sie angeben können, welche Elemente von K optimiert werden sollen, oder keine. – fireant

+0

@fireant wahr, und gute Nachrichten, wenn OpenCV es unterstützt. Es ist jedoch immer noch unklar, ob das OP die Bundle Adjustments absichtlich erwähnte oder nur als eine Möglichkeit, eine gemeinsame Optimierung vorzunehmen. Es ist erwähnenswert, dass die Funktion "calibrateCamera" so konzipiert wurde, dass sie allgemeiner als der Standard-Kalibrierungsmuster-Fall ist und dass sie auch abstrakte 3D-Muster verarbeiten kann. – AldurDisciple

Antwort

7

Siehe Beispielcode auf Seite 155 von Learning Image Processing with OpenCV. Etwas wie folgt aus:

vector<CameraParams> cameras; 
vector<MatchesInfo> pairwise_matches; 
vector<ImageFeatures> features(num_images); 

// initialize the above params here 

Ptr<BundleAdjusterBase> adjuster; 
adjuster = makePtr<BundleAdjusterReproj>(); 
if (!(*adjuster)(features, pairwise_matches, cameras)) { 
    cout << "Camera parameters adjusting failed." << endl; 
    return -1; 
} 

Wenn Sie eine MCVE bieten dann ist es einfacher, zu helfen.

Bearbeiten: Vorausgesetzt, Sie haben 5 Schätzungen der gleichen K-Matrix. Die einfachste Methode besteht darin, einfach Ihre 5 Schätzungen zu mitteln, um ein genaueres K zu erhalten. Unter einigen milden Annahmen wird dies eine optimale Schätzung sein. Wenn sich die Reprojektionsfehler stark unterscheiden, können Sie einen gewichteten Durchschnitt berechnen.

+0

Ich denke, in diesem Beispiel ist jede Kameramatrix optimiert. Wie kann ich eine einzige endgültige Kameramatrix bekommen ??. – Deepak

+1

@ user_12 es scheint, ich habe Ihre Frage missverstanden. Siehe meine Bearbeitung. – fireant

5

Meine Antwort geht davon aus, dass Sie ein bestimmtes 3D-Objekt verwenden, der Abmessungen bekannt sind genau, die intrinsischen Parameter der eine Kamera zu schätzen, von mehr Bildern des Objekts. Angesichts Ihres Kommentars zu @firefants Antwort glaube ich, dass dies auf Ihre Frage zutrifft.

Quick Hinweis auf die Bedeutung von 'Kameramatrix'

Der Begriff 'Kamera Matrix' ist sehr vage und kann auf vielfältige Weise zu verstehen:

  • Die Kamera Pose T = [R | t ], auch als extrinsische Kameraparameter bezeichnet.
  • Die intrinsische Kameramatrix K = [fx, s, cx; 0, fy, cy; 0, 0, 1].
  • Die Kameraprojektionsmatrix P = K. [R | t].

Wie Sie sagen, dass Sie mehrere Bilder haben, aber Sie möchten eine einzige Kamera Matrix, denke ich, dass Sie über die intrinsische Kameramatrix sprechen K.

Warum sollten Sie nicht Bündelausgleichung verwenden

Bundle Adjustment ist eine Technik zur Lösung eines allgemeineren Problems als die Kamerakalibrierung, bei der sowohl die extrinsischen Kameraparameter (dh 3D-Orientierungen und -Positionen) als auch die 3D-Landmarken (z. B. 3D-Punkte) unbekannt sind. Wie @fireant bemerkt, ist es auch möglich, intrinsische Kameraparameter in diese globale Gelenkoptimierung einzubeziehen. Bei der Kamerakalibrierung wird dagegen davon ausgegangen, dass die 3D-Orientierungspunkte von einer einzelnen Kamera in mehreren Bildern erkannt und beobachtet werden. Daher wird für jedes Bild ein einzelner Satz intrinsischer Kameraparameter und eine Kamerapose optimiert.

Die Sache zu verstehen ist, dass allgemeinere Optimierungsprobleme beinhalten mehr Variablen zu optimieren, und es ist daher schwieriger, sie gut eingeschränkt zu machen.Wenn sie nicht gut eingeschränkt sind, werden sie Ihre Variablen auf eine Weise optimieren, die tatsächlich den globalen Fehler verringert, aber das entspricht nicht einer Lösung Ihres wirklichen Problems. Aus diesem Grund sollten Sie bei der Verwendung eines gemeinsamen Optimierungsalgorithmus immer versuchen, die Anzahl der zu optimierenden Variablen zu reduzieren.

Bei der VS-Kamerakalibrierung "Bundle Adjustment" sollten Sie die Bundle Adjustment nur verwenden, wenn Sie keine genaue Idee der Positionen der 3D-Landmarken haben. Auch dann ist es wahrscheinlich eine bessere Idee, die Probleme zu entkoppeln, zum Beispiel durch vorheriges Kalibrieren des 3D-Objekts. Wenn Sie eine genaue Vorstellung von den Positionen der 3D-Landmarken haben, sollten diese nicht als zu optimierende Variablen betrachtet werden. Daher sollten Sie die Kamera-Kalibrierungstechnik verwenden.

erste Schätzung für die Optimierung

Sie sagen, dass Sie mehrere ungenaue Schätzungen der Kamera Matrix K, und eine gemeinsame Optimierung durchführen möchten eine einzelne genauer ein zu erhalten. Das Problem besteht darin, dass Sie, da Sie eine einzelne Kameramatrix schätzen möchten, dem gemeinsamen Optimierungsalgorithmus nur eine erste Schätzung geben müssen.

Sie können, um Ihre Schätzungen immer noch zu verwenden, versuchen, als erste Schätzung für den Optimierungsalgorithmus denjenigen zu wählen, der der wahren Lösung am nächsten ist. Zu diesem Zweck können Sie mehrere heuristische Kriterien verwenden. Zum Beispiel können Sie den mit dem minimalen Reprojektionsfehler assoziierten auswählen, oder Sie können den mit dem Bild verbundenen verwenden, wenn das Kalibrierungsobjekt der größte ist, usw.

Allerdings wird es wahrscheinlich keinen großen Unterschied machen endgültige Schätzung der Kameramatrix.

Wie für diese Aufgabe ‚calibrateCamera‘ verwenden

Angenommen, Sie mit charakteristischen Punkten ein Kalibrierungsobjekt haben. Es kann ein Standard-2D-Schachbrett oder ein asymmetrisches Kreisraster oder ein kalibriertes 3D-Objekt sein. Und angenommen, Sie haben eine Möglichkeit entwickelt, dieses Kalibrierungsobjekt in einem Bild zu erkennen (z. B. einen benutzerdefinierten Feature-Detektor oder ein Werkzeug, um die Position des Objekts manuell zu bestimmen). Dann können Sie einen Vektor allObjectPoints definieren, der die 3D-Punkte auf dem Objekt enthält, die erkannt werden können. Dann können Sie für jedes Bild i einen Vektor imagePoints_i der 2D-Punkte bestimmen, die als Beobachtungen einiger der 3D-Punkte des Objekts erkannt wurden (beachten Sie, dass einige Objektpunkte möglicherweise verdeckt sind, daher weniger Elemente als in allObjectPoints). Dann, da alle Objektpunkte identifizierbar sind (entweder direkt oder durch Argumentation), kann der Vektor bestimmt werden, der das tatsächlich in Bild i beobachtete Objekt 3D-Punkte enthält, und beständiges Bestellen mit imagePoints_i.

Dann stapeln Sie alle Vektoren in einem großen Vektor von Vektoren objectPoints. Ähnlich stapeln Sie alle imagePoints_i Vektoren in einem großen Vektor von Vektoren imagePoints. Sie können dann den Aufruf an calibrateCamera mit dem Flag CV_CALIB_USE_INTRINSIC_GUESS vornehmen, um anzugeben, dass der Optimierungsalgorithmus den von Ihnen angegebenen Anfangswert verwenden soll.