| Operatoren |
stationary_camera_self_calibration — Selbstkalibrierung einer stationären projektiven Kamera.
stationary_camera_self_calibration( : : NumImages, ImageWidth, ImageHeight, ReferenceImage, MappingSource, MappingDest, HomMatrices2D, Rows1, Cols1, Rows2, Cols2, NumCorrespondences, EstimationMethod, CameraModel, FixedCameraParams : CameraMatrices, Kappa, RotationMatrices, X, Y, Z, Error)
stationary_camera_self_calibration führt eine Selbstkalibrierung einer stationären projektiven Kamera durch. Stationär bedeutet hierbei, dass sich die Kamera nur um das optische Zentrum drehen und dabei zoomen darf. Das optische Zentrum darf also nicht verschoben werden. Projektive Kamera bedeutet hierbei, dass als Kameramodell eine Lochkamera verwendet wird, deren Abbildung durch eine projektive 3D-2D-Abbildung beschrieben werden kann. Insbesondere können radiale Verzeichnungen nur modelliert werden, wenn die Brennweite konstant bleibt. Falls die Kamera signifikante radiale Verzeichnungen aufweist, sollten diese mit change_radial_distortion_image zumindest näherungsweise beseitigt werden.
Das zugrundeliegende Kameramodell kann wie folgt beschrieben werden:
x = P * X .
Hierbei ist x ein homogener 2D-Vektor, X ein homogener 3D-Vektor und P eine homogene 3x4 Projektionsmatrix. Die Projektionsmatrix P lässt sich wie folgt zerlegen:
P = K * (R|t) .
Hierbei ist R eine 3x3 Rotationsmatrix und t ein inhomogener 3D-Vektor. Diese beiden Daten beschreiben die Lage der Kamera im Raum. Diese Konvention ist analog zu der bei camera_calibration verwendeten Konvention, d.h. für R=I und t=0 zeigt die x-Achse nach rechts, die y-Achse nach unten und die z-Achse nach vorne von der Bildebene weg. K ist die Kalibriermatrix der Kamera (die Kameramatrix), die sich wie folgt beschreiben lässt:
/ a*f s*f u \
K = | 0 f v | .
\ 0 0 1 /
Hierbei ist f die Brennweite der Kamera in Pixeln, a das Seitenverhältnis der Pixel, s ein Faktor, der die Schrägstellung der Bildachsen modelliert und (u,v) der Hauptpunkt der Kamera in Pixeln. In dieser Konvention entspricht die x-Achse der Spaltenachse und die y-Achse der Zeilenachse.
Da die Kamera stationär ist, kann man t=0 annehmen. Mit dieser Konvention sieht man leicht, dass die vierte Koordinate des homogenen 3D-Vektors X keinen Einfluss auf die Lage des projizierten 3D-Punktes hat. Somit kann man die vierte Koordinate auch auf 0 setzen und sieht, dass X als Punkt der unendlich fernen Ebene betrachtet werden kann, und somit eine Richtung im Raum repräsentiert. Mit dieser Konvention kann man die vierte Koordinate von X auch weglassen und X als inhomogenen 3D-Vektor betrachten, der als Richtungsvektor nur bis auf Skalierung bestimmt werden kann. Somit kann die obige Projektionsgleichung auch wie folgt geschrieben werden:
x = K * R * X .
Wenn man zwei Bilder desselben Punktes mit einer stationären Kamera aufnimmt, gilt folglich
x1 = K1 * R1 * X x2 = K2 * R2 * X
und somit
x2 = K2 * R2 * R1^-1 * K1^-1 * x1 = K2 * R12 * K1^-1 * x1 = H12 * x1 .
Wenn sich die Kameraparameter bei den zwei Aufnahmen nicht ändern, gilt K1=K2. Die beiden Bilder desselben 3D-Punktes sind folglich über eine projektive 2D-Abbildung miteinander verknüpft. Diese Abbildung kann mit proj_match_points_ransac bestimmt werden. Es ist zu beachten, dass die Reihenfolge der Koordinaten in den projektive 2D-Abbildungen in HALCON umgekeht ist als in der obigen Konvention. Außerdem ist zu beachten, dass proj_match_points_ransac ein Koordinatensystem verwendet, bei dem der Ursprung eines Pixels in seiner linken oberen Ecke liegt, während stationary_camera_self_calibration ein Koordinatensystem verwendet, dass dem Koordinatensystem von camera_calibration entspricht, bei dem der Ursprung eines Pixels in seiner Mitte liegt. Für die mit proj_match_points_ransac bestimmten projektive 2D-Abbildungen müssen noch die Zeilen und Spalten vertauscht werden und eine Verschiebung um (0.5,0.5) angewendet werden, so dass in HALCON statt H12 = K2*R12*K1^-1 gilt
/ 0 1 0.5 \ / 0 1 -0.5 \
H12 = | 1 0 0.5 | * K2 * R12 * K1^-1 * | 1 0 -0.5 |
\ 0 0 1 / \ 0 0 1 /
bzw.
/ 0 1 -0.5 \ / 0 1 0.5 \
K2 * R12 * K1^-1 = | 1 0 -0.5 | * H12 * | 1 0 0.5 | .
\ 0 0 1 / \ 0 0 1 /
Aus der obigen Gleichung können Bedingungsgleichungen für die Kameraparameter auf zwei Arten hergeleitet werden. Zum einen kann durch Elimination der Rotation eine Gleichung hergeleitet werden, die die Kameramatrizen mit der projektive 2D-Abbildung zwischen zwei Bildern verknüpft. Sei Hij die projektive Abbildung von Bild i nach Bild j. Dann gilt
Kj * Kj^T = Hij * Ki * Ki^T * Hij^T
Kj^-T * Kj^-1 = Hij^-T * Ki^-T * Ki^-1 * Hij^-1
Aus der zweiten Gleichung können lineare Gleichungen zur Bestimmung der Kameraparameter gewonnen werden. Dieses Verfahren wird von stationary_camera_self_calibration für EstimationMethod = 'linear' verwendet. Dabei werden für i alle in MappingSource verwendeten Bilder und für j alle in MappingDest verwendeten Bilder zur Aufstellung der Gleichungen benutzt. Nachdem die Kameraparameter bestimmt worden sind, kann die Rotation der Kamera in den einzelnen Bildern über die Gleichung Rij = Kj^-1*Hij*Ki und Bildung der Abbildungskette vom Referenzbild ReferenceImage aus berechnet werden. Aus der ersten Gleichung kann ein nichtlineares Verfahren zur Bestimmung der Kameraparameter durch Minimierung des folgenden Fehlers hergeleitet werden:
---- 2
\ || T T T ||
E = / || K * K - H * K * K * H ||
---- || j j ij i i ij ||
(i,j) in {(s,d)} F
Hierbei ist {(s,d)} wie beim linearen Verfahren die durch MappingSource und MappingDest gegebene Menge von überlappenden Bildern. Dieses Verfahren wird von stationary_camera_self_calibration für EstimationMethod = 'nonlinear' verwendet. Dabei werden die Kameraparameter mit den Ergebnissen des linearen Verfahrens initialisiert. Diese beiden Verfahren sind sehr schnell und lieferen akzeptable Ergebnisse, wenn die projektiven 2D-Abbildungen Hij hinreichend genau sind. Dazu ist es unerlässlich, dass die Bilder keine radialen Verzeichnungen aufweisen. Man sieht aber auch, dass die Bestimmung der Kameraparameter unabhängig von der Bestimmung der Rotationen erfolgt, und somit die möglichen Bedingungsgleichungen nicht vollst"ndig ausgeschöpft werden. Insbesondere kann man sehen, dass nicht erzwungen wird, dass die Projektionen desselben Punktes nahe beieinander liegen. Deswegen bietet stationary_camera_self_calibration als drittes Verfahren eine Bündelausgleichung an (EstimationMethod = 'gold_standard'). Dabei werden sowohl die Kameraparameter und Rotationen, als auch Richtungen im 3D (die oben angeführten Vektoren X), die zur Minimierung des folgenden Fehlers führen, in einer gemeinsamen Optimierung bestimmt:
n / m \
---- | ---- 2 |
\ | \ || || 1 2 2 |
E = / | / || x - K * R * X || + ------- * ( u + v ) |
---- | ----|| ij i i j || sigma^2 i i |
i=1 \ j=1 /
Hierbei werden nur Terme berücksichtigt, für die die rekonstruierte Richtung Xj im Bild i sichtbar ist. Als Startwerte für die Bündelausgleichung werden Parameter verwendet, die aus den Ergebnissen des nichtlinearen Verfahrens berechnet werden. Aufgrund der hohen Komplexität der Minimierung dauert die Bündelausgleichung erheblich länger als die beiden einfacheren Verfahren. Sie liefert aber auch signifikant bessere Ergebnisse, und sollte deshalb bevorzugt werden.
In jedem der drei Verfahren kann festgelegt werden, welche Kameraparameter bestimmt werden sollen. Die jeweils anderen Kameraparameter werden auf einem festen Wert gehalten. Die Festlegung erfolgt mit dem Parameter CameraModel, der ein Tupel von Werten enthält. CameraModel muss immer den Wert 'focus' enthalten, der festlegt, dass die Brennweite f bestimmt wird. Wenn CameraModel den Wert 'principal_point' enthält, wird der Hauptpunkt (u,v) der Kamera bestimmt, ansonsten wird er auf den Wert (ImageWidth/2,ImageHeight/2) gesetzt. Wenn CameraModel den Wert 'aspect' enthält, wird das Seitenverhältnis a der Pixel bestimmt, ansonsten wird es auf 1 gesetzt. Wenn CameraModel den Wert 'skew' enthält, wird die Schrägstellung s der Bildachsen bestimmt, ansonsten wird sie auf 0 gesetzt. Es sind nur bestimmte Kombinationen dieser Parameter erlaubt: 'focus', ['focus', 'principal_point'], ['focus', 'aspect'], ['focus', 'principal_point', 'aspect'] und ['focus', 'principal_point', 'aspect', 'skew'].
Zusätzlich zu den obigen Parametern ist es bei Verwendung von EstimationMethod = 'gold_standard' möglich mit dem Parameter Kappa die Verzeichung der Bilder zu schätzen. Hierfür kann in diesem Fall CameraModel um den Parameter 'kappa' erweitert werden. Kappa entspricht dem Verzeichnungsparemeter kappa des Divisionsmodells für Verzeichnungen (siehe camera_calibration).
Bei der Verwendung von EstimationMethod = 'gold_standard' zur Bestimmung des Hauptpunkts ist es möglich, weit vom Bildmittelpunkt entfernt liegende Schätzungen zu bestrafen. Hierzu kann ein Sigma an den Parameter 'principal_point:0.5' angehängt werden. Wird kein Sigma angegeben, so entfällt der Strafterm in der obigen Fehlerformel.
Der Parameter FixedCameraParams legt fest, ob sich die Kameraparameter pro Bild ändern können oder ob sie für alle Bilder als konstant angenommen werden sollen. Um eine Kamera zu kalibrieren und später mit der kalibrierten Kamera zu messen, ist nur FixedCameraParams = 'true' sinnvoll. Der Modus FixedCameraParams = 'false' ist hauptsächlich zur Berechnung von Mosaiken mit gen_spherical_mosaic sinnvoll, falls die Kamera bei der Aufnahme des Mosaiks gezoomt hat oder sich die Scharfstellung signifikant geändert hat. Falls ein Mosaik mit konstanten Kameraparametern berechnet werden soll, sollte natürlich auch FixedCameraParams = 'true' verwendet werden. Es ist zu beachten, dass für FixedCameraParams = 'false' in praktischen Anwendungen das Problem, speziell für Aufnahmen mit langen Brennweiten, sehr schlecht bestimmt ist. In diesen Fällen kann oft nur die Brennweite bestimmt werden. Deswegen ist es hier unter Umständen erforderlich, CameraModel = 'focus' zu wählen oder die Lage des Hauptpunktes einzuschränken, indem ein kleines Sigma für den Strafterm des Hauptpunktes gewählt wird.
Die Anzahl der Bilder, die zur Kalibrierung verwendet werden, wird in NumImages übergeben. Aus der Anzahl der Bilder ergeben sich Einschränkungen für das Kameramodell. So können bei der Verwendung von nur zwei Bildern selbst bei der Annahme von konstanten Kameraparametern nicht alle Parameter bestimmt werden. Hier sollte sinnvollerweise die Schrägstellung der Bildachsen auf 0 gesetzt werden, indem 'skew' nicht in CameraModel aufgenommen wird. Falls FixedCameraParams = 'false' verwendet wird, können in keinem Fall alle Kameraparameter bestimmt werden. Hier sollte ebenfalls mindestens die Schrägstellung der Bildachsen auf 0 gesetzt werden. Weiterhin ist zu beachten, dass das Seitenverhältnis der Pixel nur korrekt bestimmt werden kann, wenn mindestens ein Bild um die optische Achse (die z-Achse des Kamerakoordinatensystems) gegenüber den anderen Bildern verdreht aufgenommen worden ist. Falls dies nicht der Fall ist, sollte die Bestimmung des Seitenverhältnisses unterdrückt werden, indem der Wert 'aspect' nicht in CameraModel aufgenommen wird.
Wie oben beschrieben, ist es zur Kalibrierung notwendig, dass mit proj_match_points_ransac für jedes überlappende Bildpaar die projektive Abbildung zwischen den zwei beteiligten Bildern bestimmt wird. So sind z.B. für einen 2x2 Block von Bildern in folgender Anordnung
+---+---+ | 1 | 2 | +---+---+ | 3 | 4 | +---+---+
unter der Annahme, dass sich alle Bilder gegenseitig überlappen, folgende projektive Abbildungen zu bestimmen: 1->2, 1->3, 1->4, 2->3, 2->4 und 3->4. Die Indizes der Bilder, die die jeweilige Abbildung bestimmen, werden in MappingSource und MappingDest übergeben. Die Indizes der Bilder beginnen ab 1. In obigem Beispiel ist also MappingSource = [1,1,1,2,2,3] und MappingDest = [2,3,4,3,4,4] zu verwenden. Die Gesamtanzahl von Bildern, die zur Kalibrierung verwendet wird, wird in NumImages übergeben. Sie wird verwendet, um zu überprüfen, ob jedes Bild über eine Kette von Abbildungen erreicht werden kann. Der Index des Referenzbildes wird in ReferenceImage übergeben. Dieses Bild erhält in der Ausgabe als Rotation die Einheitsmatrix.
Die zu den Bildpaaren gehörigen 3x3 projektiven Transformationsmatrizen werden in HomMatrices2D übergeben. Zusätzlich müssen in Rows1, Cols1, Rows2 und Cols2 die Koordinaten der zugeordneten Punktpaare in den einzelnen Bildpaaren übergeben werden. Sie können aus der Ausgabe von proj_match_points_ransac mit tuple_select oder mit der HDevelop-Funktion subset bestimmt werden. Damit stationary_camera_self_calibration bestimmen kann, zu welcher Abbildung ein Punktpaar gehört, muss in NumCorrespondences für jedes Bildpaar die Anzahl der gefundenen Zuordnungen übergeben werden.
Die berechneten Kameramatrizen Ki werden in CameraMatrices als 3x3 Matrizen zurückgegeben. Für FixedCameraParams = 'false' werden NumImages Matrizen zurückgegeben. Da für FixedCameraParams = 'true' alle Kameramatrizen identisch sind, wird in diesem Fall nur eine Kameramatrix zurückgegeben. Die berechneten Rotationen Ri werden in RotationMatrices als 3x3 Matrizen zurückgegeben. RotationMatrices enthält NumImages Matrizen.
Falls EstimationMethod = 'gold_standard' verwendet wird, werden in (X, Y, Z) die rekonstruierten Richtungen Xj zurückgegeben. Zusätzlich wird in Error der mittlere Projektionsfehler der rekonstruierten Richtungen zurückgegeben. Dies kann verwendet werden, um zu überprüfen, ob die Optimierung zu sinnvollen Werten konvergiert ist.
Falls die berechneten Kameraparameter zur Projektion von 3D-Punkten oder 3D-Richtungen in das Bild i verwendet werden sollen, sollte die jeweilige Kameramatrix mit der Rotationsmatrix multipliziert werden (mit hom_mat2d_compose).
Anzahl der verschiedenen Bilder, die zur Kalibrierung verwendet werden.
Restriktion: NumImages >= 2
Breite der Bilder, aus denen die Punkte extrahiert wurden.
Restriktion: ImageWidth > 0
Höhe der Bilder, aus denen die Punkte extrahiert wurden.
Restriktion: ImageHeight > 0
Index des Referenzbildes.
Indizes der Ausgangsbilder der Transformationen.
Indizes der Zielbilder der Transformationen.
Array von 3x3 projektiven Transformationsmatrizen.
Zeilenkoordinaten korrespondierender Punkte in den jeweiligen Ausgangsbildern.
Spaltenkoordinaten korrespondierender Punkte in den jeweiligen Ausgangsbildern.
Zeilenkoordinaten korrespondierender Punkte in den jeweiligen Zielbildern.
Spaltenkoordinaten korrespondierender Punkte in den jeweiligen Zielbildern.
Anzahl der Punktkorrespondenzen im jeweiligen Bildpaar.
Schätzalgorithmus für die Kalibrierung.
Defaultwert: 'gold_standard'
Werteliste: 'gold_standard', 'linear', 'nonlinear'
Verwendetes Kameramodell.
Defaultwert: ['focus','principal_point']
Werteliste: 'aspect', 'focus', 'kappa', 'principal_point', 'skew'
Sind die Kameraparameter für alle Bilder identisch?
Defaultwert: 'true'
Werteliste: 'false', 'true'
(Array von) 3x3 projektiven Kameramatrizen, die die internen Kameraparameter bestimmen.
Radiale Verzeichnung der Kamera.
Array von 3x3 Transformationsmatrizen, die die Rotation der Kamera im jeweiligen Bild bestimmen.
Richtungsparameter in X-Richtung aller Punkte, wenn EstimationMethod = 'gold_standard' verwendet wird.
Richtungsparameter in Y-Richtung aller Punkte, wenn EstimationMethod = 'gold_standard' verwendet wird.
Richtungsparameter in Z-Richtung aller Punkte, wenn EstimationMethod = 'gold_standard' verwendet wird.
Durchschnittlicher Fehler pro rekonstruiertem Punkt, wenn EstimationMethod = 'gold_standard' verwendet wird.
* Assume that Images contains four images in the layout given in the
* above description. Then the following example performs the camera
* self-calibration using these four images.
From := [1,1,1,2,2,3]
To := [2,3,4,3,4,4]
HomMatrices2D := []
Rows1 := []
Cols1 := []
Rows2 := []
Cols2 := []
NumMatches := []
for J := 0 to |From|-1 by 1
select_obj (Images, ImageF, From[J])
select_obj (Images, ImageT, To[J])
points_foerstner (ImageF, 1, 2, 3, 100, 0.1, 'gauss', 'true', \
RowsF, ColsF, _, _, _, _, _, _, _, _)
points_foerstner (ImageT, 1, 2, 3, 100, 0.1, 'gauss', 'true', \
RowsT, ColsT, _, _, _, _, _, _, _, _)
proj_match_points_ransac (ImageF, ImageT, RowsF, ColsF, RowsT, ColsT, \
'ncc', 10, 0, 0, 480, 640, 0, 0.5, \
'gold_standard', 2, 42, HomMat2D, \
Points1, Points2)
HomMatrices2D := [HomMatrices2D,HomMat2D]
Rows1 := [Rows1,subset(RowsF,Points1)]
Cols1 := [Cols1,subset(ColsF,Points1)]
Rows2 := [Rows2,subset(RowsT,Points2)]
Cols2 := [Cols2,subset(ColsT,Points2)]
NumMatches := [NumMatches,|Points1|]
endfor
stationary_camera_self_calibration (4, 640, 480, 1, From, To, \
HomMatrices2D, Rows1, Cols1, \
Rows2, Cols2, NumMatches, \
'gold_standard', \
['focus','principal_point'], \
'true', CameraMatrix, Kappa, \
RotationMatrices, X, Y, Z, Error)
Sind die Parameterwerte korrekt, dann liefert stationary_camera_self_calibration den Wert 2 (H_MSG_TRUE). Gegebenenfalls wird eine Fehlerbehandlung durchgeführt.
proj_match_points_ransac, proj_match_points_ransac_guided
Lourdes Agapito, E. Hayman, I. Reid: „Self-Calibration of Rotating and Zooming Cameras“; International Journal of Computer Vision; vol. 45, no. 2; pp. 107--127; 2001.
Calibration
| Operatoren |