Files
Masterarbeit-Obsidian-Vault/Paperung/Experimente/Experiment 2 - NN performance.md
2026-03-20 22:44:00 +01:00

33 KiB

Hypothese: (besser formulieren, kommt irgendwo an den Anfang der Arbeit, mal Gucken, wo Meiko das hingepackt hatte...) LightEyes stellt Augen nur sehr grundlegende Formen dar, im Grunde graue Kreise und erzielt dabei verhältnismäßig gute Performance beim Training von Neuronalen Netzen. Daher ist davon auszugehen, dass das detailliertere Modellieren der Periorbitalregion keinen nennenswerten Einfluss auf die Leistung von Neuronalen Netzen hat.

Von Timms Arbeit: Über alle Experimente hinweg wurden die gleichen, in der medizinischen Bildsegmentierung etablierten Metriken erfasst [71]. Im Mittelpunkt stehen der Dice Score (auch F1 Score) und die IoU (auch Jaccard Index genannt) als Flächenüberlappungsmaße sowie Precision und Recall als Fehlerratenmaße. Besonders der Dice-Score fand in verwandten Arbeiten, wie etwa bei M. Calisto et al. (2021) [10] und Z. Fan et al. (2020) [19], Verwendung.

Meiko hat auch Dice und IoU überprüft. Nach jeder Epoche berehcnet.

Einleitung

In der vorliegenden Arbeit wurde die bestehende Implementierung von HEyes erweitert, sodass nun die Form der Periorbitalregion zufällig verändert werden kann. In Experiment 1 wird untersucht, wie sich die Änderungen auf die Laufzeit der Generierungspipeline auswirken. In diesem Experiment soll untersucht werden, ob diese Erweiterung einen Einfluss auf die Erkennungsleistung von KI-basierten Segmentierungsmodellen hat. Dazu wird ein Vergleich

Sachen, die ich mache:

  • NN: Yolo26-seg small (guter Tradeoff zwischen Größe/Performance)
  • Zwei Modelle mit 100% synthetischen Daten trainieren:
    1. Modell: mit alter Pipeline trainiert
    2. Modell: mit neuer Pipeline trainiert
    3. Wenn Zeit ist: ein Modell mit neuer Pipeline ohne AO
    • Datensplit (Training - Validierung): 80 - 20? Meiko hatte 85 - 15?!
  • Test-Set mit echten Daten
    • entweder 500k oder Daten aus TEyeD oder OpenEDS?
      • Vom Test-Set hängt auch die zu generierende Auflösung der synthetischen Bilder ab
    • Störfaktoren sind nicht wirklich Teil meiner Arbeit, daher möchte ich am besten einen kontrollierten Datensatz, aber mit verschiedenen Ethnien
      • Möglichst wenig Störfaktoren (wie Brille, Reflektionen, verschiedene Beleuchtung) im Test-Set
    • Auch Bilder mit Teilweise/Vollständig verdeckter Pupille
  • Synthetische Daten generieren
    • Wie viele Bilder? 5000? 10k?! Meine Hardware hat da wohl auch einen Einfluss drauf (s. u.)
    • Es werden explizit auch Bilder mit (teilweise) verdeckter Pupille erzeugt
    • Grauwerte aus echten Daten extrahieren
      • möglichst nicht aus dem Test-Set selbst, sondern aus anderen Daten, wobei ich mir da nicht sicher bin, da es ja eigentlich keinen Einfluss auf den Vergleich den ich machen möchte hat
    • Um Überrepräsentation von verdeckten Pupillen zu vermeiden wird der Exponentielle-Faktor für den Lidschluss verwendet, damit es mehr Bilder mit sichtbaren Pupillen gibt
    • Datenaugmentieren:
      • Flip (50%) für 50/50 Split aus linkem/rechtem Augen
      • leichter Blur
      • leichte Gamma/Helligkeitsanpassung

Sachen, die ich am Ende sehen möchte:

Graphen plotten über alle Epochen?

  • Train Loss
  • Validation Loss (Meiko hat das auch irgendwie für jede Epoche berechnet)
  • Precision und Recall, okay für Yolo hat er Mask Precision und Recall, was auch immer das sein soll Meiko hatte auch:
  • Validation mAP50
  • Validation mAP50-95

Jeweils für das finale Modell:

  • IoU und Dice für die Test-Set-Bilder berechnen
  • Tabelle: Mean + SD für IoU und Dice für beide Modelle
  • Ich möchte auch einen Boxplot zeigen können für IoU und Dice
  • Ich möchte einzelne Bilder, die extrem schlecht/gut waren rauspicken können und ihre Masken (Ground Truth und predicted) + Scores zeigen können

Genutzte Hardware:

Beide Experimente wurden auf einem Computer mit folgender Hardware ausgeführt:

  • CPU: AMD Ryzen 7 2700x mit 8 Kernen (16 Threads)
  • GPU: NVIDIA RTX 3080 mit 10 GB VRAM
  • RAM: 32 GB DDR4

TODO: Mitschriften letztes Meeting, mal an den richtigen Ort bringen:

