21
Reconnaissance faciale Thibault Suzanne, Ralph Maloudi

Reconnaissance facialethibault.suzanne.free.fr/rapport_Suzanne_Maloudi.pdf · 2013. 1. 23. · de reconnaissance faciale à l’aide de l’algorithme eigenfaces, et la réalisation

  • Upload
    others

  • View
    6

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Reconnaissance facialethibault.suzanne.free.fr/rapport_Suzanne_Maloudi.pdf · 2013. 1. 23. · de reconnaissance faciale à l’aide de l’algorithme eigenfaces, et la réalisation

Reconnaissance faciale

Thibault Suzanne, Ralph Maloudi

Page 2: Reconnaissance facialethibault.suzanne.free.fr/rapport_Suzanne_Maloudi.pdf · 2013. 1. 23. · de reconnaissance faciale à l’aide de l’algorithme eigenfaces, et la réalisation

Table des matières

Introduction 3

1 La reconnaissance faciale 41.1 Les faces propres : la théorie . . . . . . . . . . . . . . . . . . . . . 41.2 Les faces propres : l’implantation pratique . . . . . . . . . . . . . 9

2 L’interface graphique 152.1 Fonctionnement général . . . . . . . . . . . . . . . . . . . . . . . 152.2 Implantation python . . . . . . . . . . . . . . . . . . . . . . . . . 16

Conclusion 20

1

Page 3: Reconnaissance facialethibault.suzanne.free.fr/rapport_Suzanne_Maloudi.pdf · 2013. 1. 23. · de reconnaissance faciale à l’aide de l’algorithme eigenfaces, et la réalisation

Table des figures

1.1 Illustration de l’ACP . . . . . . . . . . . . . . . . . . . . . . . . . 51.2 Approximation d’un créneau par des sinusoïdales . . . . . . . . . 51.3 Quelques faces propres . . . . . . . . . . . . . . . . . . . . . . . . 71.4 Illustration de la distance de Mahalanobis . . . . . . . . . . . . . 9

2.1 Capture d’écran du logiciel (Arch Linux, gestionnaire de fenêtreAwesome) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

2

Page 4: Reconnaissance facialethibault.suzanne.free.fr/rapport_Suzanne_Maloudi.pdf · 2013. 1. 23. · de reconnaissance faciale à l’aide de l’algorithme eigenfaces, et la réalisation

Introduction

Ce projet a pour objectif la réalisation d’un logiciel de reconnaissance fa-ciale. Il est découpé en deux parties liées mais distinctes : le codage d’un outilde reconnaissance faciale à l’aide de l’algorithme eigenfaces, et la réalisationd’une interface graphique permettant d’utiliser n’importe quel programme dereconnaissance pourvu qu’il respecte un certain format. En particulier, cetteinterface servira à l’utilisation de notre premier code.

Le programme de reconnaissance faciale sera codé en Python. Il utiliserales bibliothèques OpenCV et Numpy. Son rôle sera d’identifier, parmi une basede visage connu, duquel se rapproche le plus un visage passé en paramètre. Ildevra également indiquer à quel point il s’en rapproche, afin de pouvoir validerou infirmer l’identification. Il utilisera la technique dite des « faces-propres »,qui bien que n’offrant pas les meilleures performances à l’heure actuelle, estrelativement simple à mettre en œuvre et reste efficace.

L’interface graphique sera également réalisée en Python, à l’aide de la pla-teforme PySide, qui est un portage de la librairie Qt pour le langage Python.Elle utilisera également OpenCV pour pouvoir prendre des photos à l’aide dela webcam. Elle devra prendre une photo à l’aide de la webcam et permettrele choix d’un module de reconnaissance parmi ceux qu’elle connait (qui serontdans une liste facilement extensible). Elle devra ensuite appeler ce module afinqu’il reconnaisse ou non le visage en question. Elle affichera dans une fenêtre levisage reconnu par le module, ainsi que diverses informations que ledit moduleaura pu lui donner.

3

Page 5: Reconnaissance facialethibault.suzanne.free.fr/rapport_Suzanne_Maloudi.pdf · 2013. 1. 23. · de reconnaissance faciale à l’aide de l’algorithme eigenfaces, et la réalisation

Chapitre 1

La reconnaissance faciale

La reconnaissance faciale s’inscrit dans le domaine plus vaste de la vision parordinateur, qui part du constat que le sens le plus utilisé par l’homme est la vue.Dès lors, il peut s’avérer très utile de donner des « yeux » à son ordinateur :ainsi, il peut devenir capable de remplacer ceux de l’homme pour des tâchesrépétitives telles que la reconnaissance de nombreux visages, ou demandantdes calculs conséquents comme le lissage d’une image ou l’augmentation de sanetteté.

