Digitale Bildbearbeitung - Flatfield-Korrektur und Kontrastierung

Begonnen von Michael Müller, Mai 13, 2025, 16:02:59 NACHMITTAGS

Vorheriges Thema - Nächstes Thema

rlu

#30
Hallo,

bin da über ein paar Dinge bei "fiji" gestolpert:
Das wichtigste zuerst:

1. Wenn man die Textdatei in das Verzeichnis fiji/plugins kopiert, dann muss die Datei im Namen einen Underscore haben. Falls der Unterstrich = "_" nicht da ist, fehlt der Eintrag in den Plugins.

2. Dateierweiterung. Neuer Rechner mit Windows 11, da war noch Erweiterungen anzeigen "aus". Das passiert Profis nicht, aber mir. Wenn die Erweiterung nicht an sind und man macht eine Datei mit dem Namen"Flatter_geht_nicht.ijm", dann steht dahinter immer noch Filetype = "Txt" also Text. Das wird so nicht funktionieren.
Anschalten dieser Ansicht über Anzeigen/Erweiterungen/Dateinamenserweiterungen. Jetzt kann der Typ(Dateityp) auf ".IJM" geändert werden.

2025-05-17 10_07_55-C__temp_Fiji.app_plugins – Datei-Explorer.jpg


3. Die beiden Bilder müssen zuvor geöffnet sein. Sonst kommt eine Fehlermeldung.
Also beide öffnen mit Menü/File/Open  - dann jeweils die Bilder. Dann noch richtig zuordnen.
Fehlermeldung falls nicht geöffnet:
2025-05-17 10_15_07-Antworten und 10 weitere Seiten - Profil 1 – Microsoft​ Edge.jpg

4. Equalize Histogramm
erst mal nicht anwählen. Sonst bekommt man ein Rauschbild.
2025-05-17 10_16_14-Enhance Contrast.jpg

Download:
https://fiji.sc/


Das Werkzeug hat schon eine gewisse Mächtigkeit.

Liebe Grüße
Rudolf

Hallo Stephan,
habe gestern den Garten von meinen Eltern nach GartenschnittArbeiten zusammengekehrt.
Ich glaube du meinst Kontemplation.
Oder zumindest den Kopf frei kriegen...
Trotzdem Danke für den Beitrag.
Kennt jemand von Fendrich: Voller Mond - Das Feuer?

Michael Müller

Hallo,

@Rudolf:
Super, freut mich, dass die Methode für Dich passt.
Nur noch eine Anmerkung zum Weißabgleich:
Bei der "Divisionsmethode" wird automatisch ein Weißabgleich auf (sogar für jedes Pixel) das Flatfield gemacht (das ergibt sich aus der Berechnung automatisch).
Bei der "Substraktionsmethode" kann im Ergebnisbild nachträglich kein Weißabgleich durchgeführt werden, da der für den Hintergrund durch die Berechnung automatisch erfolgt, aber für das Objekt nicht stimmt (auch wenn es vielleicht nicht auffällt). Bei dieser Methode sollte also der Weißabgleich bereits vor der Aufnahme an der Kamera richtig durchgeführt werden.
Ja, der Unterstrich im Dateinamen ist nötig (wenn man ein Leerzeichen im Menünamen haben möchte) - das liegt an der sehr vereinfachten Plugin-Verwaltung von ImageJ. Der Menü-Name wird aus dem Dateinamen generiert. Ebenso ist auch die richtige Dateiendung nötig.
Die zu bearbeitenden Fotos müssen in ImageJ geöffnet sein. Beim Abspeichern muss man die Bilder ggf. nach JPEG exportieren (bei neu erzeugten Bildern würde ImageJ TIF-Bilder erzeugen).

@Hubert:
Ich habe mir nochmal etwas mehr Gedanken über Deine Tests gemacht.
Wenn ich das richtig sehe, dann läuft die Berechnung dann in Sättigung, wenn

"Divisionsverfahren":

    Helligkeit(Foto) / Helligkeit(Flatfield) * 128 > 255