Hypothese: Die Leistung der NNs wird sich nicht ändern (siehe LiteEyes)

Yolo S -> sehr gute Performance Laufzeit tradeoff

Alle Entscheidungen gut begründen -> z.B. welche Yolo Version, warum?

Ergebnisse Interpretieren

Vorbereitung:

Auswahl des Test-Datensatzes:

Es gibt einige Datensätze für Pupillensegmentierung mit verschiedensten Medien aufgenommen: VR, AR: z. B. NVGaze oder OpenEDS, Eye-Tracking-Brillen z. B. 500k oder LPW.

Da wir den Einfluss von Verschiedenen Formen untersuchen, ist ein Datensatz mit verschiedenen Personen relevant. Da suchen wir Personen, die
Datensätze, die explizit verschiedene Ethnien enthalten sind rar. Viele Datensätze sind von der Domäne her (VR, AR) zu weit vom hier vorliegenden Thema entfernt und enthalten somit Noise, die wir nicht repräsentieren können (z. B. Lichtbrechung durch Linsen der VR-Brille, Verdeckung gewisser Gesichtspartien durch die VR-Brille).

Für diese Arbeit wurde sich für den 500k-Datensatz entschieden, da dieser direkt Bilder und Pupillen-Masken liefert (ohne wie z. B. bei LPW über TEyeD gehen zu müssen). Außerdem ist er in zwei Teile geteilt, wobei der erste aus 10 Aufnahmen mit laborähnlichen Bedingungen besteht, was die Einflussfaktoren wie Beleuchtungsänderung, Verdeckung, Reflektionen, etc. minimiert. Des Weiteren ist er mehrfach im Rahmen vorheriger Abschlussarbeiten am CHI verwendet worden, was theoretisch eine gewisse Vergleichbarkeit zu diesen Arbeiten ermöglicht.

Konstruktion des Datensatzen

Der 500k Datensatz wird als zwei Videos geliefert. Im Datensatz sind Videos von 20 Teilnehmern. Das erste Video enthält 10 Aufnahmen unter kontrollierten, laborähnlichen auffnahmen. Das zweite Video enthält 10 schwierige Aufnahmen unter realien Bedingungen mit wechselnden Beleuchtungsszenarien, Reflektionen und Verdeckung z. B. durch eine Brille.

Wir wollen den isolierten Einfluss von unterschiedlichen Formen des Auges untersuchen, daher bietet sich das erste Video mit den laborähnlichen Aufnahmen an. Das erste Video enthält insgesamt 509379 Bilder. Dabei sei Angemerkt, dass zwischen den einzelnen Aufnahmen einige Bilder mehrfach vorkommen. Pro Teilnehmer sind enthält es im Schnitt 50937 Bilder. Was in etwa 14 Minuten Videomaterial bedeutet. Die genauen Zeitpunkte und Frame-Nummern der Teilnehmer wurden manuell mit Hilfe des Programms VirtualDub2 ermittelt. Dieses Programm erlaubt es ein Video zu öffnen und Bild für Bild zu inspizieren. Durch ziehen der Laufleiste wurde der ungefähre Zeitraum ermittelt, an dem das Subjekt wechselt. Dann wurde Frame für Frame vor bzw. zurück gegangen, bis der exakte Frame des Wechsels gefunden wurde. VirtualDub2 zeigt dann die Frame-Nummer und den exakten Zeitstempel an.

1. Extraktionsversuch

Zunächst wurde versucht, für jeden Teilnehmer einer bestimmte Anzahl Bilder zu erfassen, indem sie über die Laufzeit des Videos in regelmäßigen Abständen extrahiert wurden. Da Bilder, die kurz nacheinander aufgenommen wurden aus Prinzip für gewöhnlich sehr Ähnlich aussehen, dann wäre das Abtasten des Videos über länge Zeiträume weniger ähnlich. Das war tatsächlich aber nicht so, und viele Bilder sahen fast identisch aus.

Zur Auswertung der Ergebnisse werden nicht alle Bilder aus dem Datensatz herangezogen. Pro Teilnehmer 155 Bilder mit gleichmäßigen Zeitabständen innerhalb ihrer Aufnahmer extrahiert. Das stellt sicher, dass die Bilder eines Patienten unterschiedlich sind (weil zwei aufeinander folgende Bilder oft fast identisch aussehen können). Da es 10 Teilnehmer in diesem Video gibt, ergibt das insgesamt 1550 Bilder, für das Testset. Davon werden fünf Bilder pro Teilnehmer aus dem Testset herangezogen um die durchschnittliche Helligkeitswerte für die Teilnehmer zu extrahieren, und als Parameter für das Bilder generieren zu verwenden. Diese Bilder werden aus dem Testset exkludiert.

TODO: Darauf hinweisen, dass dadurch technisch gesehen ein vom Testset informierter Datensatz erzeugt wird.

2. Extraktionsversuch:

Also war ein Ansatz nötig, der tatsächlich visuell unterschiedliche Bilder extrahiert.