Le principe de la reconnaissance faciale est très simple : comme son noml’indique, il s’agit d’identifier une face donnée. Selon les algorithmes et les butsrecherchés, cette identification peut prendre plusieurs aspects : il peut s’agir dedéterminer à qui appartient un visage, de décider si oui ou non ce visage estreconnu, ou même dans certains cas de déterminer s’il s’agit bien d’un visage.

1.1 Les faces propres : la théorieNous cherchons à effectuer de la reconnaissance faciale, en employant des

systèmes simples comme une webcam. Le sujet se plaçant alors face à la ca-méra, nous partons donc de la remarque, qui nous simplifie grandement notredémarche, selon laquelle nous pratiquons de la reconnaissance à deux dimen-sions.

La méthode de reconnaissance faciale Eigenfaces emploie la technique del’analyse en composante principale, qui marque une différence notable avec lesméthodes plus classiques, appelées méthodes géométriques ou locales, qui sebasent sur les particularités du visage analysé, et dont les défauts résident dansson manque de précision, ainsi que sa sensibilité aux informations qui ne sontpas pertinentes.La méthode que nous avons utilisé est qualifiée de globale, puisque l’ensembledu visage est alors analysé.

Notre technique de reconnaissance va donc utiliser la méthode d’analyse encomposantes principales (également dite ACP).De manière simple, nous visonsla diminution de la dimension de l’espace dans lequel nous allons travailler, etnous pourrons alors simplifier les données à notre disposition et leur interpréta-tion.

4

Page 6: Reconnaissance facialethibault.suzanne.free.fr/rapport_Suzanne_Maloudi.pdf · 2013. 1. 23. · de reconnaissance faciale à l’aide de l’algorithme eigenfaces, et la réalisation

Ainsi nous pourrons prendre en compte les informations importantes qui nouspermettrons de reconnaître un visage parmi d’autres avec un bon taux de réus-site.(Figure 1.1)

Figure 1.1 – Illustration de l’ACP

Faisons un simple parallèle entre ma méthode des faces propres et les sériesde Fourier. Les séries de Fourier nous permettent généralement de représenterun signal périodique à l’aide de sommes de cosinus et de sinus.(Figure 1.2)

Figure 1.2 – Approximation d’un créneau par des sinusoïdales

Dans le cas de notre projet, notre approche consiste à représenter un vi-sage comme étant la combinaison linéaire d’un ensemble d’images, ces dernièresformant une base de référence. Mathématiquement, cela revient à parvenir àl’équation :

Φi =

n∑i=1

pidi

où di représente le visage propre, et pi le coefficient associé.

Nous allons chercher à trouver les visages propres ; tout d’abord, nous de-vons prendre un nombre M de visages d’apprentissage. Chacune de ces images,qui sont en pratique des matrices N ×N sont alors transformées en un uniquevecteur colonne de longueur N2.

Matrice N ×N initiale :α11 α12 α1i α1N

α21 α22 α2i α2N

... ... ... ...αN1 αN2 αNi αNN

5

Page 7: Reconnaissance facialethibault.suzanne.free.fr/rapport_Suzanne_Maloudi.pdf · 2013. 1. 23. · de reconnaissance faciale à l’aide de l’algorithme eigenfaces, et la réalisation

transformée en :

α11

...αN1

...α1N

...αNN

Nous devons par la suite déterminer le visage moyen, déduit des M visages

d’apprentissages.

Ψ =1

M

M∑i=1

Γi

Ce visage moyen va servir dans l’analyse d’images, on soustrait en effet ce vi-sage moyen aux visages d’apprentissages, ce qui nous laisse alors les informationspropres à ce visage, nous récupérons alors dans Φi uniquement les informationsqui sont particulières à ce visage d’apprentissage.

Φi = Γi −Ψ

Où Φi représente le ieme visage auquel on a soustrait le visage moyen.

A présent nous devons calculer la matrice de covariance D. Elle correspond à

D = QQT ,

avecQ = [Φ1,Φ2, .....,ΦM ]

Nous devrions calculer les vecteurs propres di de la matrice D. Mais celareprésente pour nous N2 vecteurs propres de dimension N2 chacun.

C’est à présent que nous allons réduire l’information en limitant les compo-santes avec lesquelles nous travaillerons, en accord avec le principe de l’analyseen composantes principales. Nous allons donc considérer la matrice E = QTQ,dont nous trouverons les vecteurs propres ei.

Cette matrice est de taille M ×M ce qui nous simplifiera donc les chosesétant donné que nous aurons M vecteurs propres de taille M chacun.

Le passage de la matrice D à la matrice E n’est pas anodin, nous utilisonsen effet le fait que les vecteurs propres de ces deux matrices sont liés de manièreassez proche.

En effet, nous avons comme relation,

Eei = QTQei = λiei

avec λi la valeur propre associée au vecteur propre ei.

6

Page 8: Reconnaissance facialethibault.suzanne.free.fr/rapport_Suzanne_Maloudi.pdf · 2013. 1. 23. · de reconnaissance faciale à l’aide de l’algorithme eigenfaces, et la réalisation