also
    Helligkeit(Foto) / Helligkeit(Flatfield) >2
ist.
Bei einer Hellfeldaufnahme ist die Fotohelligkeit maximal so groß wie die vom Flatfield -> also keine Probleme.
Bei DIC ist bei konstruktiver Interferenz die resultierende Amplitude 1.4142 (also Wurzel von 2), da der Analysator im 45°-Winkel zu den Hauptrichtungen der Prismen steht. Die Helligkeit ist das Quadrat der Amplitude, also maximal doppelt so groß wie die Flatfield-Helligkeit (bitte korrigiere mich, wenn ich falsch liege). Also gibt es hier auch keine Probleme.
Bei Dunkelfeld funktioniert das Ganze nicht.

"Subraktionverfahren":
     Helligkeit(Foto) - Helligkeit(Flatfield) + 128 > 255
also
     Helligkeit(Foto) - Helligkeit(Flatfield) > 127

Das kann bei allen Beleuchtungsverfahren schiefgehen - auch wenn das in der Praxis wohl eher unwahrscheinlich ist.


Viele Grüße

Michael

Gerne per Du

Lupus

Hallo Michael,

meine Betrachtung war zunächst rein systematisch, um den gesamten Intensitätsbereich abzudecken. Du hast vollkommen Recht dass in der Praxis üblicher Beleuchtungsverfahren und der dabei im Foto auftretenden eher geringen Kontraste keine Probleme auftreten - wenn man vom bereits erwähnten Dunkelfeld absieht. Bei speziellen Polarisationsverfahren und Phasenkontrast nach Zernike könnte es je nach Einstellung etwas anders aussehen. Aber ich denke dass da die Flatfield-Korrektur auch kaum Relevanz hat.

Hubert

rlu

#33
Hallo Martin,

ein sehr wertvoller Beitrag:
ZitatIch habe auch eine Methode um den Hintergrund gleichmässig zu machen.
Anstatt der Division benutze ich Subtraktion das Ergebniss hat viel weniger Rauschen, es scheint auch das numerisch stabilere Verfahren zu sein, aber das muss ich erst noch testen.

Michael hat ja beide Methoden implementiert. Standardmäßig steht es jetzt auf Subtraktion.
Die Subtraktion erzeugt die rauschfreieren Bilder.
Was heißt das aber jetzt für das Objekt.
Zu dunkle Bereiche würden dann Rauschen. Methode: Division
Also müsste man alles flat aufnehmen; ohne Kontrast. Wie bei Videoprofilen?

Vermutlich liegt das am Signal-Rauschabstand, der verkleinert wird.
https://www.naturfotografie-digital.de/anfaengertipps-fotografie/iso-empfindlichkeit-beschreibung.php
"Die Bilder erscheinen bei höheren ISO-Einstellungen zunehmend verrauschter und weisen weniger Details auf. Insbesondere auf homogenen Flächen ist dann deutlich zu sehen, dass nicht alle Bildpunkte die gleiche Helligkeit besitzen, und dass einzelne Pixel auch von der Farbe her etwas abweichen. Man bezeichnet dies als Bildrauschen. Vor allen in dunklen Bildbereichen macht sich das Rauschen stärker bemerkbar."

Bei Helicon Focus rauscht die Methode C auch mehr, liefert aber mehr Details.
Habe jetzt zwischen den beiden Methoden Division und Subtraktion noch keinen großen Unterschied feststellen können.

Dunkelfeld: Wer hat Testbilder? Flat + Bild?


Liebe Grüße
Rudolf

Schuhmicro

#34
Hallo Michael (Müller), Rudolph, Stephan/SNoK, Peter, Michael, Leo, Hubert, Heribert und Arnold

Zitat von: Michael Müller in Mai 15, 2025, 08:50:05 VORMITTAG@Leo: Nur eine Frage: Du dividierst das Rohbild durch das Flatfield. Was ich aber nicht sehe, ist dass Du die das Ergebnis mit einer "Durchschnittshelligkeit" oder 128 multiplizierst. Macht das Python automatisch?
Beim Verfahren von Leo wird der Hintergrund Weiss, nicht grau.
Der Datentyp des Python Bildes ist np.float32 also eine Fliesskommazahl.