Wir möchten nach wie vor eine feste Anzahl an Bildern extrahieren. Wie Meiko auch (und die Paper, die Meiko auch Zitiert hatte) verwenden wir den Structural Similarity Index (SSIM) um die Zahl der Bilder zu reduzieren.

Algorithmus aus extract_frames.py:
Phase 1:  
1. Wir steppen mit einem bestimmten Stride über das Video eines Teilnehmers.  
2. Wenn der SSIM des aktuellen Bildes im Vergleich zum zuletzt gewählten Bild unter dem Schwellwert liegt, merken wir es uns.  
  
-> Dadurch entfernen wir Frames, die zeitlich nah beieinander liegen und sehr ähnlich aussehen.  
  
Phase 2:  
1. Alle Bilder aus Phase 1 werden auf 32 x 32 herunterskaliert, zu einem 1024-Komponenten-Vektor geplättet und auf den Bereich 0..1 normiert.  
2. Wähle einen zeitlich mittleren Kandidaten als erstes finales Bild aus.  
3. Wiederhole, bis die gewünschte Anzahl finaler Bilder gefunden wurde:  
4.     Bestimme für jeden verbleibenden Kandidaten den kleinsten Abstand zu den bereits final ausgewählten Bildern.  
5.     Wähle den Kandidaten, dessen kleinster Abstand am größten ist.  
6.     Füge das zugehörige Bild zu den finalen Bildern hinzu.

Phase 1 reduziert also die Zahl der Bilder drastisch und wählt visuell unterschiedliche Bilder aus. Da diese Menge immer noch zu groß war, und dort dises Temporale Sampling zu den selben Problemen geführt hat berechnen wir dann eine klassiche Distanz zwischen den Bildern um anhand der enthaltenen Grauwerte die unterschiedlichkeit der Bilder zu bewerten.

TODO: Auflisten, wie viele Bilder pro Person nach Phase 1 übrig blieben. Parameter auch noch auflisten (insbesondere Schwellwert für SSIM von 0.5 -> Grund: Ausprobiert, hat gut reduziert, da wir ja nach einem schön kleinen Datensatz suchen)

Die x unterschiedlichsten Bilder pro Teilnehmer wurden zusätzlich gesondert abgespeichert, um für die Kalibrierung der Luminanzwerte verwendet zu werden.

Bestimmung der Luminanz-Werte des Testdatensatzes

Die in der Datenextraktion ausgewählten Bilder wurden mit Hilfe des LEyes-parameter-Pickers, der am CHI entwickelt wurde bestimmt (Github-Link). Der LEyes-Parameter-Picker, der in Abbildung XYZ gezeigt wird erlaubt es einen Ordner mit Bildern zu öffnen. Die Bilder des Datensatzes können dann geöffnet werden und Segmentierungsmasken (Roter Bereich in der Abbildung) können mit einem Füll-Werkzeug oder einem Pinsel-Werkzeug gemalt werden. Die Anwendung zeigt dann für den gesamte Datensatz verschiedene Metriken wie durchschnittliche Luminanz und Standardabweichung an.

(TODO: Gucken, ob ich dass erwähnen möchte) Für diese Arbeit wurden einige Änderungen und Erweiterungen am Parameter-Picker vorgenommen:

  1. Anzeigen von 5, 10, 90 und 95%-Quantile der Luminanz-Werte
  2. .... das ist glaube ich für meine Arbeit irrelevant

Für jeden der fünf Teilnehmer wurden die fünf als am znterschiedlichsten bewerteten Bilder gewählt. Somit fand die Kalibierung anhand von 50 Bildern statt. Ziel der Kalibrierungsbilder ist nicht, die gesamte visuelle Vielfalt des Datensatzes abzubilden sondern stabile Schätzungen für Kenngrößen wie Mittelwert, Standardabweichung, Quantile / Min-Max-nahe Grenzen. Im Parameters Picker wurden erst 1 Bild pro Person, dann 2, dann 3 bis fünf segmentiert. Dabei hat sich gezeigt, dass bereits nach wenigen Bildern pro Teilnehmer die Kenngrößen nur noch wenig Veränderung aufweisen. Somit wurden 5 Bilder pro Testperson als praktikabler Kompromiss zwischen Arbeitsaufwand und statistischer Stabilität gewählt.

Da ein möglichst diverses Set erzeugt wurde, gab es auch einige Bilder, auf denen die Augen fast oder vollständig geschlossen waren. Damit dennoch fünf Bilder pro Teilnehmer vorlagen wurden in diesen Fällen statt den betroffenen Bildern jeweils die nächsten vom Algorithmus ausgewählten Bilder hinzugezogen. Dabei ist anzumerken, dass die Segmentierungsmasken, die im Datensatz für Pupille und Lidspaltöffnung vorhanden sind nicht direkt verwendet werden können, da z.B. Glanzlichter und ggf. Wimpern auf bzw. vor der Pupille nicht in die Grauwertverteilung für die Pupille einbezogen werden dürfen, da diese separat gerendert werden. Daher mussten Manuell neue Masken erstellt werden. (eben mit dem Parameter Picker)

