Chapitre 8 : Reconnaissance faciale
Objectif de ce chapitre : enregistrer des caractéristiques faciales, apprendre au NanoCam à reconnaître « qui vous êtes », et bâtir une solution complète de contrôle d'accès.
Principe
La reconnaissance faciale = détection de visage (pipeline à deux étages MSR01+MNP01) + extraction de caractéristiques (réseau de neurones FaceRecognition112V1S8 MFN) + comparaison par similarité cosinus.
Trame RGB565 de la caméra
→ Détection grossière MSR01 (320×240, seuil 0.3F)
→ Détection fine MNP01 (sur les candidats grossiers, seuil 0.4F)
→ Extraction de 10 points clés du visage (yeux / nez / commissures des lèvres)
→ Alignement sur les points clés → recadrage du visage 112×112
→ Réseau convolutif MFN → vecteur de caractéristiques 512 dimensions
→ Normalisation L2
→ Calcul de la distance cosinus avec chaque vecteur d'ID enregistré en Flash
→ Similarité cosinus maximale > seuil (0.55) → correspondance → sortie de l'ID
→ Toutes les similarités < seuil → personne inconnue → sortie « who? »Optimisation des performances
L'extraction de caractéristiques MFN et la comparaison sur l'ensemble de la base sont très coûteuses ; les exécuter à chaque trame ferait saccader l'image. L'implémentation actuelle adopte une stratégie de saut de trames : la détection de visage tourne à chaque trame (peu coûteuse), la reconnaissance MFN une fois toutes les 10 trames (coûteuse), et l'étiquette affiche en continu le dernier résultat de reconnaissance. L'image reste ainsi fluide et l'étiquette d'ID ne clignote pas.
Stockage des caractéristiques faciales
Les caractéristiques faciales enregistrées (id + embedding 512 dimensions) sont stockées de façon persistante dans la partition fr de la Flash (96 KB, jusqu'à 47 identifiants faciaux). Elles survivent à une coupure d'alimentation.
Matériel requis
Carte principale NanoCam + carte de base
Câble USB-C (alimentation + port série vers le PC)
Terminal série (débit 115200)
Étapes
8.1 Entrer en mode reconnaissance faciale
ai_mode:4L'appareil redémarre automatiquement en mode FaceID ; le LED RGB WS2812 (GPIO18 DIN, alimentation VDD50) s'allume en violet. Après le redémarrage, le port série doit afficher :
I (5526) MFN: fr partition size: 98304 bytes, maxminum 47 IDs can be stored
I (5526) MFN: No face ID in flashNo face ID in flash signifie qu'aucun visage n'a encore été enregistré — c'est normal.
8.2 Enregistrer un visage
Placez le visage bien face à la caméra (distance 30-50 cm, éclairage uniforme) et assurez-vous qu'il n'y a qu'un seul visage à l'image. Envoyez sur le port série :
face_erilL'appareil détecte le visage, extrait automatiquement les caractéristiques et l'enregistre en Flash :
I (xxxx) ENROLL: ID 1 is enrolledL'image superpose le texte bleu Enroll: ID 1, qui disparaît après environ 0.5 seconde.
Attention : la commande est
face_eril(abréviation d'enroll), pasface_enroll. Si vous voyezfail: unknown command, vérifiez l'orthographe.
8.3 Reconnaître un visage
Une fois l'enregistrement terminé, envoyez la commande de reconnaissance :
face_rzLe système passe en mode de reconnaissance continue. Le visage présent est comparé à tous les identifiants enregistrés en Flash :
Correspondance : le port série affiche
Similarity: 0.85, Match ID: 1, l'image superpose en continuID: 1en vertPersonne inconnue : le port série affiche
Similarity: 0.32, Match ID: 0, l'image superpose en continuwho?en rouge
L'étiquette reste affichée et ne disparaît pas. Pour quitter le mode reconnaissance, envoyez
face_detectpour revenir en mode détection pure.
8.4 Supprimer un visage
face_delSupprime le dernier identifiant facial enregistré ; le port série renvoie N IDs left et l'image affiche brièvement le nombre d'identifiants restants. Les caractéristiques en Flash sont supprimées en même temps.
8.5 Quitter le mode reconnaissance
face_detectRetour au mode détection de visage pure (cadre + points clés uniquement, sans reconnaissance) ; les étiquettes d'ID sont effacées.
À propos du mode DETECT : sur l'ESP32-S3, l'impression des coordonnées sur le port série en mode détection pure est désactivée (
#if !CONFIG_IDF_TARGET_ESP32S3), afin d'éviter que les journaux de détection ne saturent le port série. Les journaux de coordonnéesdetection_resultn'apparaissent qu'après être entré en mode reconnaissance (face_rz).
Aide-mémoire des commandes
| Commande | Fonction | Comportement de l'étiquette | Persistante |
|---|---|---|---|
face_eril | Enregistrer le visage actuellement détecté | bleue Enroll: ID N | flash 0.5s |
face_rz | Entrer en mode reconnaissance continue | verte ID: N / rouge who? | ✅ continue |
face_del | Supprimer le dernier identifiant enregistré | rouge N IDs left | flash 0.5s |
face_detect | Quitter la reconnaissance, revenir en détection pure | efface toutes les étiquettes | — |
Pour la liste complète des commandes, voir le Manuel du protocole série.
Exemple de déroulement
ai_mode:4 # Entrer en mode reconnaissance faciale
[redémarrage de l'appareil, LED violet]
face_eril # Enregistrer le premier visage (Alice)
→ ID 1 is enrolled
face_eril # Enregistrer le second visage (Bob)
→ ID 2 is enrolled
face_rz # Démarrer la reconnaissance continue
→ Alice devant la caméra : l'image affiche « ID: 1 » en continu
→ Bob devant la caméra : l'image affiche « ID: 2 » en continu
→ Une personne inconnue devant la caméra : l'image affiche « who? » en continu
face_detect # Quitter le mode reconnaissance
→ les étiquettes disparaissent, seuls les cadres de détection restent
face_del # Supprimer Bob (ID 2)
→ 1 IDs left
face_rz # Reconnaître à nouveau
→ Alice devant la caméra : « ID: 1 »
→ Bob devant la caméra : « who? » (supprimé)Le mode reconnaissance faciale consomme beaucoup de mémoire (modèle MFN + double modèle de détection de visage). Le port série Type-C (UART0) fonctionne normalement. Si le port série ne répond pas, vérifiez d'abord que le débit est bien de 115200.
Code
Logique de reconnaissance principale
components/modules/ai/who_human_face_recognition.cpp — stratégie de reconnaissance avec saut de trames :
case RECOGNIZE:
{
// Saut de trames : 1 reconnaissance MFN toutes les 10 détections
static int recog_skip = 0;
if (recog_skip <= 0) {
recognize_result = recognizer->recognize(
(uint16_t *)frame->buf,
{(int)frame->height, (int)frame->width, 3},
detect_results.front().keypoint);
recog_skip = 10;
}
recog_skip--;
frame_show_state = SHOW_STATE_RECOGNIZE;
break;
}Dépannage
| Symptôme | Cause possible | Solution |
|---|---|---|
No face ID in flash | Normal, aucun visage enregistré | Envoyer face_eril pour enregistrer |
Le résultat est toujours who? | Éclairage insuffisant / angle défavorable / similarité sous le seuil | Réenregistrer, face à la caméra, éclairage uniforme |
| Aucune réaction à l'enregistrement | Nombre de visages à l'image ≠ 1 | S'assurer qu'il n'y a qu'un seul visage, à 30-50 cm |
| Image saccadée pendant la reconnaissance | Normal, l'inférence MFN prend du temps | Déjà optimisé par saut de trames, une exécution toutes les 10 trames |
| Étiquette clignotante | — | Corrigé, l'étiquette reste affichée en continu |
fail: unknown command | Faute d'orthographe dans la commande | Vérifier la commande : face_eril et non face_enroll |
Résultat
Enregistrer un visage → reconnaissance continue avec affichage de l'ID → sortie I2C/port série → commande de relais ou de servomoteur : une solution de contrôle d'accès complète.
Chapitre suivant : Chapitre 9 : Dialogue vocal

