EyeTracking (2009)

Aus toolbox_interaktion
Wechseln zu: Navigation, Suche

Projekt Eye-Tracking

Aufgabe

Der Grundgedanke unserer Projektarbeit zielte darauf ab, den Blickpunkt auf einem Monitor zu erkennen und diesen mit einem Kreuz zu markieren.


Gesamtrealisierung

Nach der Einarbeitung in EyesWeb und OpenCv begannen wir mit der Strukturierung unserer Aufgaben. Die eigentliche „Hough Circle Transformation“ wurde durch die Möglichkeit eines [eigenen Blockes] in EyesWeb („My-Block_1“) realisiert, welcher unter Visual Studio implementiert wurde. Bei den ersten Versuchen die Augen zu detektieren, wurden sehr viele falsche Kreise erkannt und wir stellten schnell fest, dass ein Weg zur Einschränkung des „Erkennungsfeldes“ gesucht werden musste. Wir kamen auf die Möglichkeit die Pupille so zu separieren, dass die Wahrscheinlichkeit, falsche Kreise im Gesicht zu detektieren, möglichst gering wird. Durch dieses Vorgehen wurde die Pupille relativ gut und fehlerfrei erkannt .


Da mit den Bewegungen der Augen gearbeitet wird, war unsere Idee sehr davon abhängig in welcher Entfernung und in welchem Bereich des Bildes die abgebildete Person zu sehen war. Es musste ein geeigneter Bezugspunkt im Bild geschaffen werden. Eine Möglichkeit war die Konturen des Kopfes zu erkennen und die Augenbewegungen auf diese Kanten zu beziehen. Eine weitere, das Aufkleben eines roten Punktes auf die Stirn zwischen den Augen. Für diese entschieden wir uns.

Da die rote Farbe ebenfalls sehr gut separierbar ist, konnte man diesen Kreis gut erkennen. Nun waren wir in der Lage die Augenbewegungen, bezogen auf den Punkt, unabhängig von der Position im Bild zu berechnen, was ebenfalls in einem eigenen Block namens „Bezugspunkt_1“ untergebracht wurde.

Da bei jeder neuen Benutzung des Systems dieser rote Punkt wieder neu auf die Stirn geklebt wird, muss es eine Justierung geben, die es ermöglicht auf solche Änderungen der Abstände zu reagieren. Nach Überlegungen über eine automatische Justierung und die damit verbundenen Aufgabenstellungen, entschieden wir uns aus zeitlichen Gründen für eine manuelle Einstellung, da diese leichter zu realisieren war. Da es darauf ankam das Blickfeld zu erfassen, mussten in der ersten Phase die Abstände zwischen Auge und roten Punkt gemessen werden um diese dann einem Punkt auf dem Bildschirm zuordnen zu können, wie zum Beispiel „Links oben“, „rechts unten“ usw. Wir wählten folgende Herangehensweise. Während eine Person vor der Kamera sitz und die genannten Punkte (Links oben, rechts oben, …) fokussiert, kann eine Zweite die Werte der Abstände ablesen und an den Schiebereglern für die Justierung einstellen. Diese Werte werden nun im Block „Justierung_1“ mit den „Live-Werten“ verglichen und ausgewertet.

Die Darstellung des Blickfeldes der Testperson realisierten wir durch eine Anzeige eines Kreuzes auf dem Bildschirm. Die erforderlichen Eingabewerte für diesen bereits in EyesWeb verfügbaren Block wurden ebenfalls im Block „Justierung_1“ berechnet. Da eine weitere Forderung von uns die Unabhängigkeit der Größe des Bildschirmes war, berechneten wir die Werte so, dass nur ein Faktor zwischen 0 und 1 aus dem Justierungsblock herausgegeben wird. Dieser kann in EyesWeb mit der jeweiligen gewünschten Bildschirmauflösung multiplizieren werden. Die Auflösung kann wiederum mit Reglern eingestellt werden.

Gesamt.jpg




Teilfunktionen:

Augenseparation/Rotdetektion

Zur besseren Erkennung der Augen und des roten Punktes verwendeten wir die in einer früheren Projektarbeit benutzten Farbsegmentierung.

Augesparation.jpg Roterpunktsparation.jpg


Kreiserkennung

Die Kreiserkennung wurde mit Hilfe einer OpenCv Funktion namens Hough Circle Transformation durchgeführt.