En multipliant cette équation par la matrice Q, il vient

QEei = QQTQei

Nous voyons alors apparaître la matrice D

QEei = DQei = λiQei

Nous en déduisons donc qu’avec ei vecteur propre de la matrice E associé àla valeur propre λi, nous avons par conséquent Qei est un vecteur propre de lamatrice D associé à la même valeur propre λi.

Ainsi, nous avons di vecteur propre de D, avec

di = Qei

Ce sont les valeurs propres qui leur sont associées qui nous permet ensuitede classer les vecteurs propres en fonction de leur capacité à caractériser lesvariations entre les images.

Lorsque l’on les visualise (ces vecteurs sont à l’origine des matrices de tailleN ×N), les faces propres sont ce que l’on pourrait appeler des images aux airsfantomatiques. Mais gardons à l’esprit que sont les vecteurs propres de la ma-trice de covariance des images d’apprentissage des visages. (Figure 1.3)

Figure 1.3 – Quelques faces propres

Les Mvecteurs propres que nous avons alors obtenus nous permettrons doncd’approximer au mieux les visages d’apprentissage en utilisant les visages propresde plus grande importance.

L’avantage de réduire le nombre de visages propres est d’une part de néces-siter de moins d’espace mémoire, mais aussi de réduire les calculs, leur tempsd’exécution ; cependant nous perdons sans aucun doute de l’information et doncl’information moins précise, mais les résultats ne s’en verront pas vraiment mo-difiés, étant donné que nous ne nous donnons qu’une mission d’identification.Nous ne cherchons pas à reconstruire le visage du sujet à partir de nos visagespropres, mais seulement à le reconnaître.

Parmi les M vecteurs propres trouvés, nous allons seulement conserver unnombre L, qui seront les plus significatifs.

Nous allons trouver maintenant le poids associé à chacun des visages propres.Les images servant à l’apprentissage, auquel on a enlevé l’image moyenne, sonten fait combinaison linéaire des visages propres.

7

Page 9: Reconnaissance facialethibault.suzanne.free.fr/rapport_Suzanne_Maloudi.pdf · 2013. 1. 23. · de reconnaissance faciale à l’aide de l’algorithme eigenfaces, et la réalisation

Φi =

L∑i=1

pidi

Pour trouver le poids associé, nous faisons pour chacune des coordonnéescorrespondant à un visage d’apprentissage

pi = dTi Φi

Ce qui nous permet d’obtenir pour chacun des M visages d’apprentissagesun vecteur Πi, où i représente le ieme visage, et qui nous informe sur le coeffi-cientage appliqué à chacun des visages propres.

Πi =

p1p2...pL

Passons à présent au travail à effectuer pour la reconnaissance d’un visaged’un sujet.Une fois l’image prise, l’image (vecteur colonne Γ) obtenue est soustraite àl’image moyenne Ψ :

Φ = Γ−Ψ

Puis nous trouvons les coordonnées de cette image dans l’espace réduit desfaces propres

pi = dTi Φi

Ce qui nous donne au final :

Π =

p1p2...pL

Il nous faut maintenant interpréter la projection de l’image à analyser pour

identifier le sujet. Pour cela nous allons utiliser une mesure de distance parti-culière, la distance de Mahalanobis. L’intérêt de cette distance réside dans lefait qu’elle va accorder un poids moins important aux composantes bruitées,et qu’elle permet séparer efficacement les axes pour lesquels l’information peutêtre mieux classifiée. (Figure 1.4)

8

Page 10: Reconnaissance facialethibault.suzanne.free.fr/rapport_Suzanne_Maloudi.pdf · 2013. 1. 23. · de reconnaissance faciale à l’aide de l’algorithme eigenfaces, et la réalisation

Figure 1.4 – Illustration de la distance de Mahalanobis

Elle est définie par :

d(a, b) =√

(a− b)TQ−1(a− b)

avec Q covariance des variables.

Nous cherchons donc :

m = min ‖Π−Πi‖

Puis, nous comparons la valeur de m trouvée à une valeur seuil ∆, qui auraitdu être déterminée à partir d’essais sur des images choisies aléatoirement, quipeuvent aussi bien représenter des visages qu’autres choses, puis en comparantces valeurs aux valeurs obtenues avec des visages d’apprentissage, et décider duseuil que nous avons choisi. Mais le choix de ce seuil dépend de trop nombreusesconditions ( prise de vue des images, niveau de précision souhaité pour la re-connaissance, etc..) c’est pour cela qu’en pratique nous avons décidé de ne pasprendre de seuil.

L’utilisation d’un seuil nous aurait permis de déterminer si oui ou non l’imageanalysée correspond à un visage présent dans la base de données. Si alors lavaleur de m était inférieure à celle du seuil, l’image correspond au visage qui adonné cette valeur la plus basse.Dans notre cas, le fait de ne pas choisir de seuil à eu pour conséquence quelorsqu’un visage non présent dans la base de donnée était testé, il était tout demême reconnu par le programme.

