Emotion Recognition via Camera and Machine Learning
The content of this page is provided by Martin Eisoldt and Felix Lipinski. All rights reserved.
Language Notice
This page is available in German language only.
Project Documentation
Recognising emotions using the RGB HD camera of a personal robot and machine learning algorithms. Student project by Martin Eisoldt and Felix Lipinski
Aufgabenstellung
Ziel
Um reale Anwendungsszenarien abbilden zu können, müssen zunächst Basisfunktionalitäten geschaffen werden. So sollte Loomo zu einer Art Buttler entwickelt werden. Hierzu muss Loomo seine Umgebung kennenlernen und erkunden können, sowie geeignete Kommunikationsstrategien, entsprechend der Anforderungen seiner Nutzer, unterstützen.
Ziel dieses Komplexpraktikums soll es sein, die Kommunikation mit Loomo via Emotionserkennung zu verbessern.
Anforderungen
Die Zielerreichung setzt eine umfassende Planung voraus. Das Szenario soll in einer einzelnen App bereitgestellt werden. Die Funktionalitäten selbst sollten jedoch klar getrennt werden, um diese bei Bedarf in einer anderen App weiterverwenden zu können.
Teilaufgaben: Emotionserkennung
- Konzeption einer Vorgehensweise zur Erkennung von Emotionen. Machen Sie sich mit bestehenden Ansätzen aus dem Bereich des Machine Learning vertraut.
- Entwurf einer Nutzerschnittstelle zur Erkennung von Emotionen
- Entwickeln Sie eine Strategie zur Differenzierung der sechs Basis-Emotionen Angst/Furcht, Glück/Freude, Wut, Traurigkeit, Neugier/Überraschung und Ekel
- Implementierung der Anwendung: Erkennen von Emotionen und Ausgabe der erkannten Emotion auf dem Display
- Dokumentieren Sie Ihre Arbeit präzise
- Erfüllen Sie Bonus-Anforderungen (bspw. Zusatzemotion Verachtung. Weiterführende Emotionen. Darstellung der Emotionen auf Basis der Arbeit von Maximilian Feigl.)
Analyse
Die Analyse der Aufgabenstellung machte schnell deutlich, dass bei diesem Projekt folgende Technologien zum Einsatz kommen:
- Android/Java,
- Gesichtserkennung,
- Machine Learning,
- Loomo/Robotik
Für die Spezifikationen des Loomo stellte sich der Entwickler-Login von Segway als sehr hilfreich heraus. Dieser erlaubt sowohl den Zugriff auf detailliertere technische Spezifikationen als auch die offizielle Dokumentation.
Im folgenden sind die für dieses Projekt wichtigen Spezifikationen des Loomo aufgeführt:
- Android 5.1 (API Level 22, ohne GooglePlay Services),
- HD Kamera mit 104 Grad FOV,
- LCD Touch Screen mit 800 x 480 Pixel,
- Loomo Vision,
- Loomo Head,
Da die GooglePlay Services auf dem Roboter nicht zur Verfügung stehen, konnte nicht auf die durch diese Dienste angebotenen Implementierungen zurückgegriffen werden. Zuerst wirkte OpenCV aufgrund seiner weiten Verbreitung vielversprechend, allerdings musste diese Ansatz später verworfen werden. Die Erläuterungen dazu finden sich in Kapitel 4.2.1. Details zur aktuellen Umsetzung finden sich in Kapitel 4.1.1.
Die Suche nach geeigneten Machine Learning Algorithmen gestaltete sich insofern schwierig, dass die meisten mittels Python implementiert wurden und Python auf Loomo nicht läuft. Allerdings war TensorFlow von Anfang an sehr vielversprechend. Wesentlicher Vorteil dieser Machine Learning Umsetzung war die explizite Unterstützung mobiler Endgeräte. Außerdem wird TensorFlow durch Google angeboten, was zum einen auf eine langfristige Weiterentwicklung als auch eine gute Qualität schließen lässt.
Konzept
Folgende Anforderungen wurden an die Architektur gestellt:
- Erweiterbarkeit der Emotionen,
- Modularität, d.h. dass die Architektur in anderen Projekten einfach wiederverwendet werden kann,
- Erweiterbarkeit der Funktionalität durch z.B. erweiterte Emotionsausgabe
Erster Entwurf
Im ersten Entwurf wurden schon grundlegend die definierten Anforderungen berücksichtigt. Da allerdings noch nicht klar war, welche spezifischen Technologien sich am besten eignen, sind die Klassen, d.h. Namen, Attribute und Methoden, allgemein gehalten. Dieser Entwurf ist auf Basis der Überlegungen in Kapitel 2 entstanden, ohne jedoch die konkrete Umsetzbarkeit genauer zu betrachten.
In der MainActivity wird auf den CameraStream mittels OpenCV zugegriffen. Auf einem Frame erkannte Gesichter werden im FaceRepository verwaltet. Dieses wird pro Frame aktualisiert. Der aktuelle Frame wird jeweils an alle erkannten Gesichter übergeben. In der Face Klasse werden folgende Daten gespeichert: Position (x, y), Größe des Gesichts (Höhe, Breite), Bildausschnitt des Gesichts und die erkannte Emotion. Die Standardemotion ist “Thinking”. Die Verarbeitung des Frames findet in der ImagePreprocessor Klasse statt, d.h. zuschneiden und skalieren. Das bearbeitete Bild wird in den EmotionRecognition Algorithmus gegeben. Die Rückgaben dieses Algorithmus werden im OutputPreprocessor interpretiert und die erkannte Emotion standardisiert zurückgegeben. Die Ausgabe ist noch nicht näher spezifiziert. Der erste Entwurf der GUI sah vor, dass die Emotionen direkt auf die erkannten Gesichter “gezeichnet”werden. Dies ist in Abbildung 2 zu sehen. Die Auswahl der zu verwendeten Emojis erfolgt später und wird im finalen Entwurf näher erläutert.



