Die UniWB-Einstellung, Teil2

Einleitung

Im Folgenden wird die Begründung des im Teil 1 beschriebenen iterativen Verfahrens dargestellt.

Modell

Für die weitere Darstellung wird in guter Näherung davon ausgegangen, dass der Sensor linear arbeitet, d.h. dass sein Ausgangssignal der gesammelten Lichtmenge und damit der „Helligkeit“ des fotografierten Objekts, in unserem Fall das Monitorbild, proportional ist und dies für jeden Pixel in gleicher Weise gilt. In diesem Fall kann der Zusammenhang zwischen dem Sensor-Ausgangssignal für jedes Pixel (RAW-Bild) und der Objekthelligkeit bei einer festen Belichtungseinstellung (Belichtungszeit, Blende, ISO-Wert) wie folgt dargestellt werden:

\vec{F} = \{C\} \cdot \vec{H} + \vec{B}.

Dabei sind
\vec{F} der Vektor mit den Sensordaten  für die drei RGB-Farbkanäle
F_r, F_g und F_b,
\{C\} die Transformationsmatrix,
\vec{H} der Vektor mit den Helligkeiten der drei Grundfarben des Monitors und
\vec{B} der Vektor mit den Schwarzwerten des Sensors, d.h. den Sensorausgaben bei schwarzem Monitorbild.
Die Komponenten des Vectors \vec{H} ergeben sich aus dem Vektor \vec{S} mit den normierten RGB-Werten (R/255, G/255, B/255) für die Ansteuerung
des Monitors und seinem \gamma -Wert mit:
\vec{H} = \vec{S}^{\frac{1}{\gamma}}.

Manueller Weißabgleich

Beim manuellen Weißabgleich ermittelt die Kamerasoftware eine  Korrekturmatrix

\{W\} = Diag(K_r, 1.0, K_b) ,

so dass gilt:

\vec{G} = \{W\} \cdot \vec{F} = \{W\} \cdot(\{C\}\cdot \vec{H} + \vec{B}).

Dabei enthält der Grauwert-Vektor \vec{G} identische Werte in seinen Komponenten.

UniWB-Einstellung

Um eine UniWB-Einstellung zu erreichen, muss somit ein solcher Helligkeitsvektor \vec{H_W} auf dem Monitor dargestellt werden, dass die Kamerasoftware für \vec{W} die Einheitsmatrix \{E\}= Diag(1.0, 1.0, 1.0) ermittelt. Dieser Helligkeitsvektor lässt sich bei bekannter Transformationsmatrix und bekanntem Schwarzwertvektor aus einem vorgegebenen Grauwert gemäß den obigen Gleichungen ermitteln:

\vec{H_W}=\{C\}^{-1}\cdot(\vec{G}-\vec{B})

Die Ermittlung der Transformationsmatrix, des Schwarzwertvektors und des Gammawertes des Monitors ist mit einem entsprechend gestalteten Testbild und der Anwendung von Parameterschätzverfahren auf das RAW-Abbilds dieses Testbilds möglich. Und mit der obigen Gleichung lassen sich dann die Helligkeitswerte und die RGB-Signalwerte zur Ansteuerung des Monitors für ein Testbild zum manuellen Weißabgleich ermitteln. Ich habe dieses Verfahren auch erprobt, es funktioniert, ist aber sehr aufwändig und wenig praktikabel. Ich habe auch im Internet eine etwas abgespeckte Version gefunden, die mit nur drei Testfarben auskommt und die Schwarzwerte nicht berücksichtigt, aber selbst diese Variante ist mir zu „unhandlich“ und die Ergebnisse waren nicht optimal. Daher verwende ich das im folgenden dargestellte iterative Verfahren.

Iterativer UniWB-Abgleich

Aus der im Abschnitt Weißbildabgleich dargestellten Beziehung folgt, dass zum einen gilt:

\vec{G} = \{W\} \cdot(\{C\}\cdot \vec{H} + \vec{B}).

Und zum anderen für den UniWB-Abgleich gilt:

\vec{G} = \{C\}\cdot (\vec{H_W} + \vec{B}).

Beide Gleichungen lassen sich kombinieren, wodurch sich ergibt:

\vec{H_W}=\{W\}\cdot\vec{H}+\{C\}^{-1}\cdot(\{W\}\cdot\vec{B}-\vec{B})

Hier ist bereits zu erkennen, dass bei einem Schwarzwert gleich Null der erste Summand das Problem löst. Es ist aber ebenso zu erkennen, dass der zweite Summand gegen Null konvergiert, wenn \{W\} gleich der Einheitsmatrix ist, also wird die Iterationsfolge

\vec{H}_{neu}=\{W\}\cdot\vec{H}_{alt}

gegen den gesuchten Vektor \vec{H_W} konvergieren.  Das Einsetzen der Komponentenwerte in den Vektor \vec{H} und in die Matrix \{W\} liefert dann den gesuchten Iterationsalgorithmus

R_{neu} = R_{alt}\cdot {K_r}^{\frac{1}{\gamma}}
G_{neu} = G_{alt}
B_{neu} = B_{alt}\cdot {K_b}^{\frac{1}{\gamma}}.