1.2 Les faces propres : l’implantation pratiqueVoici donc le code de l’implantation en Python, commenté :

1 #!/usr/bin/env python22 # -*- coding: utf -8 -*-34 import cv5 import math6 import numbers

9

Page 11: Reconnaissance facialethibault.suzanne.free.fr/rapport_Suzanne_Maloudi.pdf · 2013. 1. 23. · de reconnaissance faciale à l’aide de l’algorithme eigenfaces, et la réalisation

7 import numpy as np8 import os9 import sys10 import time111213 def list_de_iplimage(image):14 "Renvoie␣la␣forme␣liste␣d’une␣image␣OpenCV"15 return [[cv.Get2D(image , i, j)[0] for j in xrange(image.width )]16 for i in xrange(image.height )]171819 class Tableau:20 def __add__(self , autre):21 "Additionne␣avec␣un␣Tableau␣ou␣un␣scalaire"22 if isinstance(autre , Tableau ):23 return Tableau(self.tab + autre.tab)24 elif isinstance(autre , numbers.Number ):25 return Tableau(self.tab + autre)26 else:27 raise TypeError("Tableau.__add__␣:␣Tableau␣ou␣scalaire␣attendu")2829 def __div__(self , autre):30 "Divise␣par␣un␣scalaire"31 return Tableau(self.tab / autre)3233 def __getitem__(self , index ):34 "Renvoie␣un␣coefficient␣du␣Tableau ,␣pour␣pouvoir␣utiliser␣tableau[index]"35 if isinstance(index , int) and self.largeur != 1:36 return Tableau(self.tab[index ])37 else:38 return self.tab[index]3940 def __init__(self , source , nom=str(time.time ())):41 """ Constructeur d’un objet Tableau42 On peut lui passer:43 * une c h a n e de c a r a c t r e , qui sera le chemin de l’image charger en Tableau44 * une image au format OpenCV passer en Tableau45 * un array numpy passer en Tableau46 """47 if isinstance(source , str):48 self.tab = np.array(list_de_iplimage(cv.LoadImage(source , cv.CV_LOAD_IMAGE_GRAYSCALE )))49 elif isinstance(source , cv.iplimage ):50 self.tab = nb.array(list_de_iplimage(source ))51 elif isinstance(source , (np.ndarray , list )):52 self.tab = np.array(source)53 else:54 raise TypeError("Tableau.__init__␣:␣%s␣inattendu" % type(source ))55 self.nom = nom56 self.calc_dimensions ()

10

Page 12: Reconnaissance facialethibault.suzanne.free.fr/rapport_Suzanne_Maloudi.pdf · 2013. 1. 23. · de reconnaissance faciale à l’aide de l’algorithme eigenfaces, et la réalisation

5758 def __len__(self):59 "Pour␣pouvoir␣utiliser␣len(tableau)␣au␣cas␣ o "60 return len(self.tab)6162 def __mul__(self , autre , element_par_element=False ):63 """ Multiplie : multiplication de matrice , ou par un scalaire64 Le flag element_par_element indique , s’il est vrai , qu’on n’utilise pas65 la multiplication de l’ a l g b r e des matrices , mais une multiplication66 lment par lment de deux matrices de m m e s dimensions """67 if isinstance(autre , Tableau ):68 if element_par_element:69 return Tableau(self.tab * autre.tab)70 else:71 resultat = np.dot(self.tab , autre.tab)72 if isinstance(resultat , numbers.Number ):73 return resultat74 else:75 return Tableau(resultat)76 elif isinstance(autre , numbers.Number ):77 return Tableau(self * autre)78 else:79 raise TypeError("Tableau.__mul__␣:␣Tableau␣ou␣scalaire␣attendu")808182 def __setitem__(self , index , valeur ):83 """ Modifie un coefficient du Tableau :84 i m p l m e n t e tableau[index] = valeur """85 self.tab[index] = valeur8687 def __sub__(self , autre):88 "Additionne␣avec␣un␣Tableau␣ou␣un␣scalaire"89 if isinstance(autre , Tableau ):90 return Tableau(self.tab - autre.tab)91 elif isinstance(autre , numbers.Number ):92 return Tableau(self.tab - autre)93 else:94 raise TypeError("Tableau.__sub__␣:␣Tableau␣ou␣scalaire␣attendu")959697 def afficher(self , nom=None):98 """ Affiche le Tableau , comme une image , dans une f e n t r e99 Utilise OpenCV pour cela """100 if nom is None:101 nom = self.nom102 cv.ShowImage(nom , self.vers_iplimage ())103104105 def calc_dimensions(self):106 "Calcule␣les␣dimensions␣du␣Tableau"

11