Markierung der Iris um die Luminanzwerte zu extrahieren: Beachte, wie Glanzlichter und Schatten nicht markiert werden, da diese nicht in der Statistik berücksichtigt werden dürfen. Würde man die Schatten mit segmentieren, würde das die durchschnittliche Helligkeit zu niedrig ansetzen, und somit tendenziell unfair nah an der Pupille dran sein. Bei Glanzlichtern wäre sie zu hell.

Es wurden die Werte für die Pupille, Iris, Aderhaut und die Haut bestimmt.

Für Pupille und Iris wurde speziell darauf geachtet, dass die Glanzlichter nicht mit in die Wertung einfließen, da sie in der Pipeline gesondert modelliert werden und die Kalibrierung fälschlich nach oben verschieben würden. Für Iris und Sclera wurde zusätzlich darauf geachtet, dass extrem dunkle Schatten nicht mitgewertet werden. Das wurde getan, um eine Verschiebung in die Dunkelheit zu verhindern. Dabei sei angemerkt, dass derzeit keine Schatten in der Pipeline modelliert werden. Wenn der großteil des Auges im Schatten lag, dann wurden diese mit segmentiert, weil sie dann in der aktuellen Pipeline einen "gültigen" Helligkeitswert darstellen. Für die Haut wurde darauf geachtet, dass Augenbrauen und Wimpern nicht einberechnet werden.

In der Bildgenerierungspipeline wird für Haut, Sclera und Pupille jeweils ein zufälliger Wert aus einer Konfigurierten Normalverteilung ermittelt. Für die Iris wird eine Textur in der jeder Pixel einen zufälligen Grauwerte aus einer aus einer Normalverteilung als Grauwert erhält.

In der Konfiguration für die Bild-Generierung kann für jeden diese vier Bereiche die Normalverteilung konfiguriert werden. Dazu kann ein Mittelwert sowie die Standardabweichung festgelegt werden. Zusätzlich können ein Minimal- und ein Maximalwert eingestellt werden. Das stellt sicher, dass keine extremen Ausreißer außerhalb der angegebenen Reichweite erzeugt werden. Die Standardabweichung und die Normalverteilung wurden direkt auf die mit dem Parameter-Picker ermittelten Werte festgelegt. Für die Minima- und Maximalwerte wurden jedoch nicht die ermittelten Maximal- und Minimalwerte verwendet. Stattdessen wurde das 5%-Quantil als Minimalwert und das 95%-Quantil als Maximalwert gewählt. Das wurde getan, da Aufnahmen mit Kameras immer ein wenig Rauschen haben und somit extreme Ausreißer nicht als valide Werte angenommen werden können. So wurde z. B. für die Haut ein Wertebereich von [0 - 242] ermittelt. Die 5%- und 95%-Quantile sind jedoch 66 und 217. Eine Helligkeit von 0 ist für die Haut unplausibel. Es kann sein, dass ein Pixel tatsächlich einen Wert von 0 hat, z. B. weil er einen sehr dunklen Schatten repräsentiert, in der vorliegenden Pipeline würde das zufällige ziehen des Wertes 0 - oder nahe 0 - die gesamte Haut, und folglich fast das gesamte Bild schwarz wäre. Durch dass wählen des 5%-Quantils als Untergrenze wird sichergestellt, dass zwar durchaus ein dunkler, aber dennoch stets ein im Vergleich zum Testset ein plausibler Grauwert gewählt wird.

Es sei an dieser Stelle angemerkt, dass zwar kein direktes Leck von Test-Daten in das Training vorliegt, aber durch das wählen der Luminanz-Bereiche anhand der Test-Daten, liegt hier ein geringfügig vom Testset informiertes Training vor. Das ist für diese Arbeit akzeptabel, da ziel dieser Untersuchung nicht die allgemeine Generalisierungsfähigkeit von Neuronalen Netzen anhand der generierten synthetischen Daten ist, sondern nur der Einfluss von verschiedenen Augenformen von Interesse für dieses Experiment ist.

Beheben von Luminanzwerten für die Haut

Bei Tests ist aufgefallen, dass mit den neu extrahierten Werten die Haut sowohl in der alten als auch der neuen Pipeline visuell sehr falsch dargestellt wurde... Es schien, als wäre der Kontrast stark erhöht, was nicht passieren sollte...

Mein gespräch mit ChatGPT dazu:

https://chatgpt.com/c/69b6c157-91bc-8393-b1f6-f55a50cc56c6

um dieses Problem zu beheben wurde der Tiefpunkt der Kurve auf 0, 0 gesetzt und der Hochpunkt auf 1, 1.

Gibbidy Formulierung:

Da die ursprünglich verwendete Kalibrierung in der Praxis zu starken Kontrastartefakten führte, wurde eine vereinfachte Parametrisierung gewählt. Diese ist nicht als exakte photometrische Modellierung zu verstehen, erwies sich jedoch für die synthetische Datengenerierung als ausreichend.

oder