Leo Dividiert das Bild durch den Hintergrund das Ergebnis 1.0=Weiss und ich "rate" mal 0.0000001=Schwarz. Die Farbwerte würden also zwischen +0 und +1 liegen.
Leos Verfahren eignet sich vorallem für Hellfeld, weil dort der Hintergrund weiss ist.

Bei Imagej also bei Michaels Verfahren ist 255=Weiss und 0=Schwarz (laut doku sollte das so sein) deshalb musst Er mit 127 oder 128 multiplizieren selbst dann wenn Imagej manchmal intern mit Floats rechnet.

Der Hintergrund wird bei Michael nach der Anwendung des Flatfield Verfahrens immer ca. 128 Grau , daher ist es Für DIK sinnvoll, wenn der DIK-Hintergrund vorher schon eher Grau ist. Für Dunkelfeld und Farb-DIK nicht.

Das Verfahren lässt sich vermutlich erweitern Für Hell/Dunkelfeld oder Farbhintergrund, die smarte Methode wäre wenn das Macro die Hintergrundfarbe aus dem Durchschnitt von I_Flatfield ermittelt.
Der Mittelwert für das I_Flatfield des Beispielbild ist 104: Analyze - Histogram - Mean

Gruss
Martin

Lupus

#35
Hallo Martin,

ZitatDer Hintergrund wird bei Michael immer Grau , daher ist es Für DIK sinnvoll, wenn der DIK-Hintergrund vorher schon eher Grau ist. Für Dunkelfeld und Farb-DIK nicht.
das ist so nicht richtig. Die Hintergrundhelligkeit hängt auch nicht vom verwendeten Datenformat ab. Da 8-bit JPG von 0...255 geht liegen die verwendeten Zahlenwerte in dieser Spannweite.

Dass der Hintergrund bei einem "richtig" eingestellten differentiellen Phasenkontrast in der Helligkeit etwa mittig zwischen den dunkelsten und hellsten Tönen des Objekts ist, liegt am Phasenkontrastverfahren. Daher ist in diesem Fall auch unvermeidlich dass der korrigierte Hintergrund im gleichen Graubereich liegt. Bei einem "normalen" Hellfeldbild wie z.B. einem gefärbten Schnitt ist normalerweise das Objekt (fast, außer wenn ein Phasenobjektanteil hier noch mitmischt) vollständig dunkler als der Hintergrund. Entsprechend wird hier auch der Hintergrund hell mit dem gleichen Rechenverfahren.

Man muss übrigens beim Divisionsverfahren als Faktor nicht den JPG-Mittelwert 128, und als Subtrahend nicht 0 nehmen - das ist nur ein guter Anhaltspunkt (ähnlich beim Subtraktionsverfahren). Wer sich nachträgliche Kontrastspreizung sparen will kann auch an das Bild angepasste Werte für k1 und k2 verwenden. Der Quotient Bild/Hintergrund liegt beim DIK um einen Wert von 1. Aus der ermittelten Spannweite dieses Quotienten könnte man optimale Spreizungs-Werte direkt berechnen. Hier ein Beispiel mit dem gleichen Ausgangs-Rohbild, nur mit den Einstellungen k1 = 245 und k2 = -130.

Ergebnis Division x245-130.jpg

Hubert


Schuhmicro

#36
Hallo Hubert,
Zitat von: Lupus in Mai 17, 2025, 17:02:35 NACHMITTAGSZitat
Martin: Der Hintergrund wird bei Michael immer Grau ,
Hubert:das ist so nicht richtig.Die Hintergrundhelligkeit hängt auch nicht vom verwendeten Datenformat ab
Der Hintergrund wird bei den Verfahren von Michael mit den fest programmierten Konstanten K1,2=128 immer "Grau" Ich habe das wohl nicht präzise genug formuliert.

