ELECINF344/381

Partie interactive du site pédagogique ELECINF344/ELECINF381 de Télécom ParisTech (occurrence 2011).

Catégories

[CASPER] Reconnaissance faciale

Nous avons implémenté la détection et la reconnaissance de visages à l’aide de la bibliothèque OpenCV. Celle-ci utilise l’algorithme de Viola-Jones pour la détection et l’algorithme des eigenfaces dont nous avons déjà parlé dans ce billet pour la reconnaissance.

Nous allons donc ici expliquer uniquement l’algorithme de Viola-Jones.

Algorithme de Viola-Jones

Cet algorithme est un algorithme de boosting, c’est-à-dire qu’il classifie une zone de l’image comme visage ou non-visage à partir de plusieurs classifieurs faibles (c’est-à-dire ayant un taux de bonne classification légèrement meilleur qu’un classifieur aléatoire). Ces classifieurs faibles, inspirés des ondelettes de Haar, consistent à sommer des pixels sur certaines zones (rectangulaires) de l’image et à les soustraire sur d’autres (on trouve ainsi par exemple un classifieur faible dont le but est de détecter des yeux en sommant sur les yeux et en soustrayant entre). Afin de réduire le coût computationnel de ces sommations, Viola & Jones ont introduit les « images intégrales » : celles-ci consistent à recueillir dans chaque pixel la somme des pixels du rectangle qu’il délimite avec le pixel origine. Les classifieurs faibles sont ensuite agrégés à l’aide de l’algorithme AdaBoost.

Afin d’accélérer le traitement, l’algorithme de Viola-Jones utilise plusieurs classifieurs « forts » en cascade, et les agrège par unanimité : dès qu’un classifieur classifie une zone de l’image comme non-visage, le traitement de cette zone s’arrête et celle-ci est classifiée comme non-visage.

Un des problèmes que soulève cette méthode est que les classifieurs faibles (et donc les classifieurs forts) sont définis pour une taille de visage donnée. Or en pratique les visages susceptibles d’apparaître sur une image ont une taille quelconque. Le traitement est donc réalisé de manière pyramidale.

Un deuxième problème est l’agrégation des résultats. En effet, en faisant glisser une fenêtre de détection sur l’image, le même visage est susceptible d’être détecté plusieurs fois, pour des décalages de quelques pixels de la fenêtre. Afin de palier ce problème, l’algorithme regroupe les fenêtres se chevauchant de plus d’une certaine proportion, et en retourne une fenêtre « moyenne ».

Une des principales limitations de cet algorithme est qu’il n’est pas invariant pas rotation, ce qui impliquera de faire un prétraitement pour redresser l’image de la caméra selon la position de notre robot avant de lancer l’algorithme.

Viola-Jones et OpenCV

Plusieurs bases de classifieurs sont fournies par défaut avec OpenCV, notamment pour détecter des visages de face ou de profil. Deux bases détectent les visages de face, les bases « haarcascade_frontalface_default.xml » et « haarcascade_frontalface_alt.xml ». Nous utilisons la deuxième, car la détection est plus rapide (de l’ordre de 50%).

Nous utilisons plusieurs paramétrages fournis par OpenCV, notamment le fait de s’arrêter dès qu’un visage a été détecté, et de commencer par rechercher les visages les plus grands.

Ceci permet d’avoir des temps de détection acceptables (de l’ordre de 50ms sur un PC portable vieux de deux ans à base d’Athlon X2) quand un visage est présent dans l’image, mais beaucoup plus longs si aucun visage n’est présent (de l’ordre de la seconde). Nous pouvons donc envisager d’arrêter la recherche dès que celle-ci dépasse la centaine de millisecondes. Nous attendons cependant le portage sur beagleboard pour évaluer les temps de calcul en conditions réelles. Il existe de plus un projet d’optimisation d’OpenCV utilisant le DSP présent dans l’OMAP de la beagleboard, qu’il sera intéressant de tester.

Algorithme complet

L’algorithme complet de détection et reconnaissance donne des résultats intéressants sur PC portable, la prochaine étape étant de les tester sur beagleboard. Nous rencontrons de même un problème de latence sur OpenCV : l’algorithme se comporte en effet comme s’il existait un buffer de quatre images qui introduit un retard sur les images traitées, le problème étant d’autant plus perceptible en cas d’absence de visage lorsque le traitement de chaque image prend une seconde… Nous n’avons cependant pas encore mené de recherches approfondies sur ce problème.

Détection de visages et reconnaissance faciale

Voici l’état des dernières réflexions sur la partie reconnaissance faciale du projet CASPER.

1) Acquisition du flux vidéo