Die ursprünglich vorgesehene Kalibrierung der Hautluminanz über eine vollständige Abbildung charakteristischer Texturwerte führte in der Praxis zu unplausiblen Kontrastverstärkungen und damit zu visuell ungeeigneten Ergebnissen.
Aus diesem Grund wurde für die Generierung der synthetischen Daten eine vereinfachte Transformation verwendet, bei der die Extremwerte nicht zusätzlich auf den Zielbereich abgebildet wurden. Diese Vorgehensweise stellt keine vollständig physikalisch bzw. photometrisch exakte Kalibrierung dar, führte jedoch zu stabileren und für den Anwendungszweck hinreichend plausiblen Resultaten.

Glints

Für die glints wurden auch die Größe mit dem Paramter-Picker extrahiert. Da einige Bilder mehrere Glints enthalten, wurden diese Kopiert und die Glints einzeln markiert. Als Minimalwert wurde für die Glints auch das 5%-Quantil verwendet. Als maximum allerdings 255, was dem höchst möglichen Wert entspricht. Das wurde getan, da davon ausgegangen werden kann, dass Glints, welche https://chatgpt.com/g/g-p-693e918aca0081919b456cb68144a742-masterarbeit/c/69b6d450-89e4-8396-908a-d195d4005a49

Für Glints wurde der obere Intensitätsgrenzwert abweichend von den übrigen Regionen auf 255 gesetzt. Der Grund ist, dass Glints spekulare Reflexionen der Lichtquelle auf der feuchten Augenoberfläche darstellen. Solche Reflexe können in realen Infrarotaufnahmen lokal sehr hohe Intensitäten erreichen und den Dynamikbereich des Sensors ausschöpfen oder in Sättigung treiben. Eine Begrenzung anhand der aus den Flächenregionen abgeleiteten 95%-Perzentile wäre daher für Glints nicht angemessen.

Lidschluss

In der Konfiguration kann ein Skalierungsfaktor für eine Exponentialverteilung eingestellt werden. Je höher dieser Faktor, desto wahrscheinlicher wird das Auge ein wenig oder ganz geschlossen. Manuelles Testen hat ergeben, dass ein Faktor von 0,4 meist ein geöffnetes Auge erzeugt, aber auch ab und zu teilweise oder vollständig geschlossene Augen erzeugt.

Blur

Zur Zeit ist in der Pipeline ein konstanter Blur eingestellt. Dieser wurde aufgrund der geringen Auflösung der generierten Bilder auf 1px reduziert. Das musste über eine Code-Änderung erfolgen

Generieren der synthetischen Daten

Es wurden jeweils mit der Alten und der neuen Pipeline 5000 Bilder erzeugt. Config:

  • Seed: 42
  • Bilder: 5000
  • Luminanz-Bereich: Siehe oben
  • Eyelid-Exponent: 0.4 -> sah ganz gut aus
  • Auflösung: wie bei 500k-Datensatz 192 x 144

Die Baseline Bilder wurden innerhalb von 00:54:30 generiert. Die neuen Bilder in 00:57:45. Hierbei sei angemerkt, dass diese Zeiten nicht vergleichbar sind mit denen aus Experiment 1. Abgesehen davon, dass die Auflösung geringer ist und die Optimierte Sclera-Textur-Generierung von der neuen Version in die alte übernommen wurde, wurde der Computer während der Generierung für andere Dinge verwendet. Außerdem hat Blender 5 scheinbar ein Memory-Leak, weshalb die Bilder für die neue Pipeline auch mit Blender 4 generiert werden mussten.

# Generieren mit dem Kommando: (blender4 muss auf Blender4-Exe zeigen)
> blender4 --background Objects.blend --python render.py

Filtern der generierten Daten

Die Pipeline berücksichtigt nicht, ob die Pupille sichtbar ist oder nicht. Die Pupillen-Masken enthalten immer die gesamte Pupille, auch wenn sie z. B. teilweise oder ganz vom Augenlid verdeckt wird. Daher wurde das Script prepare_training_data.py geschrieben. Diesem Script wird bei der Ausführung übergeben, wie viel Prozent der Pupille mindestens sichtbar sein soll. Die Pupillenmasken sind Schwarz-Weiß-Bilder, wobei weiße Pixel bedeuten, dass die Pupille sichtbar ist. Die rgb_mask_covered Bilder enthalten kombinierte Segmentierungsmasken für Pupille (Rot), Iris (Grün) und die Sclera (Blau). Hier werden auch Verdeckungen berücksichtigt. Somit kann ermittelt werden, wie viel Prozent der Pupille sichtbar ist, indem die weißen Pixel in der Pupillen-Maske gezählt werden. Und dann wird gezählt, wie viele der weißen Pixel aus der Pupillen-Maske in der rgb_mask_covered Rot sind. Wenn sie nicht rot sind, sind sie nämlich verdeckt. Daraus kann der Prozentsatz errechnet werden. Für Pupillen über dem Schwellwert wird die original Pupillen-Maske ins Ausgabeverzeichnis kopiert, sonst wird eine komplett schwarze Maske kopiert. Manuelles Probieren hat gezeigt, dass bei einem Schwellwert von ca. 20% TODO! ein Grayscale, Pupil und rgb_mask_covered Bild zeigen