Page 13: Reconnaissance facialethibault.suzanne.free.fr/rapport_Suzanne_Maloudi.pdf · 2013. 1. 23. · de reconnaissance faciale à l’aide de l’algorithme eigenfaces, et la réalisation

107 self.hauteur = len(self.tab)108 try:109 self.largeur = len(self.tab [0])110 except TypeError:111 self.largeur = 1112113 def calc_elements_propres(self):114 "Calcule␣valeurs␣propres␣et␣vecteurs␣propres␣du␣tableau"115 valeurs , vecteurs = np.linalg.eig(self.tab)116 self.val_propres = list(valeurs)117 self.vect_propres = [Tableau(vect) for vect in vecteurs]118119 def covariance(self):120 "Renvoie␣le␣Tableau␣de␣covariance␣du␣Tableau"121 return self * self.transposee ()122123 def dimensions(self):124 "Renvoie␣les␣dimensions␣-␣hauteur␣*␣largeur␣-␣du␣tableau"125 return self.hauteur , self.largeur126127 def en_colonne(self):128 "Renvoie␣le␣Tableau␣comme␣un␣vecteur␣colonne"129 return self.redimensionnee (-1)130131 def inverse(self):132 "Renvoie␣l’inverse␣du␣Tableau␣dans␣l’ a g b r e ␣des␣matrices"133 return Tableau(np.linalg.inv(self.tab))134135 def mahalanobis(self , autre , cov):136 "Calcule␣la␣distance␣de␣Mahalanobis␣entre␣deux␣Tableaux"137 a = (self - autre) * cov.inverse () * (self - autre)138 return math.sqrt(a)139140 def mettre_en_colonne(self):141 "Met␣le␣Tableau␣en␣forme␣de␣vecteur␣colonne"142 self.redimensionner (-1)143144 def redimensionnee(self , nouvelle_forme ):145 """ Renvoie le Tableau sous une nouvelle forme146 Le nombre total d’ lments doit rester le m m e """147 tab = Tableau(np.reshape(self.tab , nouvelle_forme ))148 tab.calc_dimensions ()149 return tab150151 def redimensionner(self , nouvelle_forme ):152 """ Change la forme du Tableau153 Le nombre total d’ lments reste le m m e """154 self.tab = np.reshape(self.tab , nouvelle_forme)155 self.calc_dimensions ()156

12

Page 14: Reconnaissance facialethibault.suzanne.free.fr/rapport_Suzanne_Maloudi.pdf · 2013. 1. 23. · de reconnaissance faciale à l’aide de l’algorithme eigenfaces, et la réalisation

157158 def transposee(self):159 "Renvoie␣la␣ t r a n s p o s e ␣du␣Tableau"160 return Tableau(np.transpose(self.tab))161162 def transposer(self):163 "Transpose␣le␣Tableau"164 self.tab = np.transpose(self.tab)165166 def vers_iplimage(self , profondeur=cv.IPL_DEPTH_8U ):167 "Renvoie␣l’iplimage␣ quivalente ␣(format␣OpenCV)"168 temp = cv.CreateImage ((self.largeur , self.hauteur),169 cv.IPL_DEPTH_64F , 1)170 for (i, ligne) in enumerate(self.tab):171 for (j, valeur) in enumerate(ligne):172 cv.Set2D(temp , i, j, valeur)173 img = cv.CreateImage ((self.largeur , self.hauteur), profondeur , 1)174 cv.Convert(temp , img)175 return img176177178179180 class Collection:181 def __init__(self , chemin="faces/"):182 "Constructeur␣d’un␣objet␣Collection"183 self.liste_faces = [Tableau(chemin + fichier)184 for fichier in os.listdir(chemin )]185 self.nb_faces = len(self.liste_faces)186 # On p r p a r e la Collection pour la reconnaissance"187 self.calc_moyenne ()188 self.calc_ecarts ()189 self.calc_covariance ()190 self.calc_faces_propres ()191 self.calc_coeff_faces ()192193 def calc_covariance(self):194 "Calcule␣la␣covariance␣des␣faces␣ n o r m a l i s e s ␣de␣la␣Collection"195 self.covariance = self.ecarts.transposee (). covariance ()196197 def calc_moyenne(self):198 "Calcule␣la␣moyenne␣des␣faces␣de␣la␣Collection"199 self.moyenne = reduce(Tableau.__add__ , self.liste_faces) / self.nb_faces200201202 def calc_coeff_faces(self):203 """ Calcule les coefficients des faces de la collection ,204 dans la base des faces propres """205 self.coeff_faces = Tableau ([self.coeff(face)206 for face in self.ecarts.transposee ()])

13

Page 15: Reconnaissance facialethibault.suzanne.free.fr/rapport_Suzanne_Maloudi.pdf · 2013. 1. 23. · de reconnaissance faciale à l’aide de l’algorithme eigenfaces, et la réalisation

