Comment nous avons créé un prototype de robot “stalker” en 1 jour

Iman Zarrabian
One More Thing Studio
7 min readDec 18, 2017

--

Mélanger les domaines tel que le Machine Learning, le Computer Vision ou encore la robotique n’a jamais autant été à porté de mains qu’aujourd’hui.

Les constructeurs font des efforts conséquents pour abstraire les difficultés d’implémentation et fournissent des frameworks haut niveau laissant les ingénieurs et les dévelopeurs se concentrer sur la fonctionnalité.

Dans cet article j’explique comment utiliser un iPhone couplé à un micro-controller Arduino Yún pour créer un prototype de robot stalker qui suit du regard et voue à la personne se trouvant devant lui une obsession digne de R2D2.

“Computers can see” annonce Jeremy Howard dans son cours sur le Deep Learning : http://course.fast.ai. Les travaux de computer vision ne datent pas d’hier mais aujourd’hui plus que jamais le machine learning est à la portée de tous et inclure de la détection de visage ou la classification d’objets dans nos programmes est une affaire de minutes.

Pour ce proto nous utilisons le framework Vision qu’Apple a devoilé avec iOS11. Vision repose sur un autre framework de machine learning (Core ML) et permet entre autres de réaliser la détection de visages sur un flux video capté par la camera de l’iPhone. Nous utilisons les API du même framework pour traquer le visage s’il se déplace devant l’objectif.

Vision fournit également les informations quand à la position du visage traqué. Position qui est transmise à un Arduino Yún qui fait pivoter l’iPhone grace à un servomoteur afin que le sujet reste toujours dans le champ de vision du smartphone.

Notons que l’objectif ici est d’initier le lecteur et donner une idée de ce que cela implique d’utiliser ces technos mais qu’on est loin de l’état de l’art en ce qui concerne le tracking de visage ou encore la robotique.

Notre robot en pleine action

La détection et le tracking de visages par l’iPhone

Commençons par l’app native qui s’exécute sur l’iPhone et qui est donc responsable de suivre le visage de la personne se trouvant devant la camera. Fort heureusement Vision simplifie la détection et le tracking pour nous.

Cet article n’étant pas un tuto, je ne rentrerai pas dans le détail du code mais celui ci est disponible ici (le code Arduino également) : https://github.com/OMTS/StalkerRobot

L’utilisation des API de Vision est chose relativement aisée :

  • Création d’une requête (de détection ou de tracking)
  • Démarrage de la tâche (de détection ou de tracking) à chaque fois qu’une nouvelle image est captée depuis la camera.
  • Traitement du retour (de la détection ou du tracking) pour par exemple dessiner un cadre autour du visage, communiquer la position du visage au micro-controlleur mais également fournir l’observation du tracking à la demande de tracking suivante.
Utilisation de Vision dans notre app

Ce que nous appelons observation est le résultat d’une requête de détection ou de tracking. Elle contient notamment les coordonnées de l’objet détecté ou traqué dans l’image.

Le tracking a besoin de deux paramètres en entrée : une image et une observation à traquer, contrairement à la détection qui fonctionne seulement avec une image en entrée, le framework sachant déjà que l’objet à trouver est un visage.

La première fois que nous démarrons notre tache de tracking nous disposons de la seule observation fournie par l‘API de détection (la position du visage pour faire simple). Pour toutes les autres requêtes de tracking en revanche (à chaque fois qu’une nouvelle image est capturée) nous utilisons l’observation fournie par la requête de tracking pour l’image précédente. Le framework réutilise donc le même traqueur pour suivre le visage au lieu de créer un nouveau traqueur à chaque requête.

Création d’une VNDetectFaceRectanglesRequest avec Vision pour détecter les contours d’un visage
Le callback appelé lorsqu’au moins un visage est détecté
Démarrage de la requête de détection de visage ou du traqueur à chaque fois que la camera nous fournit une nouvelle capture

A chaque réception d’une nouvelle observation provenant du traqueur nous faisons deux choses :

  • Le maintient d’une référence sur l’observation en question pour l’injecter à nouveau dans le traqueur pour les frames à venir.
  • Le traitement de l’observation courante : affichage d’un cadre autour du visage sur l’écran et surtout la communication des coordonnées du visage avec l’Arduino Yún pour que le servomoteur puisse tourner le smartphone en conséquence.
Callback appelé à chaque fois que le visage traqué est trouvé sur un frame

La communication entre l’iPhone et l’Arduino Yun

Il est important de comprendre que les coordonnées des observations retournées par Vision sont normalisées. Cela veut dire que la position de visage est compris entre 0 et 1 en x et en y.

Par ailleurs le repère dans lequel Vision fait sa détection est different de celui qui nous sert à l’affichage (notamment à cause de l’orientation des images). Nous effectuons alors une série de transformations permettant de passer d’un repère à l’autre. La méthode drawBox qui dessine un cadre autour du visage à l’écran n’est en revanche pas décrite ici.

La communication avec l’Arduino est un point d’amélioration du proto. Nous remontons les informations de position depuis l’iPhone vers une base de données Firebase et récupérons l’info la plus à jour possible coté Arduino en interrogeant Firebase via l’API REST qu’elle met à disposition. La lecture côté hardware se fait en interrogeant Firebase de manière fréquente pour obtenir l’information la plus à jour possible. On appelle ce procédé le polling.