Hough Circle Transformation: Diese Funktion basiert zum Großteil auf der „Hough Transformation“, die ein Verfahren zur Erkennung von Kanten, Kreisen oder beliebig anderen geometrischen Figuren dient. Dies geschieht durch das Erschaffen eines Dualraumes, in dem für jeden Punkt im Bild, der auf einer Kante liegt, alle möglichen Parameter der zu findenden Figur eingetragen werden. Wichtig ist zu wissen, dass dieses Verfahren nur mit binären Gradientenbildern (schwarzweiß-Bildern) funktioniert. Zudem muss eine Kantendetektion durchgeführt werden. Die Umwandlung des Bildes und die Detektion der Kanten sind ebenfalls als Funktionen in der Bibliothek OpenCv vorhanden.


Die „Hough Circle Transformation“ basiert nun auf diesem Prinzip unter der Zugrundelegung des Kreises als geometrische Figur. Es wird für jeden Kantenpunkt ein Kreis eines bestimmten Radius gesucht, der durch diesen Punkt führt. Alle Kreismittelpunkte, die zu einem Kantenpixel führen, werden in eine Maske eingetragen. Wenn mehrere Punkte im Bild einen Kreis darstellen, wird dies durch einen hohen Wert in der Maske an einem bestimmten Kreismittelpunkt erkennbar.

Die Funktion wurde von uns in einem eigenen Block realisiert und steht zum Download hier bereit.

Als erstes muss das Eingangsbild in ein schwarzweiß-Bild konvertiert werden. Dies geschieht durch die Funktion „cvCvtColor“. Da eine Umspeicherung erfolgt, wird zuvor ein neuer Speicherplatz reserviert. Die eigentliche Kreiserkennung wird durch die Funktion „cvHoughCircles“ realisiert. An diese werden einige Parameter übergeben. Der erste ist das in ein schwarzweiß umgewandeltes Bild, an dem die Erkennung durchgeführt werden soll und als zweites der reservierte Speicher. Der Parameter „CV_HOUGH_GRADIENT“ gibt an, welche Methode benutzt werden soll. In diesem Fall wird die aus Kapitel 2 bekannte Hough Transformation verwendet. Der folgende Wert ist eine Aussage über die gewünschte Auflösung des Bildes, gefolgt von der minimalen Entfernung der Mittelpunkte zweier erkannter Kreise. Zwei weitere Parameter sind für die im Vorhinein durchgeführte Kantendetektion mit Hilfe des Canny Operators. Die letzten geben den minimalen und maximalen Durchmesser der zu erkennenden Kreise an. Viele dieser Werte wurden durch testen oder Vorgaben von OpenCv gewählt. Als nächstes werden die einzelnen erkannten Kreise durchgegangen und jeweils der Radius und die X-Y-Position in einem Array gespeichert. Dies machten wir uns zunutze indem die Werte innerhalb der Schleife abgefangen wurden und in ein von uns angelegtes Array kopiert wurden. Da für das weitere Vorgehen nur die X-Y-Werte interessant sind werden auch nur diese aus unserem Block heraus gegeben.


Bezugspunkt

Die erforderlichen Berechnungen wurden ebenfalls in einem Block „Bezugspunkt“ durchgeführt.


Als Eingabewerte kommen die X-Y-Werte sowohl von der Erkennung der Augen (Kreis_x, Kreis_y) als auch von der Erkennung des roten Punktes (Bezug_x, Bezug_y) in den Block. Bevor die Berechnungen durchgeführt werden, wird überprüft, ob überhaupt Kreise erkannt wurde. Ist das nicht der Fall, macht auch eine Berechnung keinen Sinn. Dies geschieht mit einer If-Abfrage. Bei einer Nichterkennung der Kreise wären die Koordinaten Null. Nachdem sichergestellt ist, dass beide erkannt werden, wird die eigentliche Auswertung durchgeführt. Diese besteht aus dem Subtrahieren der einzelnen X- und Y-Werte voneinander. Somit wird als Ergebnis der X- beziehungsweise Y- Abstand der Pupille zum roten Punkt ausgegeben und kann weiter verwendet werden.


Justierung

Als letzten „eigenen Block“ realisierten wir die Justierung „Justierung_1“.

Justierung.jpg

Die Aufgabe dieses Blockes ist die Umrechnung der gelieferten Abstände des Auges zum Bezugspunkt auf ein am Bildschirm dargestelltes Kreuz, das den Blick symbolisieren soll. Um die Größe des Bildschirmes und die daraus resultierenden Abstände des Auges vom Punkt berechnen zu können, muss im Vorfeld eine Einstellung per Hand vorgenommen werden. Bei dieser sieht die Testperson in alle Ecken des Bildschirmes und in die Mitte. Eine zweite Person kann mit Hilfe der Displays die jeweiligen Werte ablesen und an den zugehörigen Reglern einstellen. Als weitere Parameter werden die momentan gemessenen Abstände in den Block gegeben.