Une première réflexion s’impose : il est inutile de faire de la reconnaissance faciale à 20fps, un test toutes les secondes est déjà largement suffisant. Le traitement n’a dès lors pas besoin d’une vitesse d’horloge phénoménale (on étudie les algos un peu plus loin), cependant la vitesse d’acquisition est déterminée par la caméra utilisée. On pense donc utiliser un DMA pour transférer le flux vidéo en SRAM. On utiliserait un double buffer : pendant que le DMA transfère une image dans une zone de la RAM, on travaille sur une image stockée dans une seconde zone. On pourrait dès lors utiliser 2 puces de SRAM, ce qui permettait d’avoir un double accès mémoire à moindre coût…

En travaillant à une résolution de 640*480, chaque pixel étant stocké sur 16 bits (5 bits pour rouge et bleu, 6 bits pour vert, comme sur cette caméra), une image prend 5Mbits… On pourrait aussi travailler en 320*240, ce qui ne fait plus que 1.2Mbits par image. Pour réduire la taille, on pourrait prendre directement les images encodées en JPEG (la caméra ci-dessus le propose par exemple), mais le coût de traitement ultérieur sera plus élevé… A étudier…

2) Détection des visages

On partirait sur la technique décrite dans cet article. Elle a l’avantage d’être très simple et beaucoup plus rapide que les méthodes à la Viola-Jones, ce qui permet de l’implanter avec des ressources de calcul réduites.

Le principe : on regarde la couleur de chaque pixel pour le classer en « peau / non peau ». On construit alors deux histogrammes représentant le nombre de pixels « peau », le premier en sommant sur chaque ligne, le second sur chaque colonne. On peut alors segmenter des « blobs » de peau dans l’image. A noter : cette technique peut donner des résultats plus ou moins aléatoires avec plusieurs visages sur la même image. On écarte ce cas pour commencer…

En 320*240 16bits, ça fait de l’ordre de 150000 accès mémoire 8bits pour parcourir l’image : rien d’insurmontable…

3) Reconnaissance faciale

On part sur la technique des « eigenfaces » (basée sur de l’analyse par composantes principales), technique assez ancienne qui a fait ses preuves.

Le principe : à partir d’une base de visages à différencier, on construit une base de vecteurs propres (les « eigenfaces ») de la matrice de covariance, sur laquelle on projette le visage à identifier. A partir des valeurs des composantes, on peut calculer la distance à chaque visage de la base, et reconnaître ainsi l’utilisateur. Un seuil peut permettre de rejeter le visage en cas de trop grande distance. Grâce à des astuces de calcul, la construction des vecteurs propres à partir de N images de M pixels peut se faire sur une matrice N*N, et non M*M, taille de la matrice de covariance initiale (ouf ! ca reste faisable…). A noter : la diagonalisation n’a besoin d’être faite que lors de changements de la base, chose somme toute rare et ponctuelle… De plus, rien n’empêcherait que ce calcul soit fait sur PC (puisque de toute manière on utilisera l’interface de configuration http pour associer les identités à chaque visage enregistré…).

Le gros de la reconnaissance est alors la projection du visage à tester sur la base (produit scalaire sur les M pixels de l’image pour chaque « eigenface »). Heureusement, cette technique ne nécessite pas une résolution très élevée, et peut fonctionner avec des images de 20*20 pixels, ce qui reste très raisonnable… Il faut simplement ajouter le coût du sous-échantillonage pour que tous les visages aient la même résolution…

Reste le stockage de la base d’ « eigenfaces ». En se donnant une limite de 10 visages à différencier, si chaque image fait 20*20 pixels et est codée en niveau de gris 8bits, 32 kbits suffisent…une mémoire de masse quelconque (flash, SDCard,…) partagée avec l’ensemble du système fait tout à fait l’affaire…

4) Mise en oeuvre

Reste la mise en oeuvre du tout, c’est-à-dire principalement le choix du microcontrôleur… Deux choix architecturaux s’opposent : un seul très gros microcontrôleur qui contrôle l’ensemble de CASPER, ou plusieurs microcontrôleurs dédiés chacun à une tâche. Cette deuxième solution a l’avantage d’autoriser à mettre en veille une partie des fonctionnalités s’il ne se passe rien : par exemple, mettre en veille la reconnaissance faciale s’il ne se passe rien, et la réactiver seulement si l’ambiance sonore dépasse un certain seuil (quelqu’un vient de claquer la porte par exemple), d’où une économie d’énergie (pour avoir le même effet avec un « gros » microcontrôleur, il faudrait en plus pouvoir modifier dynamiquement sa fréquence de fonctionnement, ce qui serait susceptible de perturber d’autres tâches (par exemple le traitement du son)). De plus, seuls les résultats intéressants seraient envoyés au contrôleur principal (« chef d’orchestre »), par le biais d’interruptions, ce qui facilite l’écriture du « comportement » de CASPER. En outre, les besoins en multi-tâche seraient beaucoup plus sommaires (inexistants ?).

On partirait donc sur un contrôleur milieu de gamme (référence à déterminer), quelques dizaines de MHz devant suffire pour toute cette partie « reconnaissance faciale ».