radiometric_self_calibration
— Radiometrische Selbstkalibrierung einer Kamera.
radiometric_self_calibration(Images : : ExposureRatios, Features, FunctionType, Smoothness, PolynomialDegree : InverseResponse)
radiometric_self_calibration
führt eine radiometrische
Selbstkalibrierung einer Kamera durch. Dazu müssen in
Images
mindestens zwei Bilder übergeben werden, die
denselben Bildinhalt zeigen. Alle in Images
übergebenen
Bilder müssen mit unterschiedlichen Belichtungen aufgenommen worden
sein. Typischerweise werden die unterschiedlichen Belichtungen
durch Veränderung der Verschlusszeiten (Belichtungszeiten) an der
Kamera erzeugt. Eine Änderung der Belichtung durch Verstellen der
Blende ist nicht zu empfehlen, da hier die Belichtungsverhältnisse
nicht genau genug bestimmt werden können. Das Verhältnis der
Belichtungen aufeinanderfolgender Bilder wird in
ExposureRatios
übergeben. Ein Wert von 0.5
bedeutet z.B., dass das zweite Bild des Bildpaares mit der halben
Belichtung des ersten Bildes aufgenommen wurde. Das Verhältnis der
Belichtungen kann leicht aus den Verschlusszeiten berechnet werden,
da die Belichtung proportional zur Verschlusszeit ist. Das
Verhältnis der Belichtungen muss größer als 0 und kleiner als 1
sein. Das bedeutet, dass die Bilder nach abnehmender Belichtung
sortiert sein müssen. ExposureRatios
muss ein Element
weniger enthalten, als die Anzahl der in Images
übergebenen Bilder. Falls alle Verhältnisse der Belichtungen
identisch sind, kann zur Vereinfachung auch ein einziger Wert in
ExposureRatios
übergeben werden.
Wie oben beschrieben, müssen die in Images
übergebenen
Bilder denselben Bildinhalt zeigen. Dazu ist es normalerweise
notwendig, dass sich weder die Kamera noch die im Bild enthaltenen
Objekte bewegen. Falls sich die Kamera um das optische Zentrum
gedreht hat, sollten die Bilder mit proj_match_points_ransac
und projective_trans_image
auf eines der Bilder als
Referenzbild ausgerichtet werden. Falls die zur radiometrischen
Kalibrierung verwendeten Merkmale aus dem 2D-Grauwerthistogramm von
aufeinanderfolgenden Bildpaaren aus Images
bestimmt werden
(Features
= '2d_histogram' ), ist es
unerlässlich, dass die Bilder aufeinander ausgerichtet sind und
dass sich die Objekte in den Bildern nicht bewegen. Im Modus
Features
= '1d_histograms' werden die zur
radiometrischen Kalibrierung verwendeten Merkmale aus den
1D-Grauwerthistogrammen der Bildpaare berechnet. In diesem Modus
kann eine Kalibrierung theoretisch auch dann erfolgen, falls sich
die 1D-Histogramme der Bilder durch eine Bewegung von Objekten im
Bild nicht ändert. Dies kann z.B. dann der Fall sein, falls sich
ein Objekt vor einem gleichmäßig texturierten Hintergrund bewegt.
Aufgrund der höheren Genauigkeit ist aber der Modus
Features
= '2d_histogram' vorzuziehen. Der
Modus Features
= '1d_histograms' sollte nur
verwendet werden, falls es unmöglich ist, den Kameraaufbau so zu
konstruieren, dass sich weder die Kamera noch die Bildobjekte
bewegen.
Des Weiteren ist darauf zu achten, dass der Grauwertbereich
lückenlos überdeckt wird. Hierzu sollte ein geeigneter Bildinhalt
gewählt werden. Ob Lücken im Grauwertbereich vorliegen, kann
leicht anhand der 1D-Grauwerthistogramme der Bilder und der
2D-Grauwerthistogramme aufeinanderfolgender Bilder überprüft
werden. In den 1D-Grauwerthistogrammen (siehe
gray_histo_abs
) sollten zwischen dem minimalen und maximalen
Grauwert keine Bereiche mit einer Häufigkeit von 0 oder einer sehr
kleinen Häufigkeit vorkommen. In den 2D-Grauwerthistogrammen
(siehe histo_2dim
) sollte nach der Segmentierung mit einem
unteren Schwellwert von 1 eine zusammenhängende Region in Form
eines „Schlauches“ entstehen. Falls mehrere
Zusammenhangskomponenten entstehen, sollte ein geeigneterer
Bildinhalt gewählt werden. Falls der Bildinhalt so gewählt werden
kann, dass der Grauwertbereich des Bildes (z.B. 0-255 bei
Byte-Bildern) mit zwei Bildern mit unterschiedlichen Belichtungen
ausgeschöpft werden kann, und keine Lücken in den Histogrammen
vorhanden sind, sind diese zwei Bilder zur Kalibrierung ausreichend.
Dies ist typischerweise jedoch nicht der Fall, so dass mit mehreren
Bildern der Grauwertbereich überdeckt werden muss. Dazu sind,
wie oben beschrieben, mehrere Bilder mit unterschiedlichen
Belichtungen aufzunehmen, um den Grauwertbereich möglichst
vollständig zu überdecken. Dabei sollte das erste Bild im
Normalfall so belichtet werden, dass der maximale Grauwert entweder
knapp unter der Sättigungsgrenze der Kamera liegt, oder dass das
Bild deutlich übersteuert ist. Falls das erste Bild übersteuert
aufgenommen wird, ist eine deutliche Übersteuerung notwendig, damit
radiometric_self_calibration
die übersteuerten Bereiche
sicher erkennen kann. Falls die Kamera ein ungewöhnliches
Sättigungsverhalten zeigt (z.B. eine Sättigungsgrenze, die
signifikant unter dem maximalen Grauwert liegt), sollten in dem
übersteuerten Bild die übersteuerten Bereiche per Hand mit
reduce_domain
ausmaskiert werden.
radiometric_self_calibration
liefert die inverse
Grauwert-Antwortfunktion der Kamera in InverseResponse
zurück. Die inverse Antwortfunktion kann dazu verwendet werden,
ein Bild mit linearer Grauwert-Antwortfunktion zu erzeugen, indem
InverseResponse
als LUT in lut_trans
verwendet
wird. Der Parameter FunctionType
gibt an, welches
Funktionsmodell für die Antwortfunktion verwendet werden soll.
Für FunctionType
= 'discrete' wird die
Antwortfunktion durch eine diskrete Funktion mit der relevanten
Anzahl von Grauwerten beschrieben (256 bei Byte-Bildern). Für
FunctionType
= 'polynomial' wird die
Antwortfunktion durch ein Polynom vom Grad PolynomialDegree
beschrieben. Die Berechnung der Antwortfunktion ist für
FunctionType
= 'discrete' langsamer. Da aber in
den Bereichen, an denen keine Grauwertinformation vorliegt, ein
Polynom trotz der unten beschriebenen Glattheitsbedingungen
Oszillationen aufweisen kann, ist die diskrete Funktion dem Polynom
im Normalfall vorzuziehen.
Die inverse Grauwert-Antwortfunktion wird als Tupel von ganzen
Zahlen für FunctionType
= 'discrete' und
FunctionType
= 'polynomial' zurückgeliefert. In
manchen Anwendungen kann es wünschenswert sein, die inverse
Grauwert-Antwortfunktion als Gleitkommazahlen zurückzuliefern, um
die numerischen Fehler, die durch Runden entstehen, zu vermeiden.
Falls z.B. die inverse Grauwert-Antwortfunktion invertiert werden
muss, um die tatsächliche Antwortfunktion der Kamera zu berechnen,
geht Information durch die Rundung verloren. In diesen Anwendungen
kann FunctionType
auf 'discrete_real' oder
'polynomial_real' gesetzt werden, was dazu führt, dass die
inverse Grauwert-Antwortfunktion als ein Tupel von Gleitkommazahlen
zurückgeliefert wird.
Der Parameter Smoothness
definiert (zusätzlich zu den
Bedingungen, die aus den Bildern über die Antwortfunktion der
Kamera hergeleitet werden können) Bedingungen für die Glattheit
der Antwortfunktion. Falls der Grauwertbereich wie oben
beschrieben vollständig und lückenlos überdeckt werden kann und
falls das Kamerarauschen gering ist, sollte der Standardwert von
1 nicht verändert werden. Ansonsten kann mit Werten >
1 eine stärkere Glättung und mit Werten < 1
eine schwächere Glättung der Antwortfunktion erreicht werden. Die
Glättung ist insbesondere in Bereichen wichtig, in denen keine
Grauwertinformation aus den Bildern hergeleitet werden kann, also
insbesondere in Lücken im Histogramm und für Grauwerte, die
kleiner sind als der minimale bzw. größer als der maximale
Grauwert aller Bilder. Hier führen die Glattheitsbedingungen zu
einer Interpolation bzw. Extrapolation der Antwortfunktion. Durch
die Art der intern berechneten Bedingungsgleichungen bevorzugt
FunctionType
= 'discrete' eine
Exponentialfunktion in undefinierten Grauwertbereichen, während
FunctionType
= 'polynomial' eine Gerade
bevorzugt. Beachten Sie bitte, dass die Interpolation und
Extrapolation in jedem Fall unsicherer ist, als den
Grauwertbereich vollständig und lückenlos zu überdecken.
Deswegen sollte in jedem Fall zuerst versucht werden, die Bilder
optimal aufzunehmen, bevor anhand der Glattheitsbedingungen ein
Auffüllen der Lücken vorgenommen wird. In jedem Fall sollte die
Antwortfunktion nach dem Aufruf von
radiometric_self_calibration
auf Plausibilität überprüft
werden. Insbesondere sollte überprüft werden, ob
InverseResponse
monoton ist. Falls dies nicht der Fall
ist, sollte ein geeigneterer Bildinhalt verwendet werden, damit
nicht interpoliert werden muss, oder Smoothness
auf einen
größeren Wert gesetzt werden. Für FunctionType
=
'polynomial' kann es auch notwendig sein,
PolynomialDegree
zu verändern. Falls trotz dieser
Änderungen immer noch ein wenig plausibles Ergebnis geliefert wird,
sollte das Sättigungsverhalten der Kamera überprüft werden,
z.B. anhand des 2D-Grauwerthistogramms, und die gesättigten
Bereiche wie oben beschrieben per Hand ausmaskiert werden.
Bei der Bestimmung der inversen Grauwert-Antwortfunktion der Kamera
kann die absolute Energie, die auf die Kamera fällt, nicht bestimmt
werden. Das heißt, dass InverseResponse
nur bis auf einen
Skalierungsfaktor bestimmt werden kann. Daher wird als
Nebenbedingung verwendet, dass der maximale Grauwert, der auftreten
kann, am maximalen Eingabegrauwert angenommen werden soll, also
z.B. für Byte-Bilder InverseResponse
[255] = 255. Diese
Nebenbedingung liefert im Normalfall ein intuitives Ergebnis. Falls
jedoch ein mehrkanaliges Bild (typischerweise ein RGB-Bild)
radiometrisch kalibriert werden soll (hierzu muss jeder Kanal
einzeln kalibriert werden), kann es vorkommen, dass durch die obige
Nebenbedingung ein unterschiedlicher Skalierungsfaktor für jeden
Kanal berechnet wird. Das kann dazu führen, dass Grautöne nach
der Korrektur nicht mehr grau erscheinen. In diesem Fall ist ein
manueller Weißabgleich durchzuführen, indem ein homogenes graues
Gebiet im Originalbild identifiziert wird, und aus den Grauwerten
der korrigierten Kanäle Skalierungsfaktoren für zwei der drei
Antwortkurven (bzw. allgemein für n-1 der n Kanäle)
hergeleitet werden. Dabei sollte die nicht zu ändernde
Antwortkurve so gewählt werden, dass alle Skalierungsfaktoren < 1
sind. Mit den so berechneten Skalierungsfaktoren sollten neue
Antwortfunktionen durch Multiplikation aller Werte einer
Antwortfunktion mit dem jeweiligen Skalierungsfaktor berechnet
werden.
Images
(input_object) singlechannelimage-array →
object (byte / uint2)
Eingabebilder.
ExposureRatios
(input_control) real(-array) →
(real)
Verhältnis der Belichtungsenergien aufeinanderfolgender Bildpaare.
Defaultwert: 0.5
Wertevorschläge: 0.25, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8
Restriktion: ExposureRatios > 0 && ExposureRatios < 1
Features
(input_control) string →
(string)
Merkmale, die zur Berechnung der inversen Antwortfunktion der Kamera verwendet werden.
Defaultwert: '2d_histogram'
Werteliste: '1d_histograms' , '2d_histogram'
FunctionType
(input_control) string →
(string)
Typ der inversen Antwortfunktion der Kamera.
Defaultwert: 'discrete'
Werteliste: 'discrete' , 'discrete_real' , 'polynomial' , 'polynomial_real'
Smoothness
(input_control) real →
(real)
Glattheit der inversen Antwortfunktion der Kamera.
Defaultwert: 1.0
Wertevorschläge: 0.3, 0.5, 0.7, 0.8, 1.0, 1.2, 1.5, 2.0, 3.0
Restriktion: Smoothness > 0
PolynomialDegree
(input_control) integer →
(integer)
Grad des Polynoms falls FunctionType
=
'polynomial' .
Defaultwert: 5
Wertevorschläge: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
Restriktion: PolynomialDegree >= 1 && PolynomialDegree <= 20
InverseResponse
(output_control) number-array →
(integer / real)
Inverse Antwortfunktion der Kamera.
open_framegrabber ('1394IIDC', 1, 1, 0, 0, 0, 0, 'default', -1, \ 'default', -1, 'default', 'default', 'default', \ -1, -1, AcqHandle) * Define appropriate shutter times. Shutters := [1000,750,500,250,125] Num := |Shutters| * Grab and accumulate images with the different exposures. In this * loop, it must be ensured that the scene remains static. gen_empty_obj (Images) for I := 0 to Num-1 by 1 set_framegrabber_param (AcqHandle, 'shutter', Shutters[I]) grab_image (Image, AcqHandle) concat_obj (Images, Image, Images) endfor * Compute the exposure ratios from the shutter times. ExposureRatios := real(Shutters[1:Num-1])/real(Shutters[0:Num-2]) radiometric_self_calibration (Images, ExposureRatios, '2d_histogram', \ 'discrete', 1, 5, InverseResponse) * Note that if the frame grabber supports hardware LUTs, we could * also call set_framegrabber_lut here instead of lut_trans below. * This would be more efficient. while (1) grab_image_async (Image, AcqHandle, -1) lut_trans (Image, ImageLinear, InverseResponse) * Process radiometrically correct image. * [...] endwhile close_framegrabber (AcqHandle)
Sind die Parameterwerte korrekt, dann liefert
radiometric_self_calibration
den Wert 2 (H_MSG_TRUE). Gegebenenfalls
wird eine Fehlerbehandlung durchgeführt.
read_image
,
grab_image
,
grab_image_async
,
set_framegrabber_param
,
concat_obj
,
proj_match_points_ransac
,
proj_match_points_ransac_guided
,
projective_trans_image
histo_2dim
,
gray_histo
,
gray_histo_abs
,
reduce_domain
Calibration