Die UniWB-Einstellung, Teil1

Einleitung

Die Software von Digitalkameras unterstützt den Fotografen dabei, die richtigen Einstellwerte für die Belichtung zu finden. Insbesondere Fotografen, die vorzugsweise im RAW-Format arbeiten, möchten ihre Fotos häufig so belichten, dass die hellsten bildwichtigen Teile gerade noch nicht überbelichtet sind, um den Belichtungsspielraum des Sensors voll auszunutzen. Hilfsmittel dazu ist meist das Live-Histogramm. Hiermit belichtet man in diesem Fall so, dass die bildwichtigen Lichter gerade noch nicht den rechten Rand des Histogramms erreichen (Exposure To The Right).
Das Histogramm gibt jedoch leider nicht den originalen Inhalt der RAW-Daten des Sensors wieder, sondern wird erst aus dem bereits von der Kamerasoftware online aus der RAW-Datei entwickelten (jpeg-)Foto berechnet. Dabei sind bereits eine Vielzahl von Berechnungen zur Bildverarbeitung, wie Kontrast, Helligkeit und Weißabgleich erfolgt. Daher wird es meist dazu kommen, dass bei der Aufnahme des Fotos der tatsächliche Belichtungsspielraum trotz ggf. konservativer Einstellungen für Kontrast und Helligkeit nicht ausgenutzt wird und ca. eine bis anderthalb Blendenstufen im Raw-Bild nicht genutzt werden. Abhilfe schafft hier die sogenannte UniWB-Einstellung der Kamera. Im Internet sind viele Möglichkeiten dargestellt, wie man diese Einstellung vornehmen kann. Diese Vorschläge erfordern aber meist kompliziertere Prozeduren mit Bildbearbeitungsprogrammen, wie z.B. mit Photoshop, und ein tieferes Verständnis des Farbmanagements digitaler Bildbearbeitung. Ich beschreibe meine etwas einfachere Vorgehensweise im folgenden Text. Besserer Bequemlichkeit halber habe ich für die Rechnerei und Testbilderzeugung ein Python-Skript erstellt, das weiter unten von dieser Website kopiert werden kann, aber eigentlich reichen auch ein Taschenrechner, das frei erhältliche dcraw und ein einfaches Zeichenprogramm, wie Paint o.ä.

Der Trick
Der Sensor einer Digitalkamera hat unterschiedliche Empfindlichkeiten in den drei Farbkanälen Rot, Grün und Blau. Diese Unterschiede werden erst bei der Weiterverarbeitung des RAW-Files ausgeglichen, indem für den Weißabgleich die RAW-Werte der drei Kanäle jeweils mit entsprechenden Korrekturfaktoren multipliziert werden. Da der Kanal für die grüne Farbe am empfindlichsten ist, wird sein Korrekturfaktor auf den Wert Eins gesetzt und die Werte aus dem roten und dem blauen Kanal werden dann jeweils mit von Eins verschiedenen Korrekturfaktoren multipliziert. Der Trick besteht nun darin, alle drei Korrekturwerte auf den Wert Eins zu setzen, also eine „Unitary White Balance“, kurz UniWB-Einstellung vorzunehmen. Dadurch gibt das Live-Histogramm dann die korrekten Verhältnisse der RAW-Farbkanäle im Histogramm viel besser wieder.

Der Nachteil ist jedoch ein Grün-Farbstich des jpeg-Bilds, sowohl im Live-Bild des Kameradisplays als auch des ggf. abgespeicherten jpg-Bilds. Letzteres ist damit praktisch unbrauchbar.
Der korrekte Weißabgleich muss dann immer bei der Entwicklung des RAW-Bilds von Hand vorgenommen werden. Dies ist technisch kein Problem, vergrößert aber den Zeitaufwand.

Es gibt zur Zeit bei keiner Digitalkamera die Möglichkeit, die Werte der Korrekturkoeffizienten für den Weißabgleich direkt einzugeben. Der Trick besteht darin, ein zur Empfindlichkeit der Farbkanäle des Kamerasensors „inverses“ Bild auf einem Monitor zu erzeugen und mit diesem einen manuellen Weißabgleich durchzuführen, sodass dieser Weißabgleich kameraintern in allen drei Farbkanälen Korrekturfaktoren mit einem Wert nahe Eins erzeugt.
Nachdem ich mich eine ganze Weile mit den verschiedenen Möglichkeiten beschäftigt hatte dies zu bewerkstelligen, ist mir eine relativ einfach Variante eingefallen, die ohne komplizierte Mathematik auskommt und auch keine umfassenden Kenntnisse über das Farbmanagement u.ä. erfordert.