Finaler Entwurf
Im finalen Entwurf (Abbildung 4) ist zu sehen, dass die Grundstruktur aus dem ersten Entwurf beibehalten wurde, jedoch auch einige Anpassungen nötig waren. Zunächst zu den Gemeinsamkeiten.
Die Gesichtserkennung gibt die erkannten Gesichter an das FaceRepository. Dort werden diese verwaltet, d.h. es werden die Gesichter des aktuellen Frames in einer ArrayList gespeichert. Die Klasse Face bzw. EmojiFace gibt das Frame an eine Klasse zur Bildverarbeitung weiter und bekommt das bearbeitete Bild zurück. Danach wird dieses an einen Machine Learning Algorithmus weitergeben, welcher einen Wert für die Emotion zurück gibt. Daraus kann in der Klasse des Gesichts das Objekt der entsprechenden Emotion erstellt werden. Diese sind als Interface implementiert, um eine leichte Erweiterbarkeit zu gewährleisten.
Neben der offensichtlichsten Überarbeitung, den Klassenbezeichnungen, kommen wir nun zu den Unterschieden. Camera2VideoFragment bildet das Äquvalent zur MainActivity. Hier werden alle nötigen Services initialisert (Details zu einzelnen Methoden, Attributen und Funktionsweisen sind in Kapitel 4.2.1 zu finden). Im FaceRepository wird nun durch die Methoden klar, wie die Verwaltung der EmojiFaces geschehen soll. Die Klasse EmojiFace ist nun um Methoden erweitert wurden, die größtenteils die Position und Größe des Gesichts verwalten und damit für die Eigenschaften des zu malenden Emojis benötigt werden. Die ImageProcessor Klasse wurde auf die nötigen Funktionen reduziert, die da wären: Bild zuschneiden, skalieren und drehen. Der daraus entstandene Bildausschnitt wird an TensorFlow übergeben und gibt wiederrum die Emotion zurück. Auf einem Thread läuft parallel dazu die Ausgabe des Kamera Streams und das Zeichnen der Emojis des in AutoFitDrawableView übergebenen FaceRepositorys.