207 self.covar_coeff = self.coeff_faces.transposee (). covariance ()208209 def calc_ecarts(self):210 "Calcule␣le␣Tableau␣des␣ carts ␣ ␣la␣moyenne"211 self.ecarts = Tableau ([( face - self.moyenne ). en_colonne (). tab212 for face in self.liste_faces ]). transposee ()213214 def calc_faces_propres(self):215 "Calcule␣les␣faces␣propres␣de␣la␣collection"216 self.covariance.calc_elements_propres ()217 self.faces_propres = [self.ecarts * vect218 for vect in self.covariance.vect_propres]219 #Pour un affichage , redimensionner en (100, 80)220221 def coeff(self , tableau ):222 "Renvoie␣les␣coefficients␣d’un␣tableau␣sur␣la␣base␣des␣faces␣propres"223 return [face * tableau.en_colonne () for face in self.faces_propres]224225226 def reconnaitre(self , image ):227 """ Reconnait ou non une image.228 Sauvegarde la face connue la plus proche dans le fichier resultat.bmp ,229 et renvoie la distance entre le visage r e c o n n a t r e et cette face """230 coeff = Tableau(self.coeff(image - self.moyenne ))231 distances = [coeff.mahalanobis(coeff_face , self.covar_coeff)232 for coeff_face in self.coeff_faces]233 distance_min = min(distances)234 i = distances.index(distance_min)235 cv.SaveImage("resultat.bmp", self.liste_faces[i]. vers_iplimage ())236 return distance_min237238 if __name__ == "__main__":239 collection = Collection ()240 # On passe en argument le visage r e c o n n a t r e241 visage = Tableau(sys.argv [1])242 # On utilise la m t h o d e reconnaissance et on affiche le r s u l t a t en sortie standard243 # L’interface s’occupe du reste244 print collection.reconnaitre(visage)

14

Page 16: Reconnaissance facialethibault.suzanne.free.fr/rapport_Suzanne_Maloudi.pdf · 2013. 1. 23. · de reconnaissance faciale à l’aide de l’algorithme eigenfaces, et la réalisation

Chapitre 2

L’interface graphique

Une fois le moteur réalisé, il nous faut trouver un moyen pratique pourl’utilisateur afin de s’en servir. Si la ligne de commande peut s’avérer très utileet pratique, elle est a priori moins accessible pour quelqu’un qui ne connait pasbien le fonctionnement du programme.

Nous avons donc cherché à réaliser une interface graphique. En plus de four-nir un moyen commode d’utiliser le moteur codé précédemment, elle sera utili-sable avec n’importe quel moteur de reconnaissance faciale utilisant un formatcommun. Ainsi, elle permettra de tester un algorithme de reconnaissance defaçon ergonomique en quelques clics, sans que le programme l’implémentantn’ait besoin d’effectuer les manipulations communes de lecture à la webcam etd’affichage du résultat.

Elle permettra également de choisir quel moteur utiliser, et il sera possibled’en ajouter de nouveaux à l’aide d’un fichier de configuration simple (qui auraitdu être également généré par une interface graphique, ce que nous n’avons paspu faire en raison d’un manque de temps).

2.1 Fonctionnement généralAfin de pouvoir utiliser le module de reconnaissance voulu, le logiciel doit

respecter une certaine architecture. L’interface graphique doit être correctementséparée du moteur, et ils doivent respecter un certain format de communication.Ainsi, on pourra utiliser n’importe quel moteur respectant ce format avec notreinterface.

De plus, notre logiciel doit pouvoir proposer plusieurs modules, et on doitpouvoir en rajouter dans le temps. Ils ne seront donc pas implantés en durmais il les chargera dynamiquement à partir d’une liste facilement modifiable etextensible.

Le format choisi pour l’appel des modules est relativement simple tout enrestant flexible. Ils doivent être appelables à l’aide d’un appel système, qui doitaccepter parmi ses arguments le chemin d’une image qui contient le visage à re-connaître. Cet argument peut être placé n’importe où dans la ligne de commandeà lancer. Il devra lire cette image, et écrire une autre image, qui devra contenirle visage de la personne a priori reconnue. Elle pourra également afficher un

15

Page 17: Reconnaissance facialethibault.suzanne.free.fr/rapport_Suzanne_Maloudi.pdf · 2013. 1. 23. · de reconnaissance faciale à l’aide de l’algorithme eigenfaces, et la réalisation

texte sur la sortie standard, qui contiendra des informations supplémentaires,comme par exemple le degré de confiance, le nom de la personne...

Ces modules seront listés dans un fichier au format JSON, qui contiendraleur nom, la commande à lancer pour les exécuter (formatée avec le nom del’image à lire) et une description du module. L’interface graphique commencerapar afficher une image correspondant à la capture de la webcam. Une touchepermettra de prendre la photo. Ensuite, une fenêtre sera affichée avec diverscomposants. Une liste déroulante permettra de sélectionner le module souhaité,et un bouton permettra de rafraîchir cette liste si on a modifié le fichier JSONdepuis le début de l’affichage. La description du module sera également affichéeen dessous. Enfin, il y aura un bouton permettant d’appeler le module choisipour effectuer la reconnaissance.