Natürlich hängt die Hintergrundhelligkeit vom Datenformat ab wird hier ein Zahlenwert für die Helligkeit von (255,255,255) direkt in eine BildDatei geschrieben ist das Pixel bei einem 8 bit jpeg eher hell, aber bei einem 16 bit Bild ist der Wert (00255,00255,00255) eher Dunkel.
Gruss
Martin

Lupus

Hallo Martin,

ich habe mich auf den Zusammenhang "... immer Grau, daher ist es Für DIK sinnvoll, wenn der DIK-Hintergrund vorher schon eher Grau ist" bezogen. Es ist ja eher umgekehrt, dass wie von mir betont mit "richtig" eingestelltem DIK der Hintergrund zwangsläufig Grau ist weil seine Helligkeit zwischen den "beleuchteten" und den "unbeleuchteten" Seiten der sichtbaren Reliefstrukturen liegen muss - außer das Foto ist stark unter- oder überbelichtet. Durch die nicht zwingende Wahl von k1 = 128 liegt man aber beim korrigierten Bild zumindest immer in der Mitte des Helligkeitsspielraums wenn k2 = 0.

ZitatNatürlich hängt die Hintergrundhelligkeit vom Datenformat ab wird hier ein konstanter Zahlenwert für die Helligkeit von (255,255,255) in die Datei geschrieben ist das Pixel bei einem 8 bit jpeg eher hell, aber bei einem 16 bit Bild ist der Wert (255,255,255) eher Dunkel.
Das hängt vom Programm ab, das Plugin "Calculator Plus" verwendet für RGB-Bilder als Ergebnis automatisch 8-Bit Daten.

Hubert

Michael Müller

Hallo Rudolf,

bei der Methode steigt das Rauchen, wenn das Flatfieldbild starke Helligkeitsunterschiede aufweist. Man sollte sich also immer bemühen, die Beleuchtung so gleichmäßig wie möglich zu halten. Probleme treten erst auf, wenn man - wie bei meinem Beispiel - eine heftige Korrektur vornehmen muss.

Also:
- Hintergrund so gleichmäßig wie möglich
- Bild so kontrastreich wie möglich

dann gib's auch keine Probleme.

Viele Grüße

Michael
Gerne per Du

rlu

#39
Hallo Michael,

danke für die Antwort.
Das sollte eigentlich gängige Praxis sein, ein Hintergrundbild anzufertigen.


Ich versuche jetzt das noch mit Python.

Martin hat was geschrieben, dass die Farbkanäle aufgesplittet werden.
Hat das eine Bedeutung?
Wie sieht es mit Farbrauschen bzw. Farbgradient(alte Halogenbeleuchtung) aus.
Hast du dafür ein Bildbeispiel.



Und dann noch was an alle Flat-Earther ich meinte eigentlich 8-Bitler.
jpeg kann 8bit, also 256 Helligkeitsabstufungen von Schwarz bis Weiß.
Die meisten Bilder haben wesentlich mehr Pixel in der Breite wie 256. z.B 20Mp = 5152 × 3864 Pixel
Ein gleichmäßiger Gradient kann so nicht entstehen.
Man behilft sich dadurch, dass man Rauschen in das Bild reinbringt.
Photoshop hat da sogar dafür einen eigenen Algorithums entwickelt.
Ich habe das Problem dann, wenn ich einen gewollten Gradienten in den Hintergrund als Farbverlauf in ein Bild einbringe.
Im Moment ist meine einzige Lösung, Rauschen hinzuzufügen.


Ein Thema wäre auch noch zu diskutieren, wie man am Besten ein künstliches Flatfield erzeugt.
Falls man kein separates Flatfield-Bild besitzt, um nachträglich Bilder zu optimieren.
Auch unter dem Aspekt von 8-Bit.
ODER
Du hast ja bereits mit Stitching experimentiert. Dabei ist es wichtig die Helligkeiten der Bilder untereinander anzugleichen.

Liebe Grüße
Rudolf

Schuhmicro

#40
Hallo Rudolf, Michael, Stephan/SNoK, Peter, Michael, Leo, Hubert, Heribert und Arnold ,

