alexylem / jarvis

Jarvis.sh is a simple configurable multi-lang assistant.
http://openjarvis.com
MIT License
810 stars 197 forks source link

Détection et reconnaissance Faciale avec apprentissage #56

Open alexylem opened 8 years ago

alexylem commented 8 years ago

Description

Donner la vue à jarvis: intégrer Jarvis avec l'un de mes autres projets sur opencv pour qu'il puisse détecter les visages, vous reconnaître s'il vous connaît déjà, et vous proposer de se souvenir de votre visage le cas échéant. L'idée principale serait d'avoir des notifications personnalisées en fonction de la personne qui passe devant les yeux de Jarvis, ex:

(Alex passe devant la caméra)
Jarvis: Oh bonjour Alex, tu as 2 emails non lus, veux-tu que je te les lise?
physicien commented 8 years ago

Pour ce qui est du Cascade Classifier Training, j'ai déjà tout ce qu'il faut (installation, échantillons positifs et négatifs). Je connais également assez bien les différents paramètres d'entraînement et comment les optimiser. Mais avant toute chose, je vais essayer d'améliorer les performances en recompilant pour optimiser le tout.

alexylem commented 8 years ago

Alors pour info j'ai aussi un prototype que j'ai fait qui fonctionne ainsi:

physicien commented 8 years ago

Je suis curieux, utilises-tu les classifiers de base venant avec OpenCV où as-tu entraîné tes propres .xml? De plus, quelles sont les performances pour une seule image pour ce qui est de la reconnaissance?

alexylem commented 8 years ago

