Erster Platz:

ReadToMe

Inspiration

Die Inspiration für ReadToMe kam von meinen Kindern. Insbesondere meine beiden Jüngsten, die 3 und 5 Jahre alt sind. Beide lieben Bücher, aber sie lesen noch nicht alleine. Ich wollte etwas schaffen, mit dem sie Spaß am Lesen haben können, wenn auch gerade kein Elternteil verfügbar ist, um ihnen vorzulesen.

Funktionsweise

ReadToMe nutzt Deep Learning und Computervision in Kombination mit den in AWS verfügbaren Services. Sie müssen AWS DeepLens nur eine Seite zeigen, die es lesen soll, und es liest sie laut vor.

Entwickelt vonAlex Schultz

Erfahren Sie mehr über Alex und das ReadToMe-Projekt in diesem AWS Machine Learning-Blogbeitrag.

Entwicklung

Der Workflow mag einfach klingen, aber es gab viele Herausforderungen, die es zu meistern galt, um am Ende erfolgreich zu sein. Hier sind die einzelnen Probleme, die ich lösen musste.

  • Bestimmen, wann sich eine zu lesende Seite im Kamerafokus befindet
  • Isolieren des Textblocks und Bereinigen des Bilds mit OpenCVV
  • Durchführen von OCR (Optical Character Recognition, optische Zeichenerkennung)
  • Umwandeln von Text in Sprache
  • Abspielen des Tons über die Lautsprecher

Jeder der oben genannten Schritte brachte unerwartete Herausforderungen mit sich (und teilweise war ich nicht mehr sicher, ob ich dieses Projekt rechtzeitig abschließen könnte).

Bestimmen, wann sich eine zu lesende Seite im Kamerafokus befindet

ReadToMe nutzt Deep Learning und Computervision in Kombination mit den in AWS verfügbaren Services. Sie müssen AWS DeepLens nur eine Seite zeigen, die es lesen soll, und es liest sie laut vor. Damit DeepLens eine Seite lesen kann, muss es erkennen, ob es etwas im Kamerafokus zu lesen gibt. Hier kommt das Deep Learning-Modell zum Einsatz.

Ich suchte online, konnte aber kein vorgefertigtes Modell finden, das in der Lage war, Buchseite zu klassifizieren. Infolgedessen wusste ich, dass ich ein Modell mit neuen Daten trainieren musste, um diese Art von Objekt zu klassifizieren.

Um Trainingsdaten zu erhalten, habe ich eine Schnellsuche online durchgeführt, um Bilder von Kinderbüchern zu finden. Ich fand unzählige Bilder von Buchumschlägen, aber praktisch keine Bilder, die jemanden zeigten, der das Buch in der richtigen Ausrichtung hält, damit ich das Modell damit trainieren konnte. Ich brauchte Bilder mit Seiten, auf denen Text zu lesen war. Glücklicherweise habe ich vier kleine Kinder und sie haben Hunderte von Kinderbüchern. Also schnappte ich mir eines Nachts etwa vierzig Bücher und fing an, viele Fotos von mir selbst zu machen, wie ich die verschiedenen Bücher in verschiedenen Ausrichtungen hielt, sie beleuchtete und mit der Hand verschiedene Teile der Seite verdeckte.

Während dieses Prozesses wurde mir klar, dass die Textblöcke in diesen Kinderbüchern sehr unterschiedlich sind. Manchmal war der Text weiß auf schwarz und manchmal schwarz auf weiß. Ab und zu war es auch farbiger Text auf unterschiedlich farbigen Hintergründen. Hin und wieder lief der Text am Ende der Seite entlang und einige Bücher hatten Text auf der ganzen Seite ohne logischen Lesefluss. Also beschloss ich, mich stattdessen auf Bilder von Büchern zu konzentrieren, bei denen der Text in einer "relativ normalen" Position präsentiert wurde. Bei einem zu breiten Datensatz kommt am Ende vermutlich nur ein Modell raus, das alles für einen Textblock hält. In der Zukunft kann ich vielleicht mit unterschiedlicheren Arten von Daten experimentieren, aber für dieses Projekt habe ich mich entschieden, sie einzugrenzen.

