======= Dokumentation ======= Download our Code here: {{:projektewise18:icontact:icontact_code.zip|}} \\ Welcome to //iContact// ! Hier findet ihr die Dokumentation unseres Semesterprojekts //iContact// - einem Setup für eine Eingabe ohne Hände und Stimme. Inspiriert wurde unser Projekt durch den Künstler Jason Becker, einem Musiker und Komponisten, der seit seinen 20. Lebensjahr an ALS leidet und er seitdem nur äußerst schwer seiner Leidenschaft weiter folgen konnte. Mithilfe einer Zeichensprache, die Freunde und Familie von seinen Augen ablesen können, ist er allerdings trotzdem immer noch in der Lage zu komponieren. Unser Ziel ist es, ein Programm zu entwickeln, dass es dem Benutzer ermöglicht, mithilfe von Augenbewegungen Text einzugeben. Dies soll Menschen mit ALS (Krankheit, die zu einer Ganzkörperlähmung und zum Stimmverlust führt) helfen zu kommunizieren. Die Erfassung der Bewegung soll also automatisch geschehen. Dazu soll mittels einer WebCam die Position der Augen ermittelt und die Bewegung der Pupillen aufgezeichnet und ausgewertet werden. Durch eine spezielle Zeichensprache sollen die Bewegungen in Buchstaben bzw. Befehle übersetzt werden. Optional können Bewegungen mit z.B. den Augenbrauen oder dem Mundwinkeln mit Sensoren wahrgenommen werden. Das werden wir bei ausreichender Zeit hinzufügen. WebCam und Sensor anschließen, Programm starten, auf Kalibrierung warten und es kann losgehen. Der Nutzer blickt in verschiedene Richtungen und gibt mit jeweils einem Paar aus zwei Augenbewegungen einen Buchstaben ein. Eine zusätzliche Bildschirm-"Tastatur" für Zahlen und Symbole, die Möglichkeit Dateien zu speichern (und Öffnen) sowie einige Optionen zur Konfiguration erweitern die Flexibilität. Programm abgestürzt, oder versehentlich beendet? Kein Problem, denn eine automatische Sicherung kann den Verlust wiederherstellen. Bei einer Schreibgeschwindigkeit von nur einigen Wörtern pro Minute kommt es auf jeden Absatz an! \\ \\ Übrigens: \\ \\ **Diese Zeile wurde mit unserem Programm geschrieben (und hierher kopiert)! ** {{ :projektewise18:icontact:diese_zeile_wurde...png?500 |}} \\ \\ Viele Probleme haben wir erst auf die eine, dann auf eine andere Weise gelöst. Am Anfang haben wir z.B. noch keine Gesichtserkennung von OpenCV verwendet, später nur noch Augenerkennung, dann sogar die Nase und zuletzt gar nicht mehr. Mittlerweile arbeitet unser Programm fast gänzlich ohne externe Libraries, außer //Serial// und //Video// für das Einlesen der Daten vom USB-Port und der WebCam. Stattdessen hat es sich als nützlich erwiesen, selbst einige Klassen und eine Library zu schreiben - eigentlich sogar unbedingt notwendig, da unser Code schon nach anderthalb Monaten unglaublich lang und unübersichtlich zu werden drohte. Besonders kritisch sind natürlich die Aktionen in //setup()// und //draw()//, da manche Einstellungen hier kollidieren können und beide Methoden mittlerweile wahrscheinlich weit über 300 Zeilen hätten. Ein paar Klassen sind hauptsächlich Wrapper für die vereinfachte und abgeschlossene Bedienung der Kamera und der Kommunikation mit dem Arduino. Andere, wie **GData**, der **ECScreen** (Eye-Control-Screens) und der **EyeTracker** sind viel umfangreicher: Sie dienen der Echtzeitbearbeitung der Kameradaten, der Darstellung der Eingabeanweisungen bzw. dem gewaltigen Prozess der Augenkalibrierung und -erkennung sowie dem Auswerten der resultierenden Daten. Die eigene Library **ProcessingGUI** ist entstanden, weil existierende GUI-Libraries uns nicht ausgereicht haben und generell zum Teil eher weniger zufriedenstellend und flexibel sind (unten mehr dazu). Unser Projekt lässt sich zwar deutlich in verschiedene Phasen gliedern, aber an vielen Dingen haben wir parallel gearbeitet und einige Aspekte nebenher weiterentwickelt. So sind die Übergänge in den Projektphasen oft eher fließend. **Hier ein genauerer Überblick in unseren Arbeitsprozess und die einzelnen Schritte und Maßnahmen**:
    Navigation:
  1. Gesichts- und Augenerkennung
  2. Live-Bewegung
  3. Biegemessstreifen
  4. Eye-Language
  5. Interface erstellen
  6. Extra - Automatische Wortvorgabe

Gesichts- und Augenerkennung

  1. Gesicht finden und erkennen
  2. Augenerkennung
  3. Abstände und Verhältnisse einrichten