Von Gibbidy: EllSeg Paper: EllSeg: An Ellipse Segmentation Framework for Robust Gaze Tracking

Für die synthetisch erzeugten Daten sind sowohl die vollständige Pupillenmaske als auch die nach Verdeckung sichtbare Pupillenmaske bekannt. Dadurch kann der Okklusionsgrad direkt pixelbasiert als Verhältnis der verdeckten zur vollständigen Pupillenfläche bestimmt werden. Formal wurde der Okklusionsgrad als 1 - \frac{|P_{\mathrm{vis}}|}{|P_{\mathrm{full}}|} berechnet, wobei |P_{\mathrm{vis}}| die Anzahl der Pixel der sichtbaren Pupille und |P_{\mathrm{full}}| die Anzahl der Pixel der vollständigen Pupille bezeichnet. Dieses Vorgehen entspricht im vorliegenden Fall dem im EllSeg-Paper verwendeten IoU-basierten Okklusionsmaß, da die sichtbare Pupillenmaske eine Teilmenge der vollständigen Pupillenmaske ist. In Anlehnung an die dort empirisch gewählten Schwellenwerte wurden Pupillen ab einem Okklusionsgrad von 0,7 als stark verdeckt behandelt. Für diese Fälle wurde beim Training eine leere Segmentierungsmaske verwendet. Bei geringerem Okklusionsgrad wurde dagegen weiterhin die vollständige Pupillengeometrie als Ground Truth hinterlegt, sodass das Modell lernen soll, die durch Lidverdeckung verdeckten Bereiche implizit zu ergänzen.

Falls du es etwas vorsichtiger-wissenschaftlich formuliert haben möchtest, mein Herr, wäre diese Variante auch gut 😊

In Anlehnung an EllSeg wurden Pupillen mit einem Okklusionsgrad von mindestens 0,7 nicht mehr als regulär sichtbar behandelt, sondern beim Training durch eine leere Segmentierungsmaske repräsentiert. Damit orientiert sich die gewählte Schwelle an einer bestehenden empirischen Kategorisierung starker Okklusion, wird im vorliegenden Fall jedoch direkt über den pixelbasiert bestimmten Flächenanteil der Verdeckung umgesetzt.

Durch dieses Vorgehen wurden für den Baseline-Datensatz 783 Bilder als vollständig Verdeckt interpretiert. Im neuen Datensatz wurden 1394 Bilder als vollständig verdeckt interpretiert. Dabei sei angemerkt, dass mit der neuen Pipeline 890 Bilder tatsächlich vollständig verdeckt (also 100% verdeckt) erzeugt wurden, während in der alten lediglich 368 solche Bilder existierte. Das liegt daran, dass in den mit der neuen Pipeline generierten Bildern deutlich häufiger das Augenlid soweit geschlossen ist, dass es die Pupille vollständig verdeckt. Das kann damit zusammenhängen, dass in der neuen Pipeline das Auge tatsächlich vollständig geschlossen werden kann, weshalb der selbe zufällige Schlusswert (0.0 = offen 1.0 = maximal geschlossen) tendenziell das Auge etwas weiter schließt. Daher nähern sich die Verhältnisse bei steigendem Schwellwert auch an.

Training mit Yolo

Yolo erwartet als ground truth keine Segmentierungsmasken, sodnern Polygone, die die segmentierte Region einschließen. Daher werden keine Bilder, sondern Textdateien als Labels verwendet. Pro Bild gibt es eine Text-Datei. Jede Zeile dieser Textdatei enthält als erstes den Index der Klasse des Objekts gefolgt von den Koordinaten der Eckpunkte des Polygons welches das Objekt einschließt. Eine Zeile ist also in folgendem Format:

<class-index> <x1> <y1> <x2> <y2> ... <xn> <yn>

Für mehrere Objekte könnte die Datei z. B. so aussehen:

0 0.681 0.485 0.670 0.487 0.676 0.487
1 0.504 0.000 0.501 0.004 0.498 0.004 0.493 0.010 0.492 0.0104

Hier wären also zwei Objekte in dem Bild. Eines mit Klasse 0, eingeschlossen von einem Dreieck und eines mit Klasse 1, eingeschlossen von einem Fünfeck.

Da wir immer nur ein Objekt - nämlich die Pupille - und auch nur eine Klasse haben, enthalten diese Dateien bei uns immer nur eine Zeile.

Umwandlung von Segmentierungsmasken zu Yolo-Format

