Première place :

ReadToMe

Inspiration

ReadToMe a été inspiré par mes enfants. Plus précisément, mes deux plus jeunes qui ont 3 ans et 5 ans. Tous deux adorent les livres, mais ils ne peuvent encore lire seuls. Je voulais créer quelque chose qu’ils pourraient utiliser pour continuer à lire, même quand un parent n’est pas disponible pour leur faire la lecture.

Ce qu’il fait

ReadToMe fonctionne en utilisant le deep learning et une aide visuelle par ordinateur combinés aux services disponibles dans AWS. Il vous suffit de montrer à AWS DeepLens la page que vous souhaitez lire, et il la lit à voix haute.

Créé par : Alex Schultz

En savoir plus sur Alex et le projet ReadToMe dans ce post du blog AWS Machine Learning.

Élaboration

Aussi simple que puisse paraître le flux de travail, de nombreux défis ont dû être surmontés pour que cela fonctionne. Voici les problèmes individuels que je devais résoudre.

  • Déterminer quand une page à lire se trouve dans le cadre de la caméra
  • Isoler le bloc de texte et nettoyer l'image à l'aide d'OpenCV
  • Effectuer OCR (Reconnaissance Optique de Caractères)
  • Transformer le texte en audio
  • Lecture audio via les haut-parleurs