Live Bewegung

  1. Pupillenposition dauerhaft überprüfen
  2. Position der Pupille auf Bildschirm anzeigen

-> gaze-plot.png

Biegemessstreifen

  1. Signale lesen und einbringen
  2. Sensor am Gesicht anbringen
  3. Arduino mit Processing verbinden
  4. Schutzhülle

Eye-Language

  1. Eye-Language definieren

Interface erstellen

  1. Zuerst haben wir die in Processing verfügbaren Methode text(x,y,String) verwendet, um die jeweilige Ausgabe darzustellen. Allerdings wollten wir gerne mehrzeiligen, umbrechenden und scrollbaren Text zeigen. Es gibt zwar Libraries für GUIs in Processing, aber sie sind ein wenig starr im Design und Textboxen, die in der Lage sind mehrzeiligen Text darzustellen gibt es überhaupt nicht. Aus dem Wunsch das ausführlicher zu machen ist dann die ProcessingGUI entstanden. Es gibt momentan Buttons, Menüs, Container, ScrollArrangements, Textboxen, Listen, Slider, Checkboxen und einige mehr. Die Komponenten lassen sich sehr frei designen und mittlerweile sogar automatisch animieren. Eventhandler wie mouse-enter / exit / press / release / scroll / drag / move und keypress können zu jedem Objekt hinzugefügt werden. Man kann nach wie vor die gewöhnlichen Zeichenfunktionen aus Processing mit der Oberfläche kombinieren.

    Die Textbox verhält sich schon fast wie man es erwartet: Es gibt einen blinkenden Cursor, der sich mit den Pfeiltasten verschieben lässt; mit der Maus kann der Cursor ebenfalls gesetzt werden und Text kann wie gewohnt ausgewählt werden. Copy/Paste/Cut Funktionen dürfen auch nicht fehlen...

    Für optimale Performance werden nur die Komponenten neu gezeichnet, die sich geändert haben (und ihre Eltern-Objekte), die Grafik aller Objekte wird stets in einer PGraphics gespeichert und beim Rendern abgerufen. Der Hauptcontainer, der sogenannte Frame, indem sich alle Objekte befinden müssen (nicht unbedingt direkt, denn durch Container sind auch Verschachtelungen möglich), verwaltet das Zeichnen, Aktualisieren, automatische Animieren und alle Events für die GUI. Alle Container Rendern wiederum ihre enthaltenden Objekt und leiten Maus- und Tastatur-Events an ihre Items weiter usw...

    Eine genauere Beschreibung der Funktionsweise würde allerdings hier den Rahmen sprengen. Bei Interesse einfach mal schreiben.