Zitat von: rlu in Mai 18, 2025, 12:16:10 NACHMITTAGSMartin hat was geschrieben, dass die Farbkanäle aufgesplittet werden.
Hat das eine Bedeutung?
Ja in Imagej kann man aus einem Bild 3 Graustufenbilder erzeugen.
         Image - Color - Split Channel
Das ist meine ursprüngliche Methode. Michael splittet nicht das geht schneller.

Das Ergebnis sind dann 6 GraustufenBilder mit 32Bit Farbtiefe die dann Für jede Farbe extra Subtrahiert werden mit Process - Image Calculator.
Die Subtraktion  ist dann nicht mehr 8 Bit sondern sind (3x) 32 Bit Operationen eben für jede Farbe Extra. Damit hat man die Möglichkeit Farben unterschiedlich zu behandeln(z.B. für Farb DIC)
Ich addiere hier nicht 128 (im Gegensatz zur Subtraktionsmethode mit Calculator Plus).
Zum Schluss wird alles wieder in ein einziges Bild umgewandelt. (Image - Color - Merge Channels und Image - Type - RGB Color)

Das Ergebnis der Bearbeitung ist unterschiedlich, es wurde keine Kontrastspreizung durchgeführt.
Im Bild Rechts (3x)32 Bit Subtraktion(Martin) - Composite
    Der Hintergrund ist durchnittlich bläulich (140,150,160) nicht Grau
Links 8 Bit Subtraktion mit Calculator Plus (Michael) -  Result
    Der Hintergrund ist (130,130,130) also Grau
comparison8-32.jpg
Zitat von: rlu in Mai 18, 2025, 12:16:10 NACHMITTAGSDas sollte eigentlich gängige Praxis sein, ein Hintergrundbild anzufertigen.
Das hab ich gemacht, Ein Desktop-Hintergrundbild  :P . Das lustige Rätsel ist jetzt: Wie heisst Die Person in meinem Hintergrundbild deren Gesicht man nicht mehr ganz sieht?
Hinweis: durch seine theoretische Vorarbeit wurde die Erfindung der achromatischen Korrektur angeregt.
Gruss
Martin

Kurt

.... das ist der geniale Mathematiker Leonhard Euler!
Es ist einfach verrückt, was dieser Mann geleistet hat!!!

Grüße
Kurt

Schuhmicro

#42
Hallo Kurt,
herzlichen Glückwunsch,
Leonhard Euler ist Richtig  8).
Du hast ein Linux Desktop-Hintergrundbild gewonnen. (wenn gewünscht per PN in deiner Auflösung)
Gruss
Martin

rlu

#43
Hallo,

hier wäre der Python-Code basierend auf dem vom Leo ohne Linux, vereinfacht.
Habe mir Anaconda(das eigentliche Python mit den Pakten/Bibliotheken) runtergeladen und mit Spyder als IDE(Entwicklungsumgebung) gearbeitet. Code in Spyder reinkopieren F5 drücken. Rechts unten, die Abfragen beantworten. Die Bilder müssen ins gleiche Verzeichnis wie das Programm.

Das ist der gekürzte Code, damit man ungefähr versteht um was es geht.
Die imageio muss auf imageio.v2 geändert werden
jpg ist 8-bit, deshalb braucht es die Umwandlung von 32bit

Die zwei Bilddateien liegen im Verzeichnis der Programmdatei.


import numpy as np
from imageio.v2 import imread, imsave

# Flatfield einlesen
# Pyhton achtet auf Groß/Kleinschreibung
flat_data = imread('Average-flatfield.jpg').astype(np.float32)

# Bild einlesen und korrigieren
image_data = imread('mikro1.jpg').astype(np.float32)


final_data = image_data / flat_data


print("Shape von final_data:", final_data.shape)


final_data_uint8 = (final_data * 128).astype(np.uint8)

# 2. Prüfen der Shape (falls nötig)
print("Shape vor squeeze:", final_data_uint8.shape)
final_data_uint8 = final_data_uint8.squeeze()  # Überflüssige Dimensionen entfernen
print("Shape nach squeeze:", final_data_uint8.shape)