Die Berechnungen finden wieder innerhalb des Blockes Justierung statt.

Am Anfang des Blockes wird eine If-Abfrage durchgeführt. Diese überprüft ob im Vorfeld die beiden Kreise erkannt wurden. Um einen bildschirmgrößenunabhängigen Parameter zu bekommen, ist darauf zu achten, dass die momentanen Abstände auf die Gesamtgröße bezogen werden. Dies geschieht indem wir die linke obere Ecke von unserem „istx“ Wert abziehen und durch die Differenz der gesamten horizontalen Breite teilen. Dadurch bekommt man einen Faktor der zwischen Null und Eins liegt und die genaue X-Position, multipliziert mit der Bildschirmgröße, repräsentiert. Das gleiche System wird mit der vertikalen Position durchgeführt, indem vom „isty“ Wert die linke untere Ecke abgezogen wird und wieder durch die gesamte Y-Länge geteilt wird. Eine Besonderheit ist der Faktor „1000“ in der Rechnung. Dieser dient dazu den Wert der zwischen 0 und 1 liegt auf einen Wert zu bringen der zwischen 0 und 1000 liegt. Da wir mit Integer Werten arbeiten und auch diese aus dem Block heraus geben, wäre eine Zahl zwischen 0 und 1 nicht auswertbar. Um weiterhin mit diesem Zahlentyp arbeiten zu können, entschieden wir uns für diese Umrechnung.


Darstellung

Abb.2: Testbench in EyesWeb

Da die gewünschte Display-Größe variabel einstellbar sein sollte, haben zwei externe Regler bereitgestellt anstatt feste Displaygrößen bereits im Justierungs-Block zu implementieren. Die Regler bestimmen die Größe des Displays in welchem man die Blickverfolgung darstellen möchte. Die eingestellten Werte werden mit dem Faktor, der im Justierungsblock berechnet wurde multipliziert. Anschließend folgt noch eine Division durch 1000, da um auf eine Datentypwandlung zu verzichten im Justierungsblock selber mit 1000 multipliziert wurde.

In Eyes- Web befinden sich bereits fertige Blöcke mit deren Hilfe man Punkte in einem Bild markieren kann. Mit diesen haben wir nun unsere berechneten Werte in einem weißen Bild darstellen lassen. Da sich große Schwankungen auf Grund von falsch erkannten Kreisen ergaben haben wir noch einen Mittelungsblock eingefügt, so dass sich ein etwas glatterer Verlauf ergab.




Realisierung in EyesWeb

Das Gesamtpatch kann hier runtergeladen werden [1] (Die Arbeit wurde mit EyesWeb 3.3.0 durchgeführt)


Vorgehen bei der Realisierung

Bei der Blockerstellung haben wir uns nach den Richtlinien orientiert für die bereits ein [eigenes Tutorial] vorhanden ist.

Die Include- und Bibliotheksdateien müssen in den entsprechenden Dialogfenstern manuell eingebunden werden. Für unser Projekt mussten folgende Dateien eingebunden bzw Einstellungen vorgenommen werden:

Projekt-> Einstellungen-> Linker: Objekt/Bibliotheksmodule: EyesWebSDKd.lib cv.lib cxcore.lib cvaux.lib highgui.lib


Extras-> Optionen-> Verzeichnisse->Include-Dateien:

\...\OPENCV\CV\INCLUDE \...\OPENCV\CXCORE\INCLUDE \...\OPENCV\OTHERLIBS\HIGHGUI \...\OPENCV\LIB \...\OPENCV\ML\INCLUDE \...\EYESWEB3.3.0\DEV\SDK\INCLUDE


Extras-> Optionen-> Verzeichnisse->Bibliothek-Dateien:

\...\OPENCV\CV\SRC \...\OPENCV\CVAUX\SRC \...\OPENCV\CXCORE\SRC \...\OPENCV\LIB \...\EYESWEB3.3.0\DEV\SDK\LIBRARY

Erst wenn alle Dateien richtig eingebunden sind kann das Programm fehlerfrei kompiliert werden. Um den Block für EyesWeb erstellen zu können muss dieser zuerst noch registriert werden.


Extras-> Anpassen-> Extras-> Steuerelement re&gistrieren: Argumente: '/v "$(TargetPath)"' Ausgangsverzeichnis: $(TargetDir) Extras-> Anpassen-> Extras-> Steuerelement &deregistrieren: Argumente: \u "$(TargetPath)" Ausgangsverzeichnis: $(TargetDir)


Wichtig für die Funktion der Blöcke ist die genaue Einhaltung der Syntax.