Yolo bietet eine integrierte Funktion um für alle Segmentierungsmasken in einem Ordner Textdateien im Yolo-Format zu erzeugen und diese in einem Zielordner abzuspeichern. Dieser Funktion kann man auch angeben, wie viele Klassen es insgesamt gibt. Allerdings konnte diese Funktion hier aus zwei Gründen nicht genutzt werden:

  1. Die Funktion erwartet, dass die erste Klasse den Grauwerte 1 hat. Die Masken, die von der Pipeline erzeugt werden haben aber den Grauwert 255 für die Pupille.
  2. Es gibt einen Bug, sodass bestimmte CV2 Versionen unter Windows falsch funktionieren, weshalb ein Fehler in der Yolo-Konvertierungsfunktion auftritt. Daher wurde basierend auf der von Yolo gelieferten Funktion eine neue geschrieben (siehe datei: yolotest.ipynb 😅) Diese Funktion behebt den Bug und nutzt einen Schwellwert von 127 um nur eine einzelne Maske zu extrahieren.

Trainings- und Validierungsset

Nun liegen die Bilder und Labels im korrekten Format vor. Allerdings erwartet Yolo eine spezielle Ordnerstruktur. Yolo erwartet eine Konfigurationsdatei im Yaml-Format, welche den Datensatz beschreibt.

path: current # Datensatz Wurzelverzeichnis
train: images/train # Pfad zu den Trianingsdaten (relativ zu "path")
val: images/val # Pfad zu den Validierungsdaten (relativ zu "path")
test: images/test # Optionaler Pfad zu den Testdaten (relativ zu "path")

classes:
	0: pupil

Ordnerstruktur: TODO: Die ist falsch

+ current
+-+ train
| +-+ images
| | +-- XXXX.png
| | +-- ...
| +-+ labels
| | +-- XXXX.txt
| | +-- ...
+-+ val
| +-+ images
| | +-- XXXX.png
| | +-- ...
| +-+ labels
| | +-- XXXX.txt
| | +-- ...
+-+ test
| +-+ images
| | +-- XXXX.png
| | +-- ...
| +-+ labels
| | +-- XXXX.txt
| | +-- ...

TODO:

  1. Nochmal die Bilder extrahieren, damit wir die Statisik haben, wie viele wir nach Phase 1 hatten. (Kommando ist in Experiment2/extracted_500k_images)
    1. Dafür im Script wieder alle Testpersonen aktivieren
    2. Nochmal gucken, ob 0.5 für SSIM-Schwellwert wirklich gut ist
  2. Helligkeitswerte extrahieren
  3. Mit einem kleinen Yolo-Modell testen, ob das geplotte funktioniert -> es schein einen runs-Ordner im root-Verzeichnis zu geben, da macht Yolo schon einiges
  4. Optimierungen in alte Pipeline aufnehmen
  5. Die Trainings-Bilder generieren (5000 alt, 5000 neu)
  6. Trainings der Modelle

Auswertung:

Grundlagen:

Zu berechnen:

  • IoU und Dice-Score
    • Pro Bild berechnen -> Boxplot/Violinplot
    • Durchschnitt und Std. Dev. über alle Bilder -> Tabelle

Tiefer gehen:

  • Da selbes Testset kann man gepaart vergleichen:
    • Wilcoxon Signed-Rank Test auf die per-Bild-Dice/IoU-Werte
    • oder Bootstrap-Konfidenzintervalle für die Differenz der Mittelwerte

Anteil klarer Fehlerfälle:

z. B.

  • Anteil Bilder mit IoU = 0
  • Anteil Bilder mit Dice < 0.5
  • Anteil Bilder, in denen die Pupille komplett verfehlt wurde
  • Anteil Bilder, in denen fälschlicherweise keine Pupille gefunden wurde
  • Anteil Bilder, in denen fälschlicherweise eine Pupille gefunden wurde
  • usw.

Analyse nach Bildmerkmalen / Schwierigkeiten

Wenn du aus den Daten oder Masken etwas ableiten kannst, dann unterteile nach:

  • Okklusionsgrad
  • Pupillengröße
  • Pupillenexzentrizität / Blickwinkel
  • Helligkeit / Kontrast
  • Glint-Anzahl
  • Randnähe

Dann siehst du nicht nur welches Modell besser ist, sondern auch warum.

Boundary-Metrik als Ergänzung

Falls dich die Konturgenauigkeit interessiert:

  • Boundary F1
  • Hausdorff Distance
  • Average Surface Distance

Für Pupillensegmentierung kann das nützlich sein, weil kleine Randfehler für die spätere Ellipsen- oder Mittelpunktbestimmung relevant sein können.

Pupil center error

Das RIT-Eyes-Paper nennt explizit, dass zusätzlich auch die Abweichung des Pupillenzentrums eine sinnvolle Metrik sein kann.
Für dein Eye-Tracking-Thema ist das sogar sehr relevant, weil ein Modell mit ähnlichem Dice trotzdem einen schlechteren Pupillenmittelpunkt liefern kann.

-> Da der 500k-Datensatz sowas nicht direkt bietet, müssten wir wahrscheinlich Dann berechnest du den Pupil Center Error auf zwei Arten:

  • Centroid-basiert
  • Ellipsenfit-basiert