# Speichern
imsave('result.jpg', final_data_uint8)
print("Bild erfolgreich gespeichert!")


Hier mit Auswahl zwischen Subtraktion und Division

import numpy as np
from imageio.v2 import imread, imsave

# Flatfield einlesen (Python achtet auf Groß-/Kleinschreibung)
flat_data = imread('Average-flatfield.jpg').astype(np.float32)

# Bild einlesen
image_data = imread('mikro1.jpg').astype(np.float32)

# Auswahlmenü für Korrekturmethode
print("Wähle die Korrekturmethode:")
print("1: Subtraktion (image - flatfield)")
print("2: Division (image / flatfield)")
choice = input("Deine Wahl (1 oder 2): ")

# Korrektur durchführen
if choice == '1':
    final_data = image_data - flat_data
    method = "Subtraktion"
elif choice == '2':
    # Vermeidung von Division durch Null (ersetze Nullen durch kleine Zahl)
    flat_data[flat_data == 0] = 1e-7
    final_data = image_data / flat_data
    method = "Division"
else:
    raise ValueError("Ungültige Eingabe! Nur 1 oder 2 erlaubt.")

# Debug-Ausgabe der Shape
print("Shape von final_data:", final_data.shape)

# Normalisierung und Konvertierung
if method == "Subtraktion":
    # Für Subtraktion: Werte zentrieren um 128
    final_data_normalized = np.clip(final_data, -128, 127)  # Werte auf -128..127 begrenzen
    final_data_uint8 = (final_data_normalized + 128).astype(np.uint8)  # Auf 0..255 verschieben
else:  # Division
    # Für Division: Werte auf 0..255 skalieren
    final_data_normalized = np.clip(final_data, 0, 2)  # Werte begrenzen
    final_data_uint8 = (final_data_normalized * 128).astype(np.uint8)  # Auf 0..255 skalieren

# Shape-Informationen (Debug)
print("Shape vor squeeze:", final_data_uint8.shape)
# final_data_uint8 = final_data_uint8.squeeze()  # Falls unnötige Dimensionen vorhanden
print("Shape nach squeeze:", final_data_uint8.shape)

# Speichern mit methodenspezifischem Namen
output_filename = f'Result_{method}.jpg'
imsave(output_filename, final_data_uint8)
print(f"Bild erfolgreich gespeichert als {output_filename}!")


Ergebnis wie zuvor
2025-05-19 00_16_38-Bilder vergleichen.jpg


Schuhmicro

#44
Hallo Rudolf,
Zitat von: rlu in Mai 18, 2025, 12:16:10 NACHMITTAGSEin gleichmäßiger Gradient kann so nicht entstehen.
Der Floyd-Steinberg-Algorithmus um die Farbtiefe eines Bildes zu verringern.
Das ist nicht das Gleiche wie "Rauschen".
Man erzeugt einen Farbverlauf mit np.float32 danach reduziert man die Farbtiefe auf 8 Bit mithilfe von Floyd-Steinberg. (von Robert W. Floyd und Louis Steinberg)
Ich hab den verlinkten python code nicht getestet (python kann ich nicht so gut, lerne noch).
https://github.com/szabolcsdombi/optimized-floyd-steinberg-dithering
https://gist.github.com/bzamecnik/33e10b13aae34358c16d1b6c69e89b01
https://de.wikipedia.org/wiki/Dithering_(Bildbearbeitung)
Dithering_algorithms.jpg
das sind tatsächlich nur noch 2 Farben Schwarz/Weiss, das dient der Veranschaulichung, brauchen tut man 2 Farben beim Drucken, im Vergleich einfach mit einem Schwellwert:
Post.jpg
danach mit Rauschen:
Rausch.jpg
Die Software Gimp verwendet (wählbar) verschiedene Algorithmen auch Floyd-Steinberg, Du kannst das mit Gimp testen. (Bild - Kodierung - 8Bit/32Bit)
Algo.jpg
Gruss
Martin