Il était normalement prévu d’avoir la capture webcam affichée en mêmetemps que la fenêtre principale, mais nous n’avons pas réussi à comprendrecomment afficher cette capture dans PySide. Nous deviosn également fournirune interface pour ajouter simplement des modules sans éditer à la main lefichier json, mais nous n’avons pas eu le temps de réaliser ces fonctions.

2.2 Implantation pythonCette interface graphique utilise la librairie PySide, un portage de Qt pour

le langage Python. En PySide, chaque élément graphique est un objet dont laclasse hérite de QWidget (un WInDow gadGET). Il existe de nombreux widgetsprédéfinis. Pour personnaliser son widget, on crée une classe héritant de la classecorrespondante. Par exemple, nous voulons que le pointeur de la souris deviennela « main » lorsqu’il passe au dessus d’un bouton cliquable. Nous allons doncredéfinir notre propre classe de boutons cliquables :

1 class Bouton(QPushButton ):2 """ Classe utilisee pour changer le pointeur3 quand on passe la souris sur un bouton """4 def __init__(self , texte , parent=None):5 super(Bouton , self). __init__(texte , parent)6 self.setCursor(Qt.PointingHandCursor)

Ici, on ne change qu’un comportement défini une seule fois à l’initialisation dubouton. On ne doit donc réécrire que le constructeur. On appelle le constructeurparent, et on rajoute dans ce constructeur le paramétrage souhaité du pointeur.Ainsi, chaque bouton que l’on créera en utilisant cette classe Bouton profiterade ce réglage.

La classe Fenêtre, elle, dispose de plus de réglages. On y spécifiera en parti-culier les différents widgets qu’elle contient, disposés à l’aide d’un QGridLayout,qui permet de donner leurs positions (dans des coordonnées entières) dans unegrille qui couvre la fenêtre.

Afin de gérer les évènements, on utilise le mécanisme de signaux et de slotsde Qt. Un évènement (par exemple, le clic sur un bouton) correspond à un« signal », que l’on connecte ) un « slot », c’est à dire à une fonction qui seraexécutée lors de son déclenchement. Les signaux sont ici des méthodes de laclasse Fenetre.

16

Page 18: Reconnaissance facialethibault.suzanne.free.fr/rapport_Suzanne_Maloudi.pdf · 2013. 1. 23. · de reconnaissance faciale à l’aide de l’algorithme eigenfaces, et la réalisation

Le code final de l’interface graphique est donc le suivant, suivi par une cap-ture d’écran :

1 #!/usr/bin/env python22 # -*- coding: utf -8 -*-34 import cv5 import json6 import os7 import sys8 from PySide.QtCore import *9 from PySide.QtGui import *1011 class Bouton(QPushButton ):12 """ Classe u t i l i s e pour changer le pointeur13 quand on passe la souris sur un bouton """14 def __init__(self , texte , parent=None):15 super(Bouton , self). __init__(texte , parent)16 self.setCursor(Qt.PointingHandCursor)1718 class Fenetre(QWidget ):19 def __init__(self , parent=None):20 super(Fenetre , self). __init__(parent)2122 # C r a t i o n des lments23 self.setWindowTitle("Thira")24 self.liste_modules = QComboBox () # liste d r o u l a n t e25 self.recharger_modules = Bouton("Recharger␣les␣modules")26 self.description = QLabel ()27 self.action = Bouton("Action␣!")2829 # Placement des lments30 layout = QGridLayout ()31 layout.addWidget(self.liste_modules , 0, 0)32 layout.addWidget(self.recharger_modules , 0, 1)33 layout.addWidget(self.description , 1, 0, 1, 2)34 layout.addWidget(self.action , 2, 0, 1, 2)35 self.setLayout(layout)3637 # C r a t i o n des slots38 self.liste_modules.currentIndexChanged.connect(self.changer_module)39 self.recharger_modules.clicked.connect(self.charger_modules)40 self.action.clicked.connect(self.reconnaitre)4142 # Autoriser le passage la ligne dans la description43 # Sinon elle est en une ligne et on ne peut pas r d u i r e la taille44 self.description.setWordWrap(True)4546 # On charge les modules disponibles la c r a t i o n de la f e n t r e47 self.charger_modules ()

17

Page 19: Reconnaissance facialethibault.suzanne.free.fr/rapport_Suzanne_Maloudi.pdf · 2013. 1. 23. · de reconnaissance faciale à l’aide de l’algorithme eigenfaces, et la réalisation