Nachdem ich die Daten erfasst hatte, generierte ich mit labelImg die Pascal VOC-XML-Dateien, die für das Training eingesetzt werden sollten. An dieser Stelle kam ich nicht gleich weiter. Ich wusste nicht, wie ich meine Daten richtig formatieren kann, um sie für das Training mit MXNet zu verwenden. Ich habe ein paar Beispiele mit TensorFlow gefunden, weshalb ich mich für diese Methode entschieden habe. Ich dachte mir, wenn das Projekt mal abgeschlossen sein wird, kann ich mich am Ende noch um die Funktionalität mit MXNet kümmern, wenn es die Zeit erlaubt. Ich konnte einem der Beispiele folgen, die ich auf YouTube gefunden habe, und landete bei einem funktionierenden Modell, mit dem ich Text auf einer Seite erkennen konnte. 

Durchführen von OCR (Optical Character Recognition, optische Zeichenerkennung)

Ich war überrascht, wie einfach es war, Tesseract in das Projekt zu integrieren. Man muss es nur auf dem Gerät installieren und das Python-Paket installieren und schon war der Workflow wirklich nur noch ein einziger Funktionsaufruf. Man stellt ein Bild für die Verarbeitung bereit und am Ende kommt Text dabei raus. Ursprünglich wollte ich eine separate Lambda-Funktion verwenden, bei der Tesseract installiert war, um die OCR durchzuführen, aber am Ende habe ich sie einfach in meine Haupt-Lambda-Funktion aufgenommen, weil das einfacher war und der Datenverkehr von und zu AWS reduziert wurde. Die eigentliche OCR schien nicht allzu viel Rechenleistung in Anspruch zu nehmen und im Vergleich zu einer kompletten AWS-Rundreise hat es auch nicht wirklich länger gedauert. Außerdem wird jetzt mehr "auf dem Edge" ausgeführt, was effizienter ist und weniger kostet.

Es gab nur ein Problem mit Tesseract. Es meckert ständig wegen der Bildqualität. Es war extrem aufwändig, herauszufinden, wie man die Bilder so weit anpassen kann, dass sie problemlos gelesen werden können. Außerdem hätte der Text fast vollständig horizontal sein sollen (was ziemlich unmöglich ist, wenn man bedenkt, dass ich möchte, dass Kinder im Vorschulalter damit umgehen sollen können). Ich habe OpenCV für den Großteil der Bildvorverarbeitung verwendet und nach einer Reihe von Iterationen erhielt ich zuverlässig Bilder, auf denen einfacher Schwarzweißtext mit minimalen Störeffekten zu sehen war. Das war entscheidend für den Erfolg des Projekts. Das Endergebnis war besser, als ich erwartet hatte, aber es gibt noch Luft nach oben.

Umwandeln von Text in Sprache

Das war der einfachste Schritt des ganzen Projekts. Nachdem ich auf dem Gerät Audio wiedergeben konnte, konnte ich diese Logik in einem einzigen Funktionsaufruf unterbringen, bei dem einfach AWS Polly aufgerufen wird, um die Audiodatei zu erzeugen. Ich schreibe die Datei nie auf die Festplatte, ich füge einfach den Byte-Stream in die Audiobibliothek ein und lösche sie wieder, wenn sie fertig abgespielt ist. Ich habe ein paar statische mp3-Dateien, die beim Start des Green Grass-Services abgespielt werden. Mit diesen Audiodateien kann ich dem Benutzer sagen, wie das Gerät zu benutzen ist. Ich dachte mir, es würde keinen Grund geben, Polly aufzurufen, um diese Einführung abzuspielen, da es sich nie ändern wird. Deshalb habe ich sie im Voraus generiert und in Lambda integriert. (Ich finde es toll, dass ich vorhandene AWS-Services so einfach in meine Projekte integrieren kann!)

Abspielen des Tons über die Lautsprecher

Bei Green Grass muss die gesamte Hardware, auf die der Code zugreifen kann, explizit autorisiert werden. Eine Möglichkeit besteht darin, dies über den Abschnitt Group Resources in der AWS IOT-Konsole zu konfigurieren. Nach der Konfiguration stellen Sie diese Einstellungen für DeepLens zur Verfügung. Dadurch wird eine JSON-Datei im Green Grass-Verzeichnis auf dem Gerät bereitgestellt.