GUI
Die GUI hat sich zum ersten Entwurf nicht sehr stark verändert. Durch das aufgenommene Bild ist ein Vollbildmodus ohne Verzerrung oder Verluste von Bildteilen nicht möglich. Daher wird der Kamerastream skaliert und auf dem Bildschirm zentriert. Zusätzlich zur Ausgabe der Emoji Repräsentation (siehe Abbildung 5) wird oberhalb dieser noch die ID des Gesichts und unterhalb die Wahrscheinlichkeit der Emotion ausgegeben. Die ID zählt dabei bei jedem neu erkannten Gesicht hoch. Auch wenn eine Person aus dem Blickfeld der Kamera heraus und danach wieder hinein tritt, zählt dies als neues Gesicht.
Implementierung
Die finale App hat als Grundlage die Camera2Video Sample App [6]. Darauf aufbauend wurde die vorgesehene Architektur implementiert. Als Schnittstellen sind die Klasse Camera2VideoFragment als Input und die Klasse AutoFitDrawableView als Output zu sehen. Außerdem ist der Machine Learning Algorithmus (hier TensorFlow Mobile) leicht austauschbar. Die Kopfbewegung von Loomo wurde in dieser Anwendung mit dem DTS realisiert und verfolgt dadurch den erkannten Körper, nicht das Gesicht.
Architektur
Der grundlegende Programmablauf wurde bereits in Kapitel 3.2 erläutert. In diesem Abschnitt soll es um Besonderheiten in der Architektur gehen.
Camera2VideoFragment
In der Klasse Camera2VideoFragment findet, sobald der View erstellt wurde, die Initialisierung der benötigten Services und Funktionalitäten statt. Dies schließt den View (AutoFitDrawableView) ein. Außerdem wird hier eine Instanz von TensorFlow erstellt, welche dann an das FaceRepository übergeben und dort an die EmojisFaces weitergereicht wird. Es ist wichtig TensorFlow nur einmalig zu initialisieren, da sonst Performanceeinbußen zu beobachten sind. Mit der Methode bindServices() werden die Services Vision und Head aus dem Loomo SDK initialisiert, welche für die Verbindung zur Kamera und das DTS sowie für die Kopfbewegung des Loomo verantwortlich sind.
public void onViewCreated (final View view , Bundle savedInstanceState) { autoFitDrawableView = view.findViewById(R.id.texture); tensorFlow = new TensorFlow (); tensorFlow.setContext(getActivity()); faceRepository.setTf(tensorFlow); bindServices ( ) ; }
Im Folgenden Codeauschnitt ist die Schnittstelle zwischen CameraStream und der Gesichtserkennung zu sehen. Dabei kommt die Android Gesichtserkennung zum Einsatz, die mit einer Zeile sehr effektiv ist. Welche Daten der Klasse Face vorliegen, findet man in der zugehörigen Dokumentation [3].
Wenn Gesichter erkannt wurden, wird zunächst ein Bitmap des aktuellen Frames erstellt. Danach werden Frame und Gesichter in das FaceRepository übergeben und dort verarbeitet. Im Anschluss wird das FaceRepository an den AutoFitDrawableView übergeben um die Emojis der erkannten Gesichter auszugeben.
private CameraCaptureSession.CaptureCallback mFaceCaptureCallBack = new CameraCaptureSession.CaptureCallback() { @Override public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) { super.onCaptureCompleted(session, request, result); //detected face array Face[] faces = result.get(CaptureResult.STATISTICS_FACES); if(faces!=null && faces.length > 0) { Bitmap frame = autoFitDrawableView.getPreview().getBitmap(); faceRepository.insert(faces, frame); autoFitDrawableView.drawRect(faceRepository); } } };
FaceRepository
Im FaceRepository werden die erkannten Gesichter verwaltet. D.h. neu erkannte Gesichter werden durch neue EmojiFace Objekte angelegt und wiederkehrende Gesichter werden aktualisiert. Die Überprüfung eines vorhandenen Gesichts erfolgt über die ID der Klasse Face. Das Update des EmojiFaces ist in 2 Phasen unterteilt. In der Standardphase werden nur die Gesichtsdaten, also x- und y-Position, Höhe und Breite sowie alle weiteren Daten aus der Klasse Face, aktualisiert. In der zweiten Phase, die in der aktuellen Implementierung alle 60 Frames eintritt, wird zu den Gesichtsdaten auch der aktuelle Frame übergeben um die Emotionserkennung auszulösen. Dies wird durch folgende Attribute gesteuert:
private int countFrames = 0; private int countFramesLimit = 60;
Das stellt die aktuelle Lösung für das auftretende Performanceproblem dar, welches die Bildbearbeitung und die Berechnung der Emotion durch TensorFlow auslösen. Das Attribut countFrames ist dabei eine Zählvariable, welche bis countFramesLimit hochzählt und dann wieder auf 0 zurückgesetzt wird. Jeweils bei 0 wird dann die Emotionserkennung ausgelöst.
EmojiFace
Die Klasse EmojiFace implementiert als Standardemotion “Thinking”. Dies ist nötig um den Fall abzudecken, dass noch keine Berechnung der Emotion stattfand. Zur Zeit dient dieses Emoji auch als Platzhalter für den Fall, dass keine Emotion mit ausreichender Sicherheit erkannt wurde.
Die folgenden zwei Funktionen sind zur Anpassung der durch Face vorgegebenen Umrandung (repräsentiert durch ein Rechteck [4]) nötig. Diese wurden aus der Sample App übernommen, ebenso wie die Klasse FaceUtil, welche die Berechnung durchführt. Dort sind Konstanten definiert, die für die Berechnung genutzt werden, jedoch nicht dokumentiert und somit nicht nachvollziehbar sind.
public RectF calculateFaceRange (final Rect face) {} private RectF transformRect (RectF rectF) {}
ImageProcessor
Die Klasse ImageProcessor wurde als selbstständige Klasse implementiert, um so eine einfache Erweiterung der Bildverarbeitung zu ermöglichen. Diese Erweiterungen könnten z.B. ein Histogrammausgleich oder eine Bildentzerrung sein.
In der Methode transform(Bitmap bitmap) wird das übergebene Bild an das Display angepasst. Die Maße sind durch folgende Attribute vorgegeben:
int viewWidth = 640; int viewHeight = 480;
Diese Werte sind an das mit der HD Kamera aufgenommene Bild (Seitenverhältnis 4:3) angepasst. Nach der Skalierung wird das Bild noch um -90 Grad gedreht. Dies wird durch die Kameraposition und die Displayausrichtung nötig.
Die Methode cropImage(Bitmap bitmap, RectF faceRect) schneidet das Übergebene Bild entsprechend der in RectF gespeicherten Gesichtsumrandung zu. Dabei wird in alle Richtungen ein Toleranzbereich von 20% hinzugefügt. Dies verbessert die Emotionserkennung merklich.
TensorFlow
TensorFlow wird beim Start der App initialisiert. Sobald ein Gesicht erkannt wurde, wird der entsprechende Bildausschnitt an die Funktion predictEmotion übergeben. In dieser wird das Bild auf 224×224 Pixel zurecht geschnitten. Sollte die Größe der Inputbilder für die Erstellung des Graphen anders gewählt werden, muss diese Größe hier entsprechend angepasst werden. Nachdem die Pixel normalisiert wurden, werden sie in den TensorFlow Graphen gegeben, welcher dann die entsprechende Emotion berechnet. Als Ergebnis wird eine Liste mit den entsprechenden Wahrscheinlichkeiten sowie zugehörigen Emotionen geliefert. Für die weitere Verarbeitung ist nur die Emotion mit der höchsten Wahrscheinlichkeit von Relevanz. Sobald diese Wahrscheinlichkeit über 0,5 liegt, wird diese zurückgegeben. Die Rückgabe ist dabei eine HashMap, die den Index der Emotion sowie die zugehörige Wahrscheinlichkeit beinhaltet. Sollte es keine Emotion geben, deren Wahrscheinlichkeit 50 % übersteigt, wird null zurückgeliefert.
Emotion
Die Klasse Emotion wurde als Interface implementiert um eine leichte Erweiterbarkeit von weiteren Emotionen zu gewährleisten. Die derzeitigen Emotionsbezeichnungen sind dem Klassendiagramm 4 zu entnehmen. Die Emotionen besitzen das Attribut emoji vom Typ int, welches auf das entsprechende Bild im Drawable Ordner zeigt.
AutoFitDrawableView
Dem AutoFitDrawableView wird über die Methode drawRect(FaceRepository faceRepository) das FaceRepository des aktuellen Frames übergeben. Der in setUpViews() initialisierte CustomView besitzt ebenfalls eine Methode drawRect(final FaceRepository faceRepository), welche als neuer Thread implementiert ist. Dies ermöglicht die verzögerungsfreie Ausgabe des CameraStreams. Durch diese Trennung des CameraStreams und des Outputs der Emojis über ein Canvas, können Verzögerungen nur beim Zeichnen der Emojis auftreten.
Im Folgenden ist das Zeichnen der Emojis, inklusive Face ID und Wahrscheinlichkeit der berechneten Emotion aller erkannten Gesichter zu sehen.
for (EmojiFace emojiFace : faceRepository.getEmojiFaces()) { RectF faceRangeRectF = emojiFace.calculateFaceRange ( emojiFace.getFace().getBounds()); // draws the face ID canvas.drawText("id =" + emojiFace.getFace().getId(), faceRangeRectF.left, faceRangeRectF.top − 15, paint); if(emojiFace.getConfidence() != null ) { canvas.drawText("confidence =" + emojiFace.getConfidence() + "%", faceRangeRectF.left, faceRangeRectF.bottom + 25, paint); } paint.setColor(Color.GREEN); paint.setStrokeWidth(3.0f); // get emotion representation/emoji and convertit to Bitmap Drawable d = getResources().getDrawable( emojiFace.getEmotion().getEmoji()); Bitmap emojiBitmap = convertToBitmap(d, emojiFace.emojiWidth(), emojiFace.emojiHeight()); // draw the emoji canvas.drawBitmap(emojiBitmap, emojiFace.emojiXPosition(), emojiFace.emojiYPosition(), paint); }
Mit emojiFace.getConfidence() wird die Wahrscheinlichkeit der erkannten Emotion abgefragt. Wenn der Rückgabewert gleich null ist, wird keine Wahrscheinlichkeit ausgegeben, da diese dann unter 50% liegt. Diese Rückgabe wurde in der Klasse TensorFlow in der Methode predictEmotion(Bitmap bitmap) festgelegt.
Verworfene Technologien
Im Verlauf des Projekts war es notwendig diverse Technologien bzw. Frameworks zu testen. Der Schwerpunkt lag dabei auf der Gesichtserkennung und dem Machine Learning. Im Folgenden werden solche Technologien vorgestellt, die teilweise oder komplett implementiert wurden, jedoch verworfen werden mussten.
OpenCV
Zunächst wirkte OpenCV als sehr vielversprechend, da es von einer großen Community entwickelt wird und auch viele Beispielanwendungen vorhanden sind. Allerdings wird unter Android eine minimierte Version von OpenCV verwendet. Dies hat an einigen Stellen andere Lösungen als unter Java benötigt. Auch stellte sich die Dokumentation für OpenCV4Android als lückenhaft heraus. Als größtes Problem stellte sich jedoch heraus, dass es nicht möglich war, den Kopf von Loomo einem erkannten Gesicht folgen zu lassen, ohne weitere Ressourcen aufzuwenden. Im Einzelnen hätte es bedeutet, einen neue Verbindung zur Kamera aufzubauen und darüber das DTS laufen zu lassen. Dies hätte die Architektur verkompliziert und gegen unsere Software Anforderungen verstoßen. Aus diesem Grund wurde sich für die jetzige Umsetzung entschieden und OpenCV verworfen.
Python für Android
Aufgrund der Tatsache, dass die meisten Machine Learning Anwendungen auf Python basieren, musste sich nach Möglichkeiten umgesehen werden, mit denen sich Python auf Android umsetzen lässt. Hierfür klang kivy [2] sehr vielversprechend. Dabei sind aber schon bei der Einrichtung zu Testzwecken große Problem aufgetreten, weshalb die Entscheidung gegen diese Technologie gefallen ist. Problematisch wäre perspektivisch dann auch sicher die Kombination mit anderen Modulen für Loomo geworden.
Nutzung von TensorFlow in der App
Als Datengrundlage für die Modellerstellung dient ein von Kaggle zur Verfügung gestellter Datensatz [1]. Dieser umfasst insgesamt 28.709 Bilder für die 6 Grundemotionen (und zusätzlich den Ausdruck “neutral”). Die Bilder dafür sind in Ordnern gelabelt und haben die Größe von 32×32 Pixeln. Die Modellerstellung erfolgt zuerst als normales Desktopmodell auf einem Rechner der Wahl. Danach wird der Graph für die mobile Verwendung optimiert. Erst dieser erstelle Graph (der mit Python erzeugt wurde) wird dann in den assets Ordner der App eingebunden und kann fortan genutzt werden. In dieser App wird die Version für TensorFlow Mobile verwendet.
Probleme
Workflow
Als schwierig für die Arbeit hat sich immer wieder erwiesen, dass die Dokumentation des Loomo SDK sehr spärlich ist. Auch die durch Segway zur Verfügung gestellten Beispielanwendungen sind nur kaum bis gar nicht kommentiert und lassen dadurch nur wenige Rückschlüsse auf die Funktionsweise zu. Erstaunlicherweise ist auch TensorFlow Mobile nur wenig bis gar nicht dokumentiert. Dies ist insofern problematisch, als das sich die mobile Umsetzung stark von der normalen unterscheidet. Gerade im Zusammenhang mit den Parametern für die Modellerstellung stellt dies ein Hindernis dar.
Weiterhin auftretende Probleme
Größtes Problem der entwickelten App ist die unzuverlässige Emotionserkennung. Die Ursache hierfür liegt in dem erstellten Graphen, beziehungsweise in der Datengrundlage. Bereits das normale Modell weißt eine Genauigkeit von ca. 30 % auf. Diese wird automatisch von TensorFlow ermittelt. Entsprechend setzt sich dieses Problem auf dem Loomo fort.
Die Korrektheit der ermittelten Emotion wird zusätzlich durch den Datensatz limitiert. Die Qualität der darin enthaltenen Bilder ist sehr durchwachsen. Die Größe von 32×32 Pixeln bereitet auch insofern Probleme, dass durch TensorFlow Mobile nur die Bildgrößen 128,160,192 und 224px optimal unterstützt werden.
Bei der Anwendung des Modells auf dem Roboter entsteht zusätzlich das Problem der Verzerrung. Ursache hierfür ist die Größe des Loomo, dieser schaut immer von unten. Der Testdatensatz wiederum hat aber zum Großteil Frontalaufnahmen, weshalb die Ergebnisse dann am besten sind, wenn man direkt in die Kamera schaut. Durch diese Perspektive tritt dann auch noch das Problem der Gesichtserkennung bei Gegenlicht zu Tage. Da aufgrund der Perspektive auch Deckenlicht für Gegenlicht sorgt und nicht nur einstrahlendes Tageslicht, tritt dieser Umstand häufiger auf.
Durch die Verwendung von DTS verfolgt der Kopf des Roboters den Oberkörper einer erkannten Person, aber somit nicht zwangsläufig den Kopf. Auch ist nicht immer klar zu sagen, welcher Person er folgt, wenn mehr als eine Person erkannt werden.
Benutzung
Android Studio
Für die Einrichtung von Android Studio ist lediglich zu beachten, dass die SDK Version 22 (entspricht Android 5.1) installiert ist. Weitere Besonderheiten sind nicht zu beachten.
Aufgrund der aktuellen Implementation unter Verwendung des Loomo SDK ist eine Nutzung der App auf dem Emulator beziehungsweise einem Android Handy nicht möglich. Um dies zu ermöglichen, müssen die entsprechenden Klassen aus dem Code entfernt werden.
Erstellung des Modells mittels TensorFlow
Für TensorFlow ist zwingend notwendig, dass auf dem System Python 3.5 läuft, mit anderen Versionen ist TensorFlow nicht funktionsfähig, beziehungsweise kann es auch mittels pip -install nicht installiert werden.
Die Erstellung eines neuen Modell folgt im wesentlichen den Anleitungen unter TensorFlow for Poets [7] Sobald das entsprechende Modell erstellt ist, muss dies in den assets Ordner der Android Anwendung verschoben werden und kann dann direkt verwendet werden. Die Datei mit den Labels wird für die Funktionsweise der Anwendung nicht benötigt, allerdings ist sie für die Nachvollziehbarkeit durch Dritte durchaus sinnvoll.
Loomo
Für die Verwendung auf dem Loomo ist zu beachten, dass die Zugriffsrechte für die Kamera erteilt werden müssen. Ansonsten wird die App nicht starten und mit einer Fehlermeldung abstürzen. Vorgenommen wird die Einstellung für die Berechtigungen unter Einstellungen -> Apps -> Berechtigungen. Sollte ein Loomo der ersten Generation zum Einsatz kommen, muss dieser auch in den Entwicklermodus gesetzt werden. Dieser wird über Einstellungen -> Home -> Launcher eingestellt.

Ausblick
Um die Emotionserkennung zu verbessern sollte die Datengrundlage verändert werden. Der Kaggle Datensatz weißt eine gewisse Menge von fehlerhaften Bildern auf (beispielsweise Smileys). Außerdem ist die Auflösung der Bilder mit 32×32 Pixeln sehr gering.
Um dieses Problem zu bewältigen ist die Lösung mit den höchsten Erfolgsaussichten sicher eine Verwendung eines anderen Modelldatensatzes beziehungsweise die Erstellung eines eigenen Datensatzes. Weitere Probleme bestehen darin, dass die Verzerrung in den Bildern ausgeglichen werden sollte. Diese entsteht durch die niedrige Position der Kamera im Loomo. Somit lässt sich das Problem nicht auf Seiten der Hardware lösen, sondern muss durch Software geregelt werden.
Ein weiteres Problem besteht durch das Gegenlicht. Somit werden Gesichter zum Teil nicht erkannt. Hier wäre es vorstellbar, die erfassten Bilder so zu bearbeiten, dass diese Einflüsse verringert werden. Möglicherweise ist auch die Optimierung des TensorFlow Modells mit mehr Fehlern behaftet, als erwartet. Vorstellbar wäre an dieser Stelle auch die Umstellung auf TensorFlow Lite. Dabei handelt es sich um eine Weiterentwicklung der mobilen TensorFlow Anwendung. Aufgrund des Aufbaus der Schnittstellen in der App sollte dies Umstellung gut umsetzbar sein.
Auch sollte betrachtet werden, ob die Auswahl der Emotionen optimal ist, oder ob nicht eine Verringerung der möglichen Emotionen zu besseren Ergebnissen führt. Beispielsweise ist der größte Unterschied zwischen den Emojis für Überraschung und Furcht, dass bei letzterem zwei Hände abgebildet werden. Da Emojis eine vereinfachte Darstellung von Gesichtern realer Menschen darstellen, deutet auch dies bereits auf eine schwierige Unterscheidung in der vorliegenden App hin.
Des Weiteren ist eine zusätzliche Validierung der erkannten Emotion durch Analyse der Sprache der erkannten Person beziehungsweise möglicher Indizien der Körperhaltung vorstellbar. Hierfür ist aber sicherlich ebenfalls eine Analyse nötig, inwiefern dies relevante und messbare Indikatoren sind.
Literatur
[1] Challenges in Representation Learning: Facial Expression Recognition Challenge | Kaggle https://www.kaggle.com/c/challenges-in-representation-learning-facial-expression-recognitionchallenge Zugriff: 15.06.2018
[2] Kivy: Cross-platform Python Framework for NUI Development https://kivy.org/ Zugriff: 06.06.2018
[3] Klassendokumentation für Androids Klasse Face https://developer.android.com/reference/android/hardware/camera2/params/Face Zugriff: 23.10.2018
[4] Klassendokumentation für Androids Klasse RectF https://developer.android.com/reference/android/graphics/RectF Zugriff: 23.10.2018
[5] Lizenzbedingungen für Emojis https://www.emojione.com/licenses/free Zugriff: 23.10.2018
[6] Sample that shows how to use Camera in FollowMe Mode https://github.com/SegwayRoboticsSamples/Camera2VideoSample Zugriff: 15.06.2018
[7] Tensor Flow for Poets https://codelabs.developers.google.com/codelabs/tensorflow-for-poets/index.html Zugriff: 11.08.2018
[8] Quelle für verwendete Emojis (Stand 23.10.2018: nicht mehr aufrufbar, allerdings sind Versionen 3 und 4 vorhanden, mit gleichen Lizenzbedingungen) https://www.emojione.com/emoji/v2 Zugriff: 30.05.2018