5.22. Objektiv- und Perspektivkorrektur¶
Zwei Klassen der geometrischen Korrektur verzerren das Bild auf eine Weise, die eine Rechteck-zu-Rechteck-Abbildung nicht leisten kann. Die Objektivkorrektur macht die radiale Verzerrung rückgängig, die ein echtes Weitwinkelobjektiv einbringt – die Fischaugen-Wölbung, die gerade Linien der Szene in der Nähe der Bildecken in sichtbare Kurven biegt. Die Perspektivkorrektur macht den Trapezeffekt rückgängig, der entsteht, wenn das Objektiv nicht senkrecht auf die Szene gerichtet ist – die trapezförmige Verzerrung, die ein bekanntes Rechteck in der Welt zu einem nicht-rechteckigen Gebilde im Bild macht. Beide Korrekturen machen nach der Aufnahme Effekte rückgängig, die optischen Ursprungs sind.
5.22.1. Radiale Objektivverzerrung¶
Das Material zu echten Objektiveffekten beschreibt die Tonnen-Verzerrung, die preiswerte Weitwinkelobjektive einbringen. Pixel nahe der Bildmitte liegen ungefähr dort, wo das Lochkameramodell sie vorhersagt; Pixel nahe den Rändern werden nach außen gewölbt, und zwar um einen Betrag, der mit dem Quadrat des radialen Abstands von der optischen Achse wächst. Eine gerade Linie in der Szene, die nahe am Bildrand verläuft, krümmt sich im aufgenommenen Bild sichtbar, und jeder klassische Algorithmus für maschinelles Sehen, der davon ausgeht, dass gerade Linien gerade bleiben – AprilTag-Eckenerkennung, Kantenverfolgung, linienfolgende Navigation – liefert in der Nähe der Ecken das falsche Ergebnis.
lens_corr() macht die Verzerrung rückgängig. Die Methode führt die inverse Abbildung aus: Jeder Ausgabepixel wird von der Position im Eingabebild abgetastet, von der das Objektiv ihn nach außen gewölbt hätte, und das Ergebnis ist ein geometrisch gerades Bild.
img.lens_corr(strength=1.8)
Der Parameter strength ist das Herzstück der Korrektur. Es ist eine einzelne Zahl, die beschreibt, wie stark das Objektiv wölbt; ein Wert nahe 1.0 ist eine milde Korrektur für ein mäßig weitwinkliges Objektiv, und Werte bis etwa 2.0 sind für ein starkes Fischauge angemessen. Der Standardwert 1.8 ist ein vernünftiger Ausgangspunkt für die serienmäßigen OpenMV Cam-Objektive; der richtige Wert für ein bestimmtes Objektiv ist eine Frage des Ausprobierens und der Beobachtung des Bildes.
Die beiden Nebenparameter sind in der Regel mit ihren Standardwerten gut bedient. zoom (Standard 1.0) skaliert die Ausgabe – ein Wert größer als eins beschneidet nach außen, um auszugleichen, dass die Objektivkorrektur die Ecken weiter nach außen schiebt; kleinere Werte lassen mehr der korrigierten Szene sichtbar, allerdings auf Kosten von leeren Pixeln an den Bildrändern. x_corr und y_corr verschieben das Zentrum der Korrektur weg vom geometrischen Mittelpunkt des Bildes, was nützlich ist, wenn das Objektiv optisch nicht über dem Sensor zentriert ist (ein ungewöhnlicher Fall, aber gut zu wissen).
Eine typische Pipeline: aufnehmen, einmal lens_corr() ausführen, um die Geometrie zu begradigen, und dann das ausführen, was die Anwendung tatsächlich mit dem Ergebnis macht.
5.22.2. 3D-Rotationskorrektur¶
Die andere Klasse der geometrischen Verzerrung ist die perspektivische Verzerrung, die entsteht, wenn die Sensorebene nicht parallel zur Szenenebene ist. Der klassische Fall ist ein Schild oder ein Nummernschild, das von unten betrachtet wird: Der obere Teil des Schildes ist weiter vom Objektiv entfernt als der untere, projiziert sich also kleiner, und das aufgenommene Bild zeigt das Rechteck als Trapez, dessen obere Kante kürzer ist als die untere.
Die Lösung besteht darin, eine 3D-Rotation auf das aufgenommene Einzelbild anzuwenden, die die Sensorebene virtuell so neu ausrichtet, dass sie parallel zur Szenenebene liegt. Die Mathematik ist dieselbe perspektivische Abbildung, mit der die AprilTag-Erkennung die Pose eines Tags aus seinen vier Ecken zurückgewinnt, nur in umgekehrter Richtung ausgeführt: Bei gegebener Rotation bildet die Operation jeden Ausgabepixel auf die Eingabeposition zurück, von der die Rotation gekommen wäre.
rotation_corr() führt diese Korrektur aus:
img.rotation_corr(x_rotation=10.0, y_rotation=0.0, z_rotation=0.0)
Die drei Rotationsparameter sind in Grad angegeben und beschreiben Rotationen um die x-, y- und z-Achse einer virtuellen Kamera, die auf das Bild zentriert ist. x_rotation neigt die Kamera nach oben oder unten (die natürliche Korrektur für eine Aufnahme einer Wand vom Boden aus); y_rotation schwenkt die Kamera nach links oder rechts; z_rotation dreht die Kamera um ihre optische Achse (die natürliche Korrektur für eine schiefe Montage).
x_translation und y_translation bewegen die virtuelle Kamera seitlich, ohne sie zu drehen. zoom (Standard 1.0) skaliert die Ausgabe. fov (Standard 60.0) beschreibt das vertikale Sichtfeld der Kamera, das zur Berechnung der Projektion verwendet wird – der Wert sollte mit dem tatsächlichen Objektiv übereinstimmen, um die Geometrie konsistent zu halten.
Für eine beliebige Kombination aus Neigung und Schwenk lassen sich mehrere von null verschiedene Rotationen in einem einzigen Aufruf zusammensetzen. Die Reihenfolge der Operationen ist innerhalb der Implementierung festgelegt; die Anwendung liefert lediglich die Winkel und das Ergebnis kommt heraus.
5.22.3. Ein bekanntes Rechteck entzerren¶
Die am häufigsten nützliche Form von rotation_corr() ist das Schlüsselwort corners=, das eine Liste von vier (x, y)-Tupeln entgegennimmt, welche die Ecken eines bekannten Rechtecks im Eingabebild beschreiben. Die Methode berechnet, welche 3D-Rotation ein echtes Rechteck auf genau diese vier Punkte abgebildet hätte, wendet die inverse dieser Rotation auf das gesamte Bild an und liefert ein Ergebnis zurück, in dem das bekannte Rechteck wieder rechteckig ist:
plate_corners = [(45, 80), (300, 60), (310, 180), (40, 200)]
img.rotation_corr(corners=plate_corners)
Die klassische Anwendung ist genau das, was der Name vermuten lässt: ein Nummernschild (oder ein beliebiges anderes rechteckiges Merkmal), das aus einem schrägen Winkel fotografiert wurde. Eine vorgelagerte Stufe erkennt das Schild und meldet seine vier Eckpositionen im aufgenommenen Bild; werden diese Ecken an rotation_corr() übergeben, entsteht ein Bild, in dem das Schild als echtes Rechteck sitzt, bereit für die nachfolgende Stufe der Zeichenerkennung oder des Template-Matchings.
Wenn die Vier-Ecken-Form das Problem löst, das eine Anwendung zu lösen versucht, ist sie dramatisch nützlicher als die Sechs-Parameter-Form. Die Anwendung muss keine Rotationswinkel abschätzen; sie übergibt der Methode lediglich vier Punkte und überlässt es ihr, den Rest herauszufinden. Die Sechs-Parameter-Form ist nützlich, wenn in der Szene kein identifizierbares Rechteck sichtbar ist und die Rotation aus externem Wissen von Hand abgestimmt werden muss (etwa aus einem kalibrierten Montagewinkel).