CHAPITRE TROISIEME :
MISE EN PLACE D'UNE APPLICATION D'IDENTIFICATION DE PERSONNES PAR
RECONNAISSANCE DE VISAGE POUR LA SECURITE D'UNE INSTITUTION BANCAIRE
3.1 ENVIRONNEMENT
UTILISE
Notre sujet de recherche nous a permis d'aboutir à la
conception d'une application permettant d'assurer la sécurité
d'une institution bancaire.
Notre application tourne sous un ordinateur ayant les
caractéristiques suivantes :
a. Environnement matériel ou le hardware
· Toshiba satellite C660
· Capacité du disque dur : 500 gigaoctet
· Modèle du processeur : Intel Celeron
· Vitesse du processeur : 2,30 gigahertz
· Mémoire RAM : 2 gigaoctet
b. Environnement immatérielle ou le
software
· Système d'exploitation : Linux dans sa
distribution Ubuntu 10.10
· Version d'OpenCV : 2.3.1
· Version cmake : 2.8.2
· Version ffmpeg : 0.6-4 :0.6-2ubuntu6.3
Ceci étant l'environnement sous lequel a tourné
notre application, il est à signaler qu'elle peut aussi tourner sur
d'autres ordinateurs à technologie moderne.
3.2 PROGRAMMATION
Nous avons commencé par importer les
bibliothèques suivantes que nous allons préciser leur utilisation
au fur et à mesure que nous avançons dans notre programmation.
Voici les bibliothèques utilisées :· <cv.h>
· <highgui.h>
· <cvaux.h>
· <stdio.h>
· <stdlib.h>
· <string.h>
· <assert.h>
· <math.h>
· <float.h>
· <limits.h>
· <time.h>
· <ctype.h>· Détection de
visage
Pour que l'application parvienne à détecter le
visage humain, il faut d'abord qu'il parvienne à lire à partir
d'une camera (webcam). Nous savons aussi qu'un flux est une succession d'images
(appelées frames) qui ont été prises à intervalles
de temps réguliers.
Pour arriver à capturer les éléments qui
passent devant la caméra, nous avons utilisé la fonction
cvCaptureFromCAM et nous avons stocké cette donnée dans
la variable capture qui est du type Iplimage.
Une condition a été utilisée pour
vérifier si la capture a été réalisée.
Si oui, ouverture d'une boucle infinie et dans cette
dernière nous avons utilisé la fonction cvGrabFrame pour
saisir des frames de la caméra et nous les stockons dans la variable
frame.
Si non, chargement d'un fichier image d'une personne qui se
trouve dans un emplacement de l'ordinateur à l'aide de la fonction
cvLoadImage.
Toujours dans la boucle infinie, nous avons alloué une
image de même dimension que la frame saisie et nous avons crée une
copie bien sûr avec la fonction cvCopy et c'est sur cette copie
que nous avions à appliquer la détection du visage. Dans cette
même boucle (infinie), nous y avons mis la condition d'arrêt de la
boucle au cas où on appuyait sur n'importe quelle touche du clavier avec
la fonction cvWaitKey.
A la fin de cette boucle, nous avons détruit la frame
et la copy de la frame (qui sont considérées ici comme
étant déjà des images) à l'aide de la fonction
cvReleaseImage . Pour ainsi tout afficher dans une fenêtre et
donner le nom à cette dernière, nous avons utilisé la
fonction cvNamedWindow, cette fenêtre est détruite
à la fin de la boucle par la fonction cvDetroyWindow au cas
où on quittait le programme en l'arrêtant.
Nous avons pu afficher un message sur la fenêtre de la
vidéo créée grâce à la fonction
cvPutText.
Cette partie expliquée étant la partie
principale du programme (le main en anglais), nous a permis d'aboutir
au résultat suivant et qui est représenté par l'image
ci-dessous :
Pour arriver à détecter le visage présent
devant la camera, nous avons fait usage de la fonction
cvHaarDetectObjects.
Cette fonction fait appel à un classifieur qui permet
de détecter le visage d'une personne devant la camera.
NB : Il est à noter que ces classifieurs ne sont
pas les mêmes parce que sont crées pour des fins
différentes : pour détecter les personnes, détecter
les voiture, détecter les plaques des voitures,...
OpenCV vient déjà avec différents
classifieurs du visage (face) humain dès son installation. Ces
différents classifieurs sont situés dans le dossier data/
haarcascades/. Voici en exemple les classifieurs que nous trouvons dans OpenCV
de sa version 2.2.0 :
haarcascade_eye
haarcascade_eye_tree_eyeglasses
haarcascade_frontalface_alt
haarcascade_frontalface_alt_tree
haarcascade_frontalface_alt2
haarcascade_frontalface_default
haarcascade_fullbody
haarcascade_lefteye_2splits
haarcascade_lowerbody
haarcascade_mcs_eyepair_big
haarcascade_mcs_eyepair_small
haarcascade_mcs_lefteye
haarcascade_mcs_mouth
haarcascade_mcs_nose
haarcascade_mcs_righteye
haarcascade_mcs_upperbody
haarcascade_profileface
haarcascade_righteye_2splits
haarcascade_upperbody
Etant donné que nous avions à détecter le
visage humain, nous avons fait usage du classifieur
haarcascade_frontalface_alt.xml.
C'est ainsi que nous avons crée une fonction
appelée detecte_et_dessine qui détecte le visage et
dessine un rectangle autour du visage comme son nom l'indique. Dans cette
dernière, nous chargeons le classifieur qui a été
stocké dans une variable. Si le chargement réussit, nous
parcourons les frames avec la fonction cvHaarDetectObjects pour
chercher à détecter tout visage devant la camera. Une fois le
visage détecté, nous le parcourons en considérant ses
différents cotés et nous y traçons un rectangle avec la
fonction cvRectangle. Pour mieux voir le visage
détecté, nous l'affichons dans une autre fenêtre Windows.
Nous savons que la reconnaissance faciale a ses limites entre
autre les conditions d'éclairage pour mieux assurer la reconnaissance de
visage. Pour contourner cette difficulté, nous avons converti cette
figure détectée en image grise sur laquelle nous appliquons
l'égalisation d'histogramme pour rendre la surbrillance et le contraste
consistants à l'aide de la fonction cvEqualizeHist.
Ainsi la détection est réalisée et nous
aboutissons au résultat suivant représenté par
l'image ci-dessous:
Voici en quelques lignes le code utilisé pour la
détection de visage :
Nous avons crée deux autres fonctions nommées
Enreg_faceImg1 et Enreg_faceImg2. La première fait
l'enregistrement de visages dans le dossier des visages temporaires dans et la
deuxième le dossier considéré comme la base de
données des visages sélectionnés. Ces deux fonctions nous
ont permis d'enregistrer chaque fois 3 images successivement après
chaque seconde à l'aide de la fonction cvSaveImage dans des
emplacements différents ci-haut signalés.
Dans ces fonctions, nous avons utilisé le format de la
date/heure pour donner le nom aux figures capturées. Ceci nous a permis
de capturer une ou plusieurs images de figures ayant chacune un nom
différent de l'autre.
C'est ainsi que nous avions à stocker les figures sur
le disque dur dans un emplacement précis. En plus de cela, chaque
enregistrement était accompagné par l'ouverture,
l'écriture dans un fichier texte (d'extension .txt) et la fermeture de
cet dernier. L'écriture dans le fichier texte est du format :
1 imgDataBase/face_16-01-2012_12:57:36.bmp
1 imgDataBase/face_16-01-2012_12:57:37.bmp
2 imgDataBase /face_02-02-2012_05:50:14.bmp
2 imgDataBase /face_02-02-2012_05:50:15.bmp
3 imgDataBase /face_02-02-2012_05:50:56.bmp
3 imgDataBase /face_02-02-2012_05:50:57.bmp
Ceci veut dire au programme que toutes les images (figures)
ayant le même nombre entier désigne les figures d'une même
personne, une fois ce nombre change c'est-à-dire par exemple passe de 1
à 2, les figures deviennent d'une autre personne qui n'est plus la
première.
Nous tenons à préciser que nous avions
utilisé deux fichiers de type texte : l'un nommé bdd.txt
qui stocke les adresses des figures sélectionnées dan la
base de données et l'autre nommé test.txt qui stocke les
adresses des figures capturées temporairement qui vont subir le teste
avant d'être stockées et considérées comme images de
la base de données.
· Reconnaissance du visage
Pour parvenir menant à assurer une reconnaissance pour
mieux sélectionner les visages à enregistrer une et une seule
fois dans la base de données (ne pas enregistrer le visage d'une
personne au cas où il est existe déjà dans la base de
données), nous avons utilisé une autre fonction nommée
apprentissage.
Dans cette fonction, nous avons commencé par charger
les visages stockés dans la base de données (bien sûr par
ouverture en lecture du fichier contenant les adresses des figures
stockées sur le disque dur) à l'aide de la fonction
loadFaceImgArray. Cette fonction permet de lire ligne par ligne dans
le fichier texte bdd.txt et ainsi compter le nombre de figures
chargées, ceci étant possible du fait que chaque tour de lecture
d'une ligne équivaut est stocké dans une variable nommée
nTrainFaces de type integer (entier). Toutes ces
figures chargées sont projetées dans la fonction
doPCA.
Cette fonction, n'est que celle qui permet de
régénérer d'autres figures appelées ici dans notre
programmation eigenface. Ces figures
régénérées sont issues de la première figure
capturée permettant ainsi d'avoir une multitude de figures peu
semblables à la figure d'origine. En confrontant ces différentes
figures, nous parvenons à reconnaitre la première figure
d'origine.
Cette opération se fait de la manière suivante
suivant cet exemple :
(FaceOriginale) + (13.5% de la face
régénérée0) - (34.3% de la face
régénérée1) + (4.7% de la face
régénérée2) + ... + (0.0% de la face
régénérée20).
Une fois il a résolu ceci, il peut penser à
cette image source de la formation comme les 20 proportions: {13.5, -34.3, 4.7,
..., 0.0}.
Dans cette fonction apprentissage fait aussi appel
à une autre fonction nommée storeTrainingData . Quant
à cette dernière fonction, elle permet de créer un
fichier de stockage d'extension xml. Ce fichier sert à stoker toutes les
données que nous avions à utiliser et que nous aurons aussi
à utiliser mais qui y sont stockées comme des entiers. Ces
données sont : les différentes figures
régénérées par la fonction doPCA, les
figures originales, le nombre entier qui représente le nombre de visage
stockées pour chaque personne, ...
Par la suite, nous avons aussi utilisé une autre
fonction nommée reconnaissance. Cette fonction nous a permis
aussi de charger les figures contenues dans le fichier test.txt (bien
sûr avec la fonction loadFaceImgArray) pour enfin comparer la
ressemblance entre les figures déjà stockées dans la base
de données et les figures vouées au teste avant d'être
considéré comme figures de la base de données existante.
Cette fonction nous a permis aussi de calculer le pourcentage de
rapprochement entre les visages.
Il faut aussi signaler qu'une autre fonction nommée
loadTrainingData a été utilisée pour charger
les données (visages et autres) stockées dans le fichier xml et
ainsi faire la comparaison avec ceux qui vont subir le teste.
Il convient aussi de signaler que c'est dans la fonction
findNearestNeighbor qu'a été calculée la distance de
Mahalanobis pour effectuer une mesure de distance (divergence) entre toutes
les figures (visages) détectée (cfr. Annexe A.2).
Nous avons estimé ce taux de divergence en terme de
pourcentage et avons considéré 10,00% comme seuil. Ceci veut
signifier que, chaque fois que la comparaison de distance entre deux visages
est au-delà de ce 10,00% (c'est-à-dire 10,01% et plus), les deux
visages sont différents et par conséquent le visage
détecté est enregistré dans la base de données.
Ainsi la condition remplie, une capture de trois images était
possible.
Dans le cas contraire (c'est-à-dire entre 0,00% et
10,00%), le visage détecté existe déjà dans la base
de données et par conséquent il n'est pas enregistré.
|