Chacune des étapes ci-dessus a présenté des défis inattendus (dont certains m'ont amené à douter de ma capacité de terminer ce projet à temps !)

Déterminer quand une page à lire se trouve dans le cadre de la caméra

ReadToMe fonctionne en utilisant le deep learning et une aide visuelle par ordinateur combinés aux services disponibles dans AWS. Il vous suffit de montrer à AWS DeepLens la page que vous souhaitez lire, et il la lit à voix haute. Pour que DeepLens puisse lire une page, il lui fallait un moyen de savoir s’il y avait quelque chose à lire dans le cadre de l’appareil photo. C'est là que le modèle deep learning a été utilisé.

J'ai cherché en ligne mais je n'ai pas trouvé de modèle pré-formé capable de classer une page dans un livre. En conséquence, je savais que je devrais former un modèle avec de nouvelles données pour classifier ce type d'objet.

Pour obtenir des données de formation, j’ai effectué une recherche rapide en ligne afin de trouver des images de livres pour enfants. J'ai trouvé des tonnes d'images de couvertures de livres, mais pratiquement rien qui montre une personne tenant un livre dans l'orientation correcte pour que je puisse m'entraîner. J'avais besoin d'images des pages réelles contenant du texte. Heureusement, j'ai quatre jeunes enfants et ils ont des centaines de livres pour enfants. Alors, un soir, j'ai attrapé une quarantaine de livres et commencé à prendre beaucoup de photos de moi tenant les différents livres dans des orientations différentes, avec un éclairage et avec ma main à différents endroits de la page.

Au cours de ce processus, j’ai commencé à comprendre que les blocs de texte dans ces livres pour enfants variaient considérablement. Parfois, le texte était blanc sur noir ou parfois noir sur blanc. D'autres fois, il s'agissait de texte coloré sur différents arrière-plans.. Parfois, le texte apparaissait au bas de la page et certains livres avaient du texte sur toute la page sans aucun flux logique. J'ai donc décidé de réduire mon champ d'action et de ne capturer que les images de livres contenant du texte dans un positionnement « plutôt normal ». J’ai supposé que si j'essayais d’obtenir un ensemble de données trop large, je finirais avec un modèle qui pensait que tout était un bloc de texte. Plus tard, je pourrai peut-être expérimenter avec des types de données plus variés, mais pour ce projet, j'ai décidé de les limiter.

Après avoir capturé les données, j'ai utilisé labelImg pour générer les fichiers XML Pascal VOC qui seraient utilisés lors de la formation. À ce stade, je me suis retrouvé coincé à essayer de trouver un moyen de formater correctement mes données pour pouvoir utiliser MXNet. J'ai trouvé quelques exemples d'utilisation de TensorFlow et c'est donc le chemin que j'ai emprunté. Je me suis dit que si je terminais le projet, je pourrais toujours revenir en arrière et le faire fonctionner avec MXNet s’il me restait du temps. J'ai pu suivre l'un des exemples que j'ai trouvés sur YouTube et me suis retrouvé avec un modèle de travail que je pourrais utiliser pour détecter du texte sur une page. 

Effectuer la reconnaissance optique de caractères

J'ai été surpris de la facilité d'intégration de Tesseract dans le projet. Installez-le simplement sur le périphérique et puis installez le paquet python, et ensuite le flux de travail n’est en réalité qu’un simple appel de fonction. Vous fournissez une image à traiter, et il fournit du texte. À l'origine, j'allais utiliser une fonction Lambda séparée sur laquelle Tesseract était installé pour effectuer l'OCR, mais j'ai fini par l'inclure simplement dans ma fonction Lambda principale, car cela était plus simple et réduisait le trafic vers et provenant d'AWS. L’OCR n’a pas semblé prendre trop de puissance de calcul et, comparé à l’aller-retour avec AWS, le temps semblait être comparable. De plus, je fais maintenant plus de tâches « en périphérie », ce qui est plus efficace et coûte moins cher.

Il y en avait un souci avec Tesseract. Il est très pointilleux sur la qualité de l'image. Beaucoup d'efforts étaient requis pour trouver un moyen de nettoyer les images pour obtenir une lecture nette. Tesseract souhaite également que le texte soit presque complètement horizontal (ce qui est pratiquement impossible compte tenu du fait que je veux que les enfants d'âge préscolaire puissent l’utiliser). J'ai utilisé OpenCV pour la majeure partie de ce prétraitement d'image et, après un certain nombre d'itérations, j'ai été capable de produire des images au format texte noir et blanc avec un minimum de bruit. C'était essentiel pour que ce projet fonctionne. Les résultats finaux ont été meilleurs que ce à quoi je m'attendais. Cependant, il y a encore matière à amélioration dans ce domaine.

Transformer le texte en audio

Cette étape était la plus facile de tout le projet. Une fois que j’ai pu faire jouer de l'audio sur le périphérique, j'ai pu encapsuler cette logique dans un appel de fonction unique qui appelle simplement AWS Polly pour générer le fichier audio. Je n’écris jamais le fichier sur le disque, j’ai simplement alimenté le flux d’octets dans la bibliothèque audio et je l’ai supprimé une fois la lecture terminée. J'ai quelques fichiers MP3 statiques qui sont lus au démarrage du service Green Grass. J'utilise les fichiers audio pour donner des instructions à l'utilisateur afin qu'il sache comment utiliser le périphérique. J’ai supposé qu'il n'y avait aucune raison d'utiliser Polly pour générer ce discours car il ne change jamais. Je les ai donc générés à l'avance et déployés avec Lambda. (J'adore la facilité d'intégration des services AWS existants dans mes projets !)

Lecture audio via les haut-parleurs

Green Grass exige que vous autorisiez explicitement tout le matériel auquel votre code a également accès. Une façon de configurer cela est via la section Ressources de groupe de la console AWS IOT. Une fois la configuration effectuée, vous déployez ces paramètres sur DeepLens, ce qui effectue le déploiement d’un fichier JSON sur le répertoire Green Grass du périphérique.

Pour activer la lecture audio via votre Lambda, vous devez ajouter deux ressources. La carte son du DeepLens se trouve dans le chemin d’accès « /dev/snd/ ». Vous devez ajouter « /dev/snd/pcmC0D0p » et « /dev/snd/controlC0 » pour pouvoir jouer le son.

De plus, vous devrez rajouter ces ressources chaque fois que vous déployez un projet sur le périphérique. Au moment de la rédaction de cet article, Green Grass remplace le fichier de ressources par un fichier group.json préconfiguré chaque fois que vous déployez un projet sur DeepLens. 

Les réalisations dont je suis fier

J'étais très satisfait des résultats finaux de ce projet. Malgré un emploi à temps plein et quatre enfants, j'ai pu créer quelque chose de génial et le faire fonctionner assez bien en quelques mois à peine. J'ai plus d'idées pour des projets futurs avec ce périphérique et je suis impatient de continuer à apprendre. 

Ce que j'ai appris

Avant de plonger dans ce projet, je n'avais aucune expérience de Deep Learning ou de l'IA en général. Le sujet m'a toujours intéressé, mais il semblait toujours inaccessible aux « développeurs normaux ». Grâce à ce processus, j'ai découvert qu'il est possible de créer de véritables projets de deep learning utiles sans doctorat en mathématiques et qu'avec un effort suffisant et de la patience, quiconque ayant une formation en développement peut commencer à l'utiliser. 

La prochaine étape pour ReadToMe

J'ai quelques idées pour améliorer le projet. Une fonctionnalité que j'aimerais ajouter est la possibilité de traduire le texte lu. (Je me suis inscrit pour un accès préliminaire au nouveau service de traduction d’Amazon mais je n’ai pas encore été approuvé.) Je prévois également continuer à améliorer mon modèle pour voir si je peux augmenter la précision du modèle et le faire fonctionner avec une gamme plus étendue de livres.

Enfin, la fonction de nettoyage des images de texte, directement transmise à Tesseract, peut être améliorée. Spécifiquement, il serait avantageux de pouvoir faire pivoter et déformer l'image avant de l'envoyer à Tesseract. Ainsi, lorsqu'un enfant ne tient pas le livre correctement, le texte pourrait toujours être lu. Le flou causé par le mouvement était également un problème auquel je devais faire face lors du nettoyage des images. Si le livre n’est pas immobile pendant quelques secondes, l’image est trop floue pour que l’OCR fonctionne. J'ai lu diverses techniques pour résoudre ce problème, comme l'utilisation de la moyenne d'image sur plusieurs images ou l'application de différents filtres à l'image pour lisser les pixels. Je suis sûr qu'il est possible d'obtenir un résultat meilleur/plus rapide, mais il est difficile de travailler sur un périphérique aux ressources limitées.

Ressources utiles

De nombreuses ressources en ligne m'ont aidé tout au long du processus, mais ces liens se sont avérés les plus utiles.

(Sans ordre particulier)

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/

Merci également à tous les participants aux forums qui ont répondu aux questions, et plus particulièrement à l’équipe AWS DeepLens, qui m’a aidé plusieurs fois ! :)

Conçu avec

opencv
deeplens
python
polly
tesseract-ocr
lambda
mxnet
tensorflow