Alors si je me souviens, j'utilise les classifiers de base pour la détection du visage. Après je traine mon propre modèle pour la reconnaissance. C'est trop lent pour tourner sur raspberry pi 1 (d'ailleurs je crois même que ca plante), mais sur mon raspberry pi 3 c'est acceptable. La détection est quasi instantanée, et la reconnaissance je pense qu'on est à 1 seconde. Il faudrait que je le refasse tourner car je ne me souvient plus exactement.

physicien commented 8 years ago

Moi pour le moment j'entraîne mes classifiers sur mon PC pour une meilleure performance. Je les teste cependant directement sur la RP3. Je compte utiliser plus que les .xml de détection de visage (détection de banane, de chats, de Charlie,...), car mon installation de Jarvis est embarquée et sur chenilles :laughing:

physicien commented 8 years ago

Je viens d'entraîner un classifier et le résultat est intéressant. Sur cette base, je vais pouvoir optimiser l'entraînement et obtenir un meilleur taux de détection. EDIT: j'ai essayé avec une image prise de la Picam et je suis aussi à une seconde sur la RP3.

alexylem commented 8 years ago

Ok pour les classifiers, mais la tu parles de détection, pas de reconnaissance. Pour la détection j'ai des résultats bcp plus performants (genre 0.1 ou 0.2 secondes). Testes-tu aussi la reconnaissance (donner un nom à un visage) ? Au fait mon prototype est mon python, tu fais ca en quel language?

physicien commented 8 years ago

Pour l'instant je me concentre sur la détection (j'ai ~55k positive samples et ~150k negative samples et je maîtrise assez bien l'optimisation des paramètres maintenant). Dès que je vais avoir lancé l'entraînement, je compte me lancer dans la reconnaissance avec le chapitre 8 de ce livre Mastering_OpenCV_with_Practical_Computer_Vision_Projects.pdf Sinon, pour les performances j'ai pris le temps de faire un time et j'ai aussi des temps de calcul de l'ordre de 0.1 à 0.2 secondes pour une image normale. Pour ce qui est du langage, j'utilise du Python et du C++ (surtout qu'on ne va pas réinventer la roue, une bonne partie des codes sont déjà dispo sur les internets).

alexylem commented 8 years ago

Ok pour info mon prototype est 100% python, et je me suis bcp servi de ce projet la: https://learn.adafruit.com/raspberry-pi-face-recognition-treasure-box/overview

physicien commented 8 years ago

C'est drôle, parce que j'ai ce projet là dans mes marque-pages depuis un moment déjà. Je vais donc regarder ça de plus près dès que j'ai fini de comparer les performances de mon .xmlavec ceux par défaut.

physicien commented 8 years ago

J'aimerais avoir ton opinion. Je suis en train de refaire une installation propre et pour l'installation d'OpenCV, j'ai suivi ce guide où on utilise workon comme environnement virtuel. Je me demandais simplement quel genre de config tu as fais pour OpenCV.

alexylem commented 8 years ago

Oui j'ai vu qu'il était recommandé d'utiliser workon si l'on travaille beaucoup avec python pour éviter les conflits de versions et de modules. Ne faisant qu'un prototype je suis allé à l'essentiel et m'en suis passé. Si tu veux je peux te passer qqchose qui vaut de l'or, c'est à dire mes étapes d'installation et de compilation d'openCV, c'est le résultat de plusieurs jours, que dis-je, semaines de bataille acharnée, intéressé? 😄

Pour te donner un peu de motivation, voici quelques screenshots (que j'ai fait à l'instant) de mon prototype :

image

image

image

Le chiffre entre parenthèse est le facteur de confiance fourni par openCV. Et du coup je confirme, je suis bien à plus d'une frame par seconde 😄

physicien commented 8 years ago

C'est certain que je suis intéressé! Ça va me permettre de tester la reconnaissance sur la RP3 pendant que mon PC essai de digérer un peu moins de ~200k images. :smile:

Si tu veux, je te montrerai mes config pour PC et surtout les options de compilation pour accélérer le calcul au maximum. J'ai aussi passé quelques jours à éplucher la littérature pour l'optimisation des paramètres, et je suis prêt à dire que je les maîtrise assez bien maintenant.

alexylem commented 8 years ago

J'ai oublié cette image, sinon c'est trop facile 😉 image

Voici le saint graal:

sudo apt-get install -y apt-transport-https
sudo apt-get install -y build-essential git cmake pkg-config
sudo apt-get install -y libjpeg-dev libtiff5-dev libjasper-dev libpng12-dev
sudo apt-get install -y libavcodec-dev libavformat-dev libswscale-dev libv4l-dev
sudo apt-get install -y libxvidcore-dev libx264-dev
sudo apt-get install -y libxvidcore-dev libx264-dev
sudo apt-get install -y libgtk2.0-dev
sudo apt-get install -y libatlas-base-dev gfortran
sudo apt-get install -y python2.7-dev python3-dev
cd ~
wget -O opencv-3.1.0.zip https://github.com/Itseez/opencv/archive/3.1.0.zip
unzip opencv-3.1.0.zip 
wget -O opencv_contrib-3.1.0.zip https://github.com/Itseez/opencv_contrib/archive/3.1.0.zip
unzip opencv_contrib-3.1.0.zip 
wget https://bootstrap.pypa.io/get-pip.py
sudo python get-pip.py
sudo pip install numpy
cd opencv-3.1.0/
mkdir build
cd build
cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -D INSTALL_C_EXAMPLES=OFF -D INSTALL_PYTHON_EXAMPLES=ON -D OPENCV_EXTRA_MODULES_PATH=~/opencv_contrib-3.1.0/modules -D BUILD_EXAMPLES=ON ..
make -j4
sudo make install
sudo ldconfig

(les paramètres de compil sont optimisés pour Rasperry Pi 3)

Qui inclue bien évidemment le package opencv_contrib qui permet d'utiliser la fonction predict (reconnaissance). opencv compilé sans opencv_contrib ne permettra que la détection.

alexylem commented 8 years ago

Par contre tu ne pourras pas tester avant demain, il y a 4 heures de compilation si je me rappelle bien... EDIT: maintenant j'ai un doute, je crois que c'était sans le flag -j4

physicien commented 8 years ago

4 heure... C'est rien dans mon référentiel. Les joies de la computational geometry, c'est que tu travailles sur ton divan en attendant le résultat d'une simulation :laughing: Et je suis content de savoir que je vais pouvoir apprendre à ma Pi à reconnaître Flanby.

alexylem commented 8 years ago

Génial! A par contre j'ai aussi bcp lutté sur le facteur de confiance. J'ai du modifier des headers et refaire la compilation, si tu n'en as pas besoin pour le moment c'est pas grave, sinon regarde mon post sur: http://answers.opencv.org/question/82294/cant-get-predict-confidence/?comment=92484#comment-92484

physicien commented 8 years ago

Je partage mes dernier développements pour ce qui est de la détection. J'ai réussi à entraîner un classeur de 10 stage qui a un excellent taux de détection. Durée d'entraînement: 09:13:57

physicien commented 8 years ago

@alexylem J'aimerais savoir, ton prototype tu l'as fait en Python ou en C++? Je demande, car je trouve des morceaux de code directement dans OpenCV (ex /opencv_contrib/modules/face/samples /facerec_video.cpp) et que C++ est généralement beaucoup plus léger à rouler.

alexylem commented 8 years ago

@physicien full python 2.

image

$> cat run 
#/bin/sh
python main.py
physicien commented 8 years ago

Humm, intéressant. J'ai bien hâte que ce soit ajouté à Jarvis pour voir le code source :smile:

physicien commented 8 years ago

Bon, de mon côté je suis aussi arrivé des résultats avec la version C++. capture d ecran - 2016-07-25 - 20 26 59

Pour faire ça, j'ai:

alexylem commented 8 years ago

Super travail, tu as un joli taux de confidence 👍 surtout vu le contre jour! Si jamais tu mets une photo de quelqu'un d'autre, ca te met quoi?

physicien commented 8 years ago

En fait, je ne suis pas certain que le chiffre soit le taux de confiance. Je crois que c'est l'ID de la personne identifiée. Si c'est bien ça, je ressemble donc à cet homme: 1 Faudrait bien analyser le facerec_video.cpp, mais de ce que j'en ai vu il est fait pour qu'on l'améliore facilement.

Je viens d'essayer avec une autre photo, et voici le résultat. capture d ecran - 2016-07-26 - 02 15 50 C'est pas encore super, mais le C++ a probablement plus de potentiel pour l'embarqué vu le peu de ressources nécessaires.

EDIT1: Je confirme que nous avons tout ce qu'il faut pour améliorer la version C++. Nous n'avons qu'à suivre le chapitre 8 du livre que j'ai partagé il y a 7 jours. EDIT2: Voici le Github du livre avec tous les codes :smile: https://github.com/MasteringOpenCV/code

alexylem commented 8 years ago

Oui en effet il retourne l'ID, pour avoir le taux de prédiction, j'ai du changé des header et recompiler (voir mon post plus haut). Ensuite j'ai utilisé l'ID pour retrouver le nom de la personne (c'est un genre d'index). Ça serait bien qu'on fasse un benchmark de la version c++ versus la version python, mais comme on utilise les mêmes librairies pas dit qu'il y ait une grosse différence.

physicien commented 8 years ago

Je ne sais pas si tu as vu mes EDITs, mais on a visiblement un prototype très complet en C++ aussi maintenant :smile: Le résultat supposé ressemble à ça: screenshot Je vois déjà que les trois boutons en haut à gauche pourraient être remplacer par une commande vocale de Jarvis.

alexylem commented 8 years ago

Oui j'entrevois bien la nouvelle interface de Jarvis :smile:

physicien commented 8 years ago

Je suis en train d'essayer de compiler l'interface et au moment de faire le make, j'obtiens ces erreurs: capture d ecran - 2016-07-26 - 12 34 12

Il y a visiblement certains headers à refaire.

Smanar commented 8 years ago

Je viens de voir ca sur un github

error: ‘FaceRecognizer’ was not declared in this scope

If you ever get this error with OpenCV, it can be solved using either of the two simple includes mentioned below:

If your OpenCV version is below 3.0 (and above 2.xx) Then, adding #include "opencv2/contrib/contrib.hpp" in the cpp file should have the required declarations for the FaceRecognizer class
If your OpenCV version is 3.0 and up, Then, instead of #include "opencv2/contrib/contrib.hpp" add #include "opencv2/face.hpp" and instead of FaceRecognizer use cv::face::FaceRecognizer in the code.
physicien commented 8 years ago

Est-ce qu'il est précisé les endroits où il faut le changer? Parce qu'il semble y en avoir un paquet, et n'étant pas un expert en C++, je vais certainement en oublier :laughing:

Smanar commented 8 years ago

Si tu te retrouve exactement dans leur cas, c'est pas dur. Tu commences toujours par le premier message d'erreur. Ne pas chercher a corriger le second car il y a de forte chance que les problemes suivant proviennent du premier.

Je ne peux pas te dire trop precisement car le projet est apparement tres lourd a compiler, et je n'ai pas accee au PI avant ce WE, mais vla ce que moi je ferais.

Apparement la definition qui te manque ce trouve ici http://docs.opencv.org/trunk/dd/d65/classcv_1_1face_1_1FaceRecognizer.html#gsc.tab=0

Donc dans main.cpp je rajoute (fait gaffe a l'ordre des headers, ca a une importance aussi, si le second contient une definition pour le premier ca va deconner aussi)

include "opencv2/face.hpp"

A modifier selon tes chemins d'acces.

Du coup quand je vais arriver au fichier recongnition.h la class FaceRecognizer sera definie. Par contre d'apres le lien precedent, il y a une histoire d heritage donc la fonction FaceRecognizer ne marchera pas il faudrait utiliser cv::face::FaceRecognizer

Sinon, regarde ce projet https://github.com/peterbraden/node-opencv/blob/master/src/FaceRecognizer.h , sur les 12 premieres lignes, c'est exactement ce que fait leur code, tu n'as pas ce fichier toi ? En fait pour la modif "Enable FaceRecognizer on OpenCV3 " ils ont cree ce fichier et rajoute "#include "FaceRecognizer.h" dans leur main

if CV_MAJOR_VERSION >= 3

include <opencv2/face.hpp>

namespace cv { using cv::face::FaceRecognizer; }

else

include "opencv2/contrib/contrib.hpp"

endif

Tu fais la modif uniquement sur la premiere erreur, et tu recompiles, si elle revient (tu as les numeros de ligne dans le debug pour te reperer 40:10 = ligne 40, 10 eme caractere), pas la peine d'aller modifier les autres.

Normalement ca va te supprimer les 3 premieres erreurs d'un coup. Apres rebelotte si ca continue.

physicien commented 8 years ago

Je partage ma progression. Pour l'instant, j'ai réglé pas mal d'erreurs en m'assurant d'avoir using namespace cv;, using namespace cv::face; et using namespace std; dans main.cpp, recognition.h et recognition.cpp J'ai aussi dû modifier l'appel à certaine class pour l'adapter à OpenCV >= 3 Voici mes erreurs actuelles capture d ecran - 2016-07-28 - 12 45 52

TmpName commented 8 years ago

La c'est bizarre, tu es sur de ne pas avoir fait de fausse manip ? En fait le compilo ne trouve pas la fonction "getmean" dans fazeReconiser et c'est normal. Facereconizer

http://docs.opencv.org/3.1.0/dc/dd7/classcv_1_1face_1_1BasicFaceRecognizer.html#gsc.tab=0

Par contre elle se trouve dans BasicFaceRecognizer (par exmple)

http://docs.opencv.org/3.1.0/dc/dd7/classcv_1_1face_1_1BasicFaceRecognizer.html#gsc.tab=0

Tu devrais avoir juste avant Ptr model = BasicFaceRecognizer(); ou Ptr model = createEigenFaceRecognizer();

Tu n'aurais pas deborde en mettant des "cv::face::" ? Sur la premiere ligne en blanc, il me semble y en avoir beacoup. void showTrainingDebugData(Ptr model, int, int) me semble mieux.

Tu es sur que ton code ne date pas de 5 ans au moins ?

physicien commented 8 years ago

Je n'ai pas modifié cette partie du code pourtant. Je viens de changer pour BasicFaceRecognizer et j'ai en effet moins d'erreurs. On va y arriver peu à peu! capture d ecran - 2016-07-28 - 21 12 33

Smanar commented 8 years ago

Heu, je crois pas, dsl ^^. Cette fois la mise a jour est vraiment differente, trop de difference avec ta version et la derniere, les fonctions ne sont plus du tout les memes, il faudra plus que modifier une ligne.

Honnetement le plus simple pour toi, c'est de mettre ce tuto a la poubelle, trop vieux, et de passer sur le nouveau mit a jour. Regarde sur ce github si tu retrouves, ton code mais a jour https://github.com/opencv/opencv_contrib/tree/master/modules/face/samples apprement ce serait le dernier officiel mais a jour.

physicien commented 8 years ago

Ah oui, ça je l'ai essayé et je suis capable de le faire fonctionner. C'est ce que j'ai publié il y a 4 jours environ. Le seul problème avec la nouvelle version, c'est que tout est à faire côté client et fonctions d'apprentissage pour l'utilisateur. Et en effet, j'ai dû changer quelques fonctions, et actuellement je cherchais celles qui me manquent.

Smanar commented 8 years ago

Je viens de lire ton fichier, et j'ai compris le prb, sauf que j'ai essaye de trouver une source a jour, faisant la meme chose, et c'est hard de trouver des projets de moins de 1 an ... Je n'arrive meme pas a trouver des mecs ayant fait comme toi et mit a jour ce tutorial. Honnettement je ne peux meme pas te dire si ca irait plus vite de mettre le code a jour ou de le refaire a partir d'une base plus recente.

physicien commented 8 years ago

Je suis content qu'on arrive à la même problématique: mettre à jour ou repartir des bases. Pour info, les seuls erreurs qu'il me reste sont celles par rapport à projection, subspaceProject et subspaceReconstruct. Je ne peux pas faire de capture pour l'instant, car j'ai démonté mon montage pour changer de lieu. Je remonterai une fois à destination.

Smanar commented 8 years ago

Pour le probleme de getmat(), j'ai vu ce post http://stackoverflow.com/questions/28863538/no-member-named-getmat-in-cvfacefacerecognizer si tu ne l'as pas deja vu. Mais sans connaitre le code je ne vois absolument pas de quoi ils parlent.

Tiens moi au courant, je suis en train de l'installer sur Visual studio, en esperant que les tuto soit multiplateforme.

Smanar commented 8 years ago

Bon dsl, j'etais d'astreinte et j'ai vraiment pas eu de temps libre mais je viens de finir de l'installer sur visual studio, par contre y avait pas mal de modif. Il ne me reste plus que la convertion pour getmat, et de croiser les doigts pour que le prog marche encore.

Il te manque deja

  Mat projection = cv::LDA::subspaceProject(eigenvectors, averageFaceRow, preprocessedFace.reshape(1, 1));
    Mat reconstructionRow = cv::LDA::subspaceReconstruct(eigenvectors, averageFaceRow, projection);

avec en debut

include "include\opencv2\core.hpp"

Smanar commented 8 years ago

Bon dsl de me taper un monologue, mais si j'edite encore le precedent post, il n'aura pas d'alerte. J'ai fini la convertion, tout focntionne sauf la partie model = cv::face::createLBPHFaceRecognizer(); mais je sais meme pas si elle sert. Si tu n'es pas encore en vacance et tjours interesse, je te met tout ca dans un zip.

physicien commented 8 years ago

Ah, génial! Pour le .zip c'est quand tu veux. Sinon, quelles fonctions du programmes as-tu utilisé? Est-ce qu'il y a des trucs qu'on va devoir refaire?

Smanar commented 8 years ago

Fichiers modifies > http://www.cjoint.com/c/FHepjDFmyWx

Pas de grosses modifs, j'ai juste change les vielles API par les nouvelles. Le seul truc que j'ai pas corrige recognition.cpp ligne 64, je l'ai laisse en commentaire, car apparement jamais appellée (j'ai mis un breakpoint qui n'a jamais ete atteint.

physicien commented 8 years ago

Ok, la ligne 64 est supposer appeler la méthode des Local Binary Pattern Histograms qui se trouve dans ~/opencv_contrib-3.1.0/modules/face/facerec_lbph.cpp.

EDIT1: en fait, je ne suis plus certain si c'est là ou si c'est simplement un autre bout de code qui appelle la même classe, mais je vais regarder si je n'arrive pas à retrouver le bon chemin de là. EDIT2: Projet assez récent (4 mai 2016 selon Google) qui parle des avantages d'utiliser les LBPH. Lien

physicien commented 8 years ago

Bon, je viens de remonter mon setup de RP3 et je suis en train d'essayer les fichiers modifiés de @Smanar . Cependant, il y a une ligne nouvellement ajoutée qui me cause une erreur de compilation capture d ecran - 2016-08-15 - 16 10 09

EDIT1: Si je commente cette ligne, la compilation se termine sans problème. Il ne me reste donc qu'à link la caméra de la RP3. capture d ecran - 2016-08-15 - 16 32 15

EDIT2: Il y a une piste de solution pour utiliser la caméra avec RaspiCam et voir les lignes 173 à 185 de main.cpp. Autre source.

physicien commented 8 years ago

Je viens de tester avec ma webcam, et ça fonctionne tempête!

capture d ecran - 2016-08-16 - 01 10 10

Par contre, j'ai un segmentation fault si je tente d'utiliser la reconnaissance par LBPH au lieu de Fisherfaces ou Eigenfaces.

capture d ecran - 2016-08-16 - 01 27 50

Je dois aussi trouver comment enregistrer les entraînements.

capture d ecran - 2016-08-16 - 01 50 34

Smanar commented 8 years ago

Ben je crois que c'est la partie que j'ai pas adapte car chez moi, je n'y suis jamais passe, je ne sais meme pas ce que c'est ^^.

Le seul truc que j'ai pas corrige recognition.cpp ligne 64, je l'ai laisse en commentaire, car apparement jamais appellée (j'ai mis un breakpoint qui n'a jamais ete atteint.

A moins que tu ais deja fait des modifs a cet endroit ?

physicien commented 8 years ago

Je vais tenter de corriger cette ligne 64, car ça semble être à cet endroit que ça m'empêche d'utiliser le LBPH. Déjà, voici les erreurs de compilation que j'ai en décommentant la ligne. J'ai aussi trouvé la classe que l'on cherche utiliser dans opencv_contrib/modules/face/samples/facerec_lbph.cpp.

capture d ecran - 2016-08-16 - 11 28 59

physicien commented 8 years ago

@Smanar En fait, je peux t'expliquer exactement comment "y passer" comme tu dis. Si tu vas dans main.cpp, les lignes 32 et 33 définissent quel algorithme le programme va utiliser pour effectuer la reconnaissance faciale. J'ai également ajouté une ligne 34 qui manquait, ces lignes vont donc comme suit:

//const char *facerecAlgorithm = "FaceRecognizer.Fisherfaces";
//const char *facerecAlgorithm = "FaceRecognizer.Eigenfaces";
const char *facerecAlgorithm = "FaceRecognizer.LBPH";

où la l'algorithme que nous voulons utilisé n'est pas commenté. À remarquer que la ligne 41 doit être ajustée en conséquence de l'algorithme et selon les préférences de l'utilisateur, car elle indique la valeur pour laquelle quelqu'un est classé inconnu. const float UNKNOWN_PERSON_THRESHOLD = 0.5f;

Pour résumer, la raison pourquoi ça n'y passait pas, c'est parce que nous utilisons de base un algorithme différent.

physicien commented 8 years ago

Pour ce qui est de la caméra de la RP3, je viens de réussir à l'activer par défaut au lancement. Il suffi pour cela de configurer le driver.

Pour qu'il soit automatiquement chargé au démarrage, éditez le fichier /etc/modules et ajoutez à la fin bcm2835-v4l2

Cependant, je remarque que ça utilise ~40% du CPU de la RP3, mais il y a très peu de latence.