So kannst du zwei leicht unterschiedliche Fragen beantworten:

  • Centroid:
    Wie gut stimmt der Schwerpunkt der vorhergesagten Maske mit dem der Ground Truth überein?
  • Ellipsenfit:
    Wie gut stimmt das aus der globalen Pupillenform geschätzte Zentrum überein? Das hilft dir auch bei der Interpretation:
  • Centroid schlechter, Ellipsenfit besser
    → eher lokale Formfehler / Löcher / kleine Artefakte
  • beide schlecht
    → echte Lagefehler oder grobe Segmentierungsfehler
  • Dice gut, aber Center Error schlecht
    → Segmentierung überlappt ordentlich, liegt aber leicht verschoben

Methodisch würde Gibbidy es so formulieren

Zusätzlich zu Dice-Score und IoU wurde der Fehler des Pupillenzentrums im Bildraum bestimmt. Dazu wurde das Pupillenzentrum sowohl als Schwerpunkt der binären Pupillenmaske als auch als Mittelpunkt einer an die Pupillenkontur angepassten Ellipse berechnet. Der jeweilige Pupil Center Error wurde als euklidischer Abstand zwischen dem aus der Vorhersage bestimmten Zentrum und dem entsprechenden Zentrum der Ground-Truth-Maske angegeben.

Inhaltlich wichtig für deine Argumentation

Wenn dein Ziel ist zu zeigen, dass die neue synthetische Pipeline bessere Trainingsdaten liefert, dann ist die stärkste Story meist:

  1. Höherer Dice/IoU auf realen Testdaten
  2. Weniger Ausreißer / robustere Verteilung
  3. Bessere Ergebnisse gerade in schwierigen Fällen
  4. eventuell besserer Pupillenmittelpunkt

Das ist meist überzeugender als nur ein einzelner Durchschnittswert.

TODO:

https://chatgpt.com/g/g-p-693e918aca0081919b456cb68144a742-masterarbeit/c/69b9ba88-3018-8390-a2af-0d57aa308a56

Tabelle 1 (pro Modell):

Hauptmetriken:

  • Dice: Mittelwert ± Standardabweichung, Median, IQR
  • IoU: Mittelwert ± Standardabweichung, Median, IQR

Ergänzende Metriken

  • Center Error (Centroid): Mittelwert ± Standardabweichung, Median, IQR
  • Center Error (Ellipse): Mittelwert ± Standardabweichung, Median, IQR

Tabelle 2 (Vergleich neu vs. alt):

  • mittlere Differenz pro Metrik
  • Wilcoxon-p-Wert
  • 95%-Konfidenzintervall (weil ich das in einem anderen Experiment auch schon habe)

Abbildungen

  • Boxplot/Violinplot Dice
  • Boxplot/Violinplot IoU
  • optional Center Error
  • Beispielbilder der schlechtesten Fälle

Optional: Boundary Metriken berechnen

Quantitative Untersuchung

1. Anteil Bilder mit IoU = 0

2. Anteil Bilder mit leerer vorhergesagter Maske (keine Pupille erkannt, obwohl in ground-thruth eine ist)

3. Anteil Bilder mit fälschlich erkannter Pupille (eine Pupille erkannt, obwohl in ground-thruth KEINE ist)

3. Anteil Bilder mit zu vielen Pupillen erkannt (mehrere Pupillen erkannt, obwohl in ground-thruth immer nur eine ist)

Was ich jetzt habe (und noch Plane):

  1. Dice und IoU:
    1. Tabelle für Dice und IoU mit Mean, Std.Dev., Median, Q1, Q3 und IQR
    2. Boxplot für Dice und IoU
    3. TODO: Die Daten im Testset sind zu gleichen Teilen von 10 Probanden -> Boxplot pro Proband machen
  2. TODO: Konfidenzintervall oder Wilcoxon dingsbums
  3. Pupil center error (Für Centroid und Ellipse)
    1. Tabellen
    2. Boxplots
    3. TODO: Den Fall: keine Segmentierung in GT erwartet und auch korrekt nichts predicted -> Distanz von 0 oder doch lieber NaN?
  4. Qualitativer Vergleich:
    1. (Anzahl) Fälle in denen ein Modell Dice von 1 und das andere von 0 hat: Das bedeutet, dass keine Pupille in GT ist, aber eines der beiden Modelle hat eine Pupille "erkannt" (-> Dice = 0), während das andere korrekt keine erkannt hat (Dice = 1)
    2. (Anzahl) Fälle in denen beide Modelle Dice = 0 haben, also fälschlicherweise keine Pupille gefunden oder fälschlicherweise eine gefunden haben
    3. (Anzahl) Fälle in denen ein Modell Dice von 0 und das andere von > 0 hat: Das bedeutet, dass eine Modell hat versagt, das andere aber nicht (entweder korrekt keine Pupille segmentiert, oder zumindest teilweise segmentiert)
    4. TODO: In wie vielen Fällen ist Baseline Dice besser, in wie vielen ist Current Dice
      1. TODO: Fälle mit größter Dice-Differenz visuell beurteilen
    5. TODO: In wie vielen Fällen hat eines der beiden Modelle Dice < 0.5