4849 def reconnaitre(self):50 " U t i l i s e ␣lorsqu ’on␣demande␣ ␣ r e c o n n a t r e ␣le␣visage␣pris␣en␣photo"51 commande = self.modules[self.liste_modules.currentIndex ()]["commande"]52 # La commande est sous la forme :53 # nom_du_programme_a_executer {0}54 # on a "c{0}d". format ("bla") == "cblad"5556 # Le moteur r p o n d sur la sortie standard57 # Actuellement on se contente de le laisser l’afficher ,58 # on pourrait le rediriger vers une variable pour l’exploiter59 # par exemple en l’affichant dans une f e n t r e60 os.system(commande.format("visage.bmp"))616263 def changer_module(self , texte ):64 """ Lorsqu ’on change de module l’aide de la liste d r oul an te ,65 on actualise l’affichage de la description """66 self.description.setText(67 self.modules[self.liste_modules.currentIndex ()]["description"])6869 def charger_modules(self):70 """ Pour recharger la liste des modules si on a m o d i f i le fichier71 modules.js qui contient leur description sous format json """72 self.liste_modules.clear ()73 self.modules = json.loads(open("modules.js").read ())74 for module in self.modules:75 self.liste_modules.addItem(module["nom"])7677 if __name__ == "__main__":78 # Ce code ne s’ e x c u t e que si on e x c u t e directement le module (pas en cas d’import)79 webcam = cv.CaptureFromCAM (0)80 print "Appuyez␣sur␣S␣pour␣prendre␣la␣photo"81 while True:82 image = cv.GetSubRect(cv.QueryFrame(webcam), (281, 191, 80, 100))83 cv.ShowImage("webcam", image)84 key = cv.WaitKey (1)85 # La touche pour prendre la photo est la touche s86 # Sous le linux u t i l i s pour tester , la valeur correspondante87 # tait 1048691.88 # Sous Windows , la valeur tait ord("s"), soit 115.89 # Sous certaines machine , cette valeur peut tre "s".90 if key in [1048691 , ord("s"), "s"]:91 cv.SaveImage("visage.bmp", image)92 break93 # thira = THIbault RAlph94 # sys.argv = les arguments de la commande e x c u t e ,95 # par exemple [" interface.py", "-o3", "visage.bmp"]96 # Inutile pour nous mais d e m a n d dans le constructeur de QApplication97 thira = QApplication(sys.argv)

18

Page 20: Reconnaissance facialethibault.suzanne.free.fr/rapport_Suzanne_Maloudi.pdf · 2013. 1. 23. · de reconnaissance faciale à l’aide de l’algorithme eigenfaces, et la réalisation

98 fenetre = Fenetre ()99 fenetre.show()100 sys.exit(thira.exec_ ())

Figure 2.1 – Capture d’écran du logiciel (Arch Linux, gestionnaire de fenêtreAwesome)

19

Page 21: Reconnaissance facialethibault.suzanne.free.fr/rapport_Suzanne_Maloudi.pdf · 2013. 1. 23. · de reconnaissance faciale à l’aide de l’algorithme eigenfaces, et la réalisation

Conclusion

Ce projet nous a permis de découvrir plus profondément plusieurs aspectsdu développement d’un logiciel complexe. Il nous a fallu d’abord nous renseignersur le côté algorithmique de la reconnaissance de visage, et plus généralement dela vision par ordinateur, qui est un domaine en pleine expansion. Cette recherchenous a donc mené à la réalisation d’un moteur de reconnaissance faciale « brut ».Il nous a fallu résoudre plusieurs problèmes algorithmiques ayant plus ou moinsde rapport avec les mathématiques, discipline importante dans le traitementd’images en général.

Ensuite, nous avons du concevoir une interface graphique. Il nous a fallu pourcela comprendre les mécanismes de fonctionnement de ces outils particuliers,qui ne suivent pas une structure impérative linéaire mais plutôt un modèledéclaratif, où la bibliothèque utilisée se charge de tout gérer une fois qu’on adécrit le comportement attendu. Dans la continuité du cours de Génie Logicielet dans une démarche d’ingénieur, nous avons également du organiser notrelogiciel final de façon à le rendre modulaire et extensible par la suite.

Ainsi, la réalisation de ce projet nous a permis de comprendre plus en profon-deur le développement d’un logiciel, de la conception à la réalisation en passantpar la réflexion logique et algorithmique. Si nous avions plus de temps, nousaurions aimé développer un peu plus l’interface graphique afin de compléter sonrôle (il ne se serait toutefois agit principalement que de réutiliser des conceptsdéjà présents dans notre code final). Il aurait été également intéressant d’affinerle moteur de reconnaissance, en trouvant un moyen de prendre des images cor-rectement cadrées et en déterminant les seuils de façon rigoureuse. Si d’autresprojets se font sur ce thème, il serait sans doute intéressant de leur fournirl’interface graphique afin de tester une utilisation par des utilisateurs externes.

20