Die Vorgehensweise ist iterativ:

  1. Es wird ein Monitorbild mit definierten RGB-Vorgabewerten erzeugt.
  2. Mit diesem Bild wird ein manueller Weißabgleich durchgeführt.
  3. Anschließend wird mit diesem Weißabgleich ein beliebiges gut belichtetes Foto aufgenommen und als Raw-Datei abgespeichert.
  4. Aus den Exif-Daten dieses Fotos werden die Korrekturkoeffizienten Kr und Kb des manuellen Weißabgleichs ausgelesen.
  5. Mit diesen Korrekturkoeffizienten wird dann ein korrigiertes Monitorbild mit neuen RGB-Werten erzeugt. (Diese Arbeit erledigt mein Pythonskript.)

Die Prozedur wird dann wiederholt, und zwar solange, bis die Korrekturfaktoren nahe genug am Zielwert Eins liegen. 5% Abweichung ist nahe genug.
Als weiterer Eingabewert wird der Gamma-Wert (\gamma) des verwendeten Monitors benötigt. Der Gamma-Wert ist für die gleichmäßige Konvergenz der beiden Korrekturfaktoren während der Iteration wichtig. Er kann ausreichend genau mit visuellen Tools aus dem Internet ermittelt werden. Im Pythonskript ist dieser Wert als Variable „Gam“ abgespeichert und muss daher entsprechend angepasst werden. Werte von 1.8 (Mac) oder 2.2 (Windows PC) sind dafür üblich. Für mein IPad habe ich den Wert 2,0 ermittelt. Wichtig ist außerdem, während der Prozedur die Kamera mit immer gleichen Belichtungseinstellungen zu benutzen, also zweckmäßigerweise den manuellen Modus für die Belichtungseinstellungen zu wählen.

Ein Beispiel

Für das Beispiel habe ich meine alte KonicaMinolta A200 benutzt, mit meiner Fujifilm XT-20 hat die Prozedur ebenfalls in gleicher Weise funktioniert.  Zunächst habe ich mit meinem Pythonskript und den Eingaben: R = G = B = 90 und Kr = Kb = 1.0 ein Graubild erzeugt, dieses auf meinem IPad (sein Bildschirm ist besser als mein PC-Monitor) dargestellt und einen manuellen Weißbildabgleich durchgeführt. Mit diesem Abgleich habe ich ein Foto (in meiner Wohnung) gemacht und mir dann mit dcraw die relevanten Koeffizienten anzeigen lassen:

\Projekte\Foto\UniWB\Iteration>dcraw -i -v PICT0140.MRW
Filename: PICT0140.MRW
Camera multipliers: 602.000000 254.000000 400.000000 254.000000

Die Camera Multipliers sind die Parameter des eingestellten Weißabgleichs in der Kamera. Sie werden in dcraw für die sog. Bayer-Anordnung der Farbmatrix angegeben. Es handelt sich daher um die 4 Werte für die Farbkanäle RGBG. Für die weitere Berechnung werden die Werte dann auf den grünen Farbkanal normiert (G=1).
Die gesuchten Korrekturwerte ergeben sich dementsprechend aus den Werten der „Camera multipliers“, und zwar sind in diesem Fall:
Kr = 602.0/254.0 = 2.37 und
Kb = 400.0/254.0 = 1.57.

Mit diesen Werten errechnet das Pythonskript die neuen RGB-Werte aus

R_{neu} = R_{alt} \cdot K_r^{\frac{1}{\gamma}}, G_{neu} = G_{alt}, B_{neu} = B_{alt} \cdot K_r^{\frac{1}{\gamma}},

und mit diesen Werten wird die Prozedur wiederholt. Diese Iteration erfolgt dann solange, bis man mit dem Ergebnis zufrieden ist oder es sich nicht mehr verbessert. (Warum diese Prozedur funktioniert, erkläre ich demnächst in einem anderen Beitrag.)
In dem gewählten Beispiel ergab sich folgender Ablauf:

\Projekte\Foto\UniWB\Iteration>dcraw -i -v PICT0140.MRW
Filename: PICT0140.MRW
Camera multipliers: 602.000000 254.000000 400.000000 254.000000

Filename: PICT0141.MRW
Camera multipliers: 335.000000 254.000000 312.000000 254.000000

Filename: PICT0142.MRW
Camera multipliers: 280.000000 254.000000 281.000000 254.000000

Filename: PICT0143.MRW
Camera multipliers: 272.000000 254.000000 267.000000 254.000000

Filename: PICT0144.MRW
Camera multipliers: 264.000000 254.000000 261.000000 254.000000

Filename: PICT0145.MRW
Camera multipliers: 256.000000 254.000000 260.000000 254.000000

Die dazugehörigen RGB-Werte und Korrekturfaktoren Kr und Kb waren:

  1.   90 90  90  2.37   1.57
  2. 138 90 112 1.319 1.228
  3. 158 90 124 1.102 1.106
  4. 165 90 130 1.071 1.051
  5. 170 90 133 1.039 1.026
  6. 173 90 134 1.008 1.023

Nach 5 Iterationsschritten war meine Zielvorgabe von weniger als 5 %-Abweichung von 1 bereits erreicht.
Das dazugehörige Monitorbild kann abgespeichert und bei Bedarf jederzeit wieder verwendet werden.

Das Pythonskript

Das Python-Skript kann hier heruntergeladen werden.