Un moyen plus naturel est d’utiliser une connexion directe entre l’iPhone et le hardware comme par exemple le Bluetooth mais pour ce proto nous n’avions pas d’extension (Shield) Bluetooth pour l’Arduino. La version Yún du micro-controller embarque cependant une puce wifi. La voie des WebSocket est aussi à explorer.

Notre approche pour la communication est donc pour le moins naïve mais permet de boucler la boucle facilement.

L’envoi de la position en x à notre base de donnée Firebase

Remarquons pour des raisons de performances mais aussi de coût (Firebase devient payant au delà de 20 000 requêtes en écriture par jour) nous n’envoyons pas toutes les valeurs de x trouvées par Vision. En effet seules les variations de plus d’un quart du champs de vision nous interessent. Nous filtrons également les variations trop rapprochées dans l’espace.

Le traitement des positions et la rotation du smartphone par le micro-controlleur

Pour finir notre proto, il nous faut monter un circuit électronique permettant de faire fonctionner un servomoteur qui supportera notre iPhone.

Notre choix s’est porté facilement vers Arduino pour sa simplicité d’utilisation, pour l’excellent kit de démarrage qu’il propose et pour les ressources disponibles partout sur internet pour les apprentis que nous sommes. Le coffret contient tous les composants nécessaires pour ce proto. Nous utilisons en revanche une carte Arduino Yún acheté à part plutôt que sa petite soeur Uno qui elle est fournit dans le coffret. 2 raisons à ce choix :

  • La version Uno ne possède pas de puce wifi ou Bluetooth.
  • Sa connexion en USB est pour le moins chaotique quand on utilise un hub USB coté ordinateur. Ce qui est souvent le cas avec les nouveau macbook pro qui possède uniquement des ports Thunderbolt 3.
Lecture de la donnée depuis l’API REST coté Arduino. Ecrit en C/C++ et compilé avec avr-g++

La récupération de la donnée à jour se fait coté Arduino en utilisant cURL et une librairie externe du nom d’ArduinoJson (qui comme l’ensemble des technos Arduino software et hardware est open source).

La fonction runCurlRequest() décrite plus haut est appelée dans la boucle principale du code qui sera déployé. Cette fonction est donc appelée plusieurs milliers de fois par seconde par la carte.

Si nous avons moins de contraintes coté Firebase pour la lecture (50 000 requetes en lecture par jour) il est tout de même important de limiter le nombre d’appels en mettant un delay à la fin de la boucle. Dans notre cas 250 millisecondes (ce qui réduit le nombre d’appels à 4 par seconde).

La requête HTTP ne récupère pas toute la base de donnée mais seulement le dernier élément inséré. Pour cela nous trions d’abord nos éléments par date (la clef dans la base de données) et nous limitons le nombre d’element retourné au seul dernier.

“https://YOU_FIREBASE_DB_URL/deltas.json?orderBy=\"$key\"&limitToLast=1"

Il ne nous reste plus qu’à traiter cette donnée et à faire pivoter le servomoteur.

Le circuit

La vue schématique du circuit de notre robot stalker

La carte Arduino alimente le servo avec du 5V et le pilote à travers une sortie numérique (1 ou 0) mais qui est capable de fournir un signal analogique grâce à une technique appelée “Pulse Width Modulation” ou PWM. Notez également la présence d’une capa de 100µF pour lisser tout changement de voltage lié au servomoteur.

Le même circuit en photo (avec un petit bug en bonus pour les plus avertis)

Enfin voici le code qui permet de traiter une position reçue depuis la base de donnée distante Firebase et de faire tourner le servomoteur en conséquence.

Le fonction mapf fournit pour les valeurs de normalizedPoisition (variant entre 0.0 et 1.0), un angle compris entre 45 et 135 degrés. L’angle de vision que nous nous somme imposé dans le proto pour faciliter les calculs.

A chaque fois que le visage se déplace sur l’axe X de plus de 0.25 (1/4 de déplacement dans le champs de vision de la camera) l’Arduino récupère ce déplacement et fait tourner l’iPhone pour ramener le sujet le plus proche possible vers le centre de l’écran. Notez que les valeurs min et max de notre angle de rotation sont choisi après expérimentation. Ces valeurs sont à adapter et à améliorer.

Pour finir

Notre approche naïve nous a donc permis de rapidement prototyper un robot capable de voir et de suivre du regard un visage qui passe devant son oeil aguérri. Si beaucoup de choses peuvent être améliorées il est intéressant de voir qu’avec si peu de moyen et de temps on arrive à un résultat assez surprenant.

Voici donc notre robot stalker qui connait déjà son maître.

Notre robot qui reconnaît et suit le portrait de Mark Hamill

Il ne lui manque plus qu’une seule chose pour la décoration :)

source : https://i.pinimg.com/originals/72/51/cc/7251cc7e20e2f8a61cd82648f6d8cffa.jpg

--

--

Iman Zarrabian
One More Thing Studio

CTO and Co-founder at One More Thing Studio. @OMTStudio and @imanzarrabian