Extra - Automatische Wortvorgabe

  1. Für die Wortvorgabe hatten wir vor, eine Baumstruktur zu verwenden. In jedem Node (Knoten) steht genau ein Zeichen, sodass ein Pfad ein Wort ergibt. Jeder Node enthält außerdem eine Zahl, die eine Wertung für die Häufigkeit angibt. So werden häufige Wörter eher vorgeschlagen als selten verwendete.

    Ein Pfad kann auch mehrere Wörter enthalten: Eisenbahn → “Eis”, “Eisen”, “Eisenbahn”. Die Nodes mit den Zeichen ‘i’, ‘e’, ‘b’ etc. haben die Wertung 0 und zählen daher nicht als Wort (so wird zum Beispiel “Eisenb” nicht vorgeschlagen). Beispiel: Durch diese Struktur können wir “Eis”, “Eisen”, “Eisenbahn”, “Eisenach” und “Eisbein” mit nur (theoretisch) 16 Zeichen speichern. Außerdem wird das Suchen durch diese Ordnung stark beschleunigt, vor allem wenn sehr viele Wörter gespeichert sind. Da auch Wörter durch den Nutzer automatisch hinzugefügt und die Häufigkeiten reguliert werden, muss das Vokabular in eine Datei gespeichert werden. Die einfachste Idee ist, beim Speichern einfach alle Wörter zu bilden und als Zeilen zu speichern. Beim Öffnen des Programms wird die Datei eingelesen und alle Wörter neu zum Baum hinzugefügt. Es erweist sich aber als schwierig dabei effizient auch die Häufigkeiten zu berücksichtigen.

    Der zweite Ansatz baut auf dem Prinzip von xml-Dateien auf. XML-Dateien sind zum Beispiel so aufgebaut:
    <abschnitt>
      <part>
      </part>
    
      <part>
        <inhalt>
        </inhalt>
      </part>
    </abschnitt>
    
    Damit lassen sich sowohl Listen als auch Baumstrukturen realisieren, nur sind bei den vielen <>-Tags mit nur wenig Inhalt die ‘<’, ‘>’-Zeichen sehr verschwenderisch, daher sieht unser Ansatz deutlich anders aus: Aus der langen Struktur (hier ohne "Eisenach")...
    |<E> 
    |   <i> 
    |      |<s>
    |      |   <e> 
    |      |      <n> 
    |      |         <b> 
    |      |            <a> 
    |      |               <h> 
    |      |                  <n> 
    |      |                  </n> 
    |      |               </h> 
    |      |            </a> 
    |      |         </b> 
    |      |      </n> 
    |      |   </e>
    |      |   <b> 
    |      |      <e> 
    |      |         <i> 
    |      |            <n>
    |      |            </n>
    |      |         </i>
    |      |      </e>
    |      |    </b>
    |      |</s>
    |   </i>
    |</E>. 
    ...wird:
     E i s e n b a h n ////// b e i n /////// 
    Dabei schließt ein ‘/’ je einen Tag. Die Zahlen werden je hinter den Buchstaben geschrieben.
     E0 i0 s1 e0 n1 b0 a0 h0 n1 ////// b0 e0 i0 n1 /////// 
    Auch das lässt sich noch weiter komprimieren, zum Beispiel können alle Leerzeichen weggelassen werden, wenn die Zahlen durch Steuerzeichen ersetzt werden, die man nicht in normalem Text verwendet (So bleit die Möglichkeit erhalten, auch Ziffern in den "Wörtern" mitzuspeichern). Auch die Nullen (sind am häufigsten) können weggelassen werden, wobei unser Parser stets eine 0 annimmt, wenn keine Zahl dasteht.
    Sowohl das Abspeichern als auch das Einlesen und Suchen haben wir rekursiv gelöst, was hier übersichtlicher ist, als iterativ zu arbeiten.

    In einem kleinen Programm (auch im Code oben zu finden) haben wir das implementiert (Achtung, es wird wieder unsere GUI-Library verwendet). Beim Eingeben werden in der Liste unten Wörter vorgeschlagen, die beim Anwählen die Eingabe vervollständigen.


  2. Behälter für den Arduino
    • Nach einer Brainstorming Session standen wir vor zwei Optionen. Entweder wir würden eine Box mithilfe von einem 3D-Drucker fertigen lassen, oder selbst eine Box aus Holz bauen. Da die Kosten beim 3D-Druck allerdings voraussichtlich zu hoch werde würden, haben wir uns für die zweite Option entschieden. Die Box sollte leicht und klein sein, weshalb wir relativ dünne Holzplatten verwendeten. Diese sägten und schliffen wir passend und klebten sie mit Holzkleber daraufhin. Als Schließmechanismus entschieden wir uns für zwei Magneten, deren Befestigung aber ziemlich ermüdend war, weil die verschiedenen Kleber meistens nicht lange gehalten haben. Nach einigen Versuchen sind die Magnete aber an ihrem Stellen geblieben.
FM0   FC010000000:zzzzzz11d e3 00  0  09364fc fa14e1040 c3010d25f 55  0260 eb24c
 0  0  0  0 0 0 0 021361186110  032 020161186110  033 01ef61186110  0 c
01dd61186110  072 01cb61186110  033 01b961186110  033 01a761186110  033
019561186110  033 018361186110  033 017161186110  033 015f61186110  033
014d61186110  033 013b61186110  033 012961186110  033 011761186110  033
010561186110  033 0 f361186110  033 0 e161186110  033 0 cf61186110  033 0
bd61186110  033 0 ab61186110  033 0 9961186110  033 0 bf61186110  033 0
c761186110  034 0 cf61186110  034 0 d761186110  034 0 df61186110  034 0... AC Bscale(2.0) Dscale(2.0) enhenced_level(0) isOutdoor(0) result(1)   FM0  
FC001001100:zzzzzz01b f8 00  0  05f040045042c1040 c3010d25f 55  028a115276  0  0
 0  0 0 0 0 02765136511d  0 2 026551355118  0 2 0254512e510f  0 0 0243512d510e 
090 023251275103  0 2 022151295101  0 2 021051355101  0 2 01ff513a50ff  0 2
01ee514f5106  0 2 01dd51535102  0 2 01cc51745115  0 2 01bb518c5121  0 2
01aa51d9513e  0 2 0199520d515e  0 2 018852415175  0 2 017752915191  0 2
016652c551ad  0 2 0155532351dc  0 2 0144532851da  0 2 0133531c51e2  0 2
0155534e51e7  0 2 015d531d51de  0 2 016553b4522e  0 2 016d53c7523e  0 2...
==== Ausblick ==== - Ursprünglich hatten wir noch vor eine Sprachausgabe mit einzubringen, jedoch hat die Zeit nicht gereicht. - Außerdem wäre es sehr interessant, noch einmal einen ganz anderen Ansatz zu probieren und mit maschinellem Lernen, statt mit Hard-Coding bei dem Erkennungsproblem zu arbeiten. Das würde sich bei der Sicherheit und Stabilität der Ergebnisse bei der Positionsauswertung sicher auszahlen.