Um die Audiowiedergabe über Lambda zu ermöglichen, müssen zwei Ressourcen hinzugefügt werden. Die Soundkarte auf DeepLens befindet sich unter dem Pfad "/dev/snd/". Man muss sowohl "/dev/snd/pcmC0D0p" als auch "/dev/snd/controlC0" hinzufügen, um Sound abspielen zu können.

Außerdem muss man diese Ressourcen bei jeder Projektbereitstellung auf dem Gerät neu hinzufügen. Als ich diese Zeilen verfasst habe, überschrieb Green Grass bei jeder DeepLens-Projektbereitstellung die Ressourcendatei noch mit einer vorkonfigurierten group.json-Datei. 

Erfolge, die mich stolz machen

Ich war sehr glücklich darüber, was am Ende bei dem Projekt herauskam. Trotz eines Vollzeitjobs und vier Kindern war ich in der Lage, etwas wirklich Cooles zu erschaffen, das in nur wenigen Monaten relativ gut funktionierte. Ich habe noch weitere Ideen über zukünftige Projekte mit diesem Gerät und freue mich schon darauf, selbst auch mehr dabei zu lernen. 

Was ich gelernt habe

Vor diesem Projekt hatte ich von Deep Learning oder KI im Allgemeinen keinen Schimmer. Ich war schon immer an dem Thema interessiert, aber es schien für "normale Entwickler" immer unzugänglich. Ich habe durch diesen Prozess entdeckt, dass es möglich ist, wirklich nützliche Deep-Learning-Projekte ohne einen Doktortitel in Mathematik zu erstellen, und dass mit genügend Aufwand und Geduld jeder mit entsprechend Entwicklungserfahrung dazu in der Lage ist, was auf die Beine zu stellen. 

Die Zukunft von ReadToMe

Ich habe noch ein paar Ideen, wie man das Projekt verbessern könnte. Ich würde zum Beispiel gerne noch eine Funktion hinzufügen, mit der der vorgelesene Text automatisch übersetzt wird. (Ich habe mich für den frühen Zugang zu Amazons neuem Translate-Service angemeldet, wurde aber noch nicht bewilligt.) Ich habe außerdem vor, mein Modell weiter zu verbessern, um zu sehen, ob sich die Modellgenauigkeit nicht erhöhen lassen kann, damit ein breiteres Spektrum an Büchern abgedeckt wird.

Außerdem hat die Textbereinigungsfunktion, die direkt in Tesseract integriert ist, Verbesserungspotential. Es wäre vor allem toll, wenn man das Bild drehen oder verkrümmen könnte, bevor man es an Tesseract schickt. Somit könnte der Text auch dann noch gelesen werden, wenn das Kind das Buch nicht im "richtigen" Winkel hält. Bewegungsunschärfe war auch noch ein Problem bei der Bildbereinigung. Wenn das Buch nicht mehrere Sekunden lang still gehalten wird, ist das Bild einfach zu verschwommen für OCR. Ich habe über verschiedene Techniken zur Lösung dieses Problems gelesen, wie z. B. die Verwendung der Bildmittelwertbildung über mehrere Einzelbilder oder die Anwendung verschiedener Filter auf das Bild, um die Pixel zu glätten. Ich bin sicher, dass es möglich ist, ein besseres/schnelleres Ergebnis zu erzielen, aber es ist schwierig, das auf einem ressourcenbeschränkten Gerät zu realisieren.

Nützliche Ressourcen

Es gab viele Online-Ressourcen, die mir dabei geholfen haben, aber diese Links erwiesen sich als die hilfreichsten.

(In keiner bestimmten Reihenfolge)

https://becominghuman.ai/an-introduction-to-the-mxnet-api-part-1-848febdcf8ab
http://gluon.mxnet.io/chapter08_computer-vision/object-detection.html?highlight=ssd
https://github.com/apache/incubator-mxnet/blob/master/example/image-classification/README.md
https://github.com/zhreshold/mxnet-ssd
https://pythonprogramming.net/introduction-use-tensorflow-object-detection-api-tutorial/

Vielen Dank auch an alle Benutzer in den Foren, die meine Fragen beantwortet haben, und vor allem an das AWS DeepLens-Team, das mir mehrmals weitergeholfen hat! :)

Entwickelt mit

opencv
deeplens
python
polly
tesseract-ocr
lambda
mxnet
tensorflow