.

FaceSort : classer localement des milliers de photos par reconnaissance faciale sur un Mac Apple Silicon

Ce guide explique comment mettre en place FaceSort, un outil Python qui reconnaît des personnes connues dans une grande collection de photos, puis classe les images correspondantes dans des dossiers portant leur nom.

Le traitement s’effectue entièrement sur le Mac. Les photographies et les empreintes faciales ne sont envoyées vers aucun service en ligne. Le projet présenté ici a été conçu et testé sur un Mac mini M4 équipé de 16 Go de mémoire, mais il peut fonctionner sur d’autres Mac Apple Silicon.

FaceSort sait notamment :

Important — vie privée et licence : une empreinte faciale est une donnée biométrique sensible. N’utilisez ce système qu’avec des images que vous êtes autorisé à traiter, conformément à la législation applicable. Les poids préentraînés LVFace et InsightFace/SCRFD peuvent être soumis à des restrictions d’usage, notamment non commercial. Vérifiez toujours les licences officielles avant toute diffusion ou exploitation.

1. Comprendre le fonctionnement

Le traitement comporte deux étapes distinctes :

  1. SCRFD détecte tous les visages présents dans une photographie et repère leurs points caractéristiques.
  2. LVFace-B transforme chaque visage aligné en un vecteur numérique, appelé ici empreinte faciale.

Pour chaque personne connue, FaceSort calcule l’empreinte de chacune de ses photos de référence, en fait la moyenne, puis normalise le résultat. Chaque visage trouvé dans Input est comparé à ces identités par similarité cosinus.

Une similarité supérieure ou égale à 0,45 est considérée comme une correspondance certaine dans notre configuration. Entre 0,30 et 0,45, le mode Audit propose l’image pour une vérification humaine. Ces seuils ne sont pas universels : ils doivent être validés avec vos propres photos.

2. Matériel et logiciels nécessaires

Configuration utilisée pour ce projet :

Dans le Terminal, vérifiez Python :

python3.11 --version

Si Python 3.11 n’est pas installé :

brew install python@3.11

Installez également ExifTool :

brew install exiftool

ExifTool n’est pas nécessaire à la reconnaissance elle-même. Sans lui, les photos seront classées, mais aucun nom ne sera inscrit dans leurs métadonnées.

3. Créer le dossier du projet

Le dossier peut être placé n’importe où sur le disque. Toutes les adresses utilisées par le programme sont calculées relativement à l’emplacement du script.

Créez cette structure :

FaceSort/
├── Models/
├── Model_weights/
├── Input/
├── Output/
├── Review/
├── FaceSort.py
├── FaceSort.command
├── FaceSort Audit.command
├── Installer.command
└── requirements.txt

Rôle de chaque élément :

4. Installer l’environnement Python

Le fichier requirements.txt contient :

numpy>=1.26,<3
onnxruntime>=1.20,<2
opencv-python-headless>=4.10,<5
insightface>=0.7.3,<0.8
Pillow>=10,<12
pillow-heif>=0.18,<2

Depuis le Terminal, placez-vous dans le dossier FaceSort :

cd "/chemin/vers/FaceSort"

Créez un environnement isolé et installez les dépendances :

python3.11 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -r requirements.txt

L’environnement .venv reste dans le dossier du projet. Il n’altère donc pas l’installation Python générale du Mac.

5. Télécharger les modèles

FaceSort attend exactement ces fichiers :

Model_weights/scrfd_10g.onnx
Model_weights/lvface_b.onnx

Détecteur SCRFD

SCRFD-10G est le détecteur de visages. Le projet et le catalogue officiels sont disponibles dans le dépôt InsightFace. Téléchargez le modèle ONNX SCRFD-10G comportant les cinq points caractéristiques, puis renommez-le scrfd_10g.onnx si nécessaire.

Reconnaissance LVFace-B

Téléchargez la version ONNX de LVFace-B entraînée sur Glint360K depuis le dépôt officiel LVFace de ByteDance ou sa page de modèles liée, puis placez-la sous le nom lvface_b.onnx.

LVFace-B a été choisi comme compromis entre précision, temps de calcul et mémoire sur une machine de 16 Go. Les modèles plus grands ne garantissent pas nécessairement un gain utile sur une photothèque réelle et peuvent ralentir sensiblement le traitement.

Ne téléchargez pas des poids depuis une source inconnue. Vérifiez le nom, la taille et, si l’éditeur en fournit une, la somme de contrôle du fichier.

6. Préparer les personnes connues

Créez un dossier par identité dans Models :

Models/
├── Personne_A/
│   ├── portrait_01.jpg
│   ├── portrait_02.jpg
│   └── portrait_03.jpg
└── Personne_B/
    ├── reference_01.jpg
    └── reference_02.jpg

Chaque photo de référence doit contenir exactement un visage détectable. Une image contenant zéro ou plusieurs visages est automatiquement rejetée lors de la construction de l’identité.

Pour obtenir une empreinte plus représentative :

FaceSort recalcule toutes les empreintes à chaque lancement. Toute nouvelle photo de référence est donc prise en compte immédiatement. Le fichier technique identity_cache.npz conserve le dernier calcul, mais n’est pas utilisé pour éviter cette reconstruction.

7. Ajouter les photographies à analyser

Copiez les images dans Input, avec autant de sous-dossiers que nécessaire :

Input/
├── Voyage_01/
│   ├── photo_001.jpg
│   └── photo_002.heic
└── Archives/
    └── 2019/
        └── groupe.png

Formats pris en charge : JPEG, PNG, HEIC et HEIF.

Il n’est pas obligatoire de déplacer une photothèque volumineuse. Input accepte :

Le parcours est récursif. Une protection empêche les boucles de liens et évite de traiter deux fois le même fichier réel, même s’il est accessible par plusieurs chemins.

8. Premier lancement

Activez l’environnement et lancez le programme :

cd "/chemin/vers/FaceSort"
source .venv/bin/activate
python FaceSort.py

Ou double-cliquez simplement sur FaceSort.command si ce lanceur accompagne le projet.

Au démarrage, le programme :

  1. charge SCRFD et LVFace-B ;
  2. relit toutes les références ;
  3. rejette les références ne contenant pas exactement un visage ;
  4. parcourt récursivement Input ;
  5. détecte tous les visages de chaque image ;
  6. compare chaque visage aux identités ;
  7. copie les correspondances certaines dans Output ;
  8. inscrit les métadonnées sur les copies.

Exemple de résultat :

Output/
├── Personne_A/
│   ├── photo_001.jpg
│   └── groupe.png
└── Personne_B/
    └── groupe.png

Si groupe.png contient les deux personnes, elle apparaît dans les deux dossiers. Une photo ne correspondant à aucune identité n’est ni copiée ni modifiée.

9. Les métadonnées ajoutées

FaceSort ajoute les identités reconnues dans trois champs largement exploitables par les logiciels de photothèque :

Seules les copies placées dans Output sont modifiées. Les fichiers d’origine restent strictement intacts.

Pour vérifier une copie :

exiftool -XMP-dc:Subject -IPTC:Keywords -EXIF:UserComment "Output/Personne_A/photo_001.jpg"

10. Utiliser le mode Audit

Le mode normal utilise un seuil de 0,45. Il privilégie les résultats fiables et ignore le reste. Pour rechercher les faux négatifs proches du seuil :

python FaceSort.py --audit

ou lancez FaceSort Audit.command.

Le comportement devient alors :

Le fichier Review/candidates.csv contient le chemin de la photo, l’identité proposée et son score. Il n’est finalisé qu’à la fin normale du traitement. Si le programme est interrompu, des images peuvent déjà être présentes dans Review, sans CSV complet.

Ne transformez pas automatiquement toutes les propositions d’Audit en références. Vérifiez-les humainement : une seule erreur introduite dans Models peut dégrader l’empreinte moyenne de l’identité.

11. Régler les seuils

Pour modifier le seuil principal :

python FaceSort.py --threshold 0.50

Un seuil plus élevé réduit généralement les faux positifs, mais peut manquer davantage de vrais visages. Un seuil plus bas retrouve plus de candidats, au prix d’erreurs possibles.

Une méthode prudente consiste à :

  1. commencer à 0,45 ;
  2. contrôler manuellement toutes les copies de Output ;
  3. lancer un Audit entre 0,30 et 0,45 ;
  4. noter les scores des vrais positifs et des erreurs ;
  5. ajuster le seuil sur ces observations, pas uniquement sur un benchmark public.

12. CPU, Core ML et performances sur M4

Trois moteurs sont proposés :

python FaceSort.py --backend hybrid
python FaceSort.py --backend cpu
python FaceSort.py --backend coreml

Le mode hybrid, utilisé par défaut, exécute SCRFD avec le fournisseur Core ML d’ONNX Runtime et LVFace-B sur CPU. Sur notre Mac mini M4, un essai de 200 photos a donné environ :

Le résultat peut sembler surprenant. Passer par le fournisseur Core ML d’ONNX Runtime ne signifie pas que toutes les opérations sont exécutées de façon optimale sur le Neural Engine. LVFace-B peut être découpé en plusieurs segments avec des transferts coûteux entre moteurs. Le mode hybride évitait ce surcoût.

Il ne s’agit donc pas encore d’une conversion Core ML native entièrement optimisée. Une étape future consisterait à convertir les modèles en paquet MLProgram FP16, à vérifier chaque opération, puis à comparer CPU, GPU et Neural Engine sur un jeu de test fixe.

13. Retour d’expérience sur une grande photothèque

Lors d’un traitement réel anonymisé comprenant trois identités :

Ce résultat montre surtout l’intérêt d’un seuil conservateur : FaceSort peut rechercher quelques apparitions au milieu de dizaines de milliers d’images sans envoyer la photothèque dans le cloud. Il ne prouve cependant pas l’absence de faux négatifs. C’est précisément le rôle du mode Audit.

14. Comprendre les avertissements d’images

Les photothèques anciennes contiennent souvent des fichiers imparfaits.

PNG portant une extension JPG

Si le contenu réel est PNG mais que le fichier se termine par .jpg, FaceSort détecte sa signature et donne à la copie l’extension .png. Même principe pour un JPEG mal nommé .png.

Métadonnées XMP dupliquées

ExifTool est lancé en mode tolérant pour écrire les tags malgré certaines anomalies mineures, telles qu’une propriété XMP dupliquée ou des attributs rdf:about incohérents.

Messages « Corrupt JPEG data » ou « Invalid SOS parameters »

Ces messages proviennent généralement de la bibliothèque de décodage JPEG. Si le traitement continue sans ligne ERREUR, l’image a pu être décodée et analysée. Si FaceSort affiche ERREUR, le fichier concerné est ignoré. Dans les deux cas, l’original n’est jamais réparé ni réécrit automatiquement.

15. Rendre le projet portable

FaceSort utilise comme racine le dossier contenant FaceSort.py. Pour transférer l’outil à un autre utilisateur :

  1. distribuez le dossier sans Input, Output, Review ni photos de Models ;
  2. évitez d’inclure .venv, qui doit être recréé sur l’autre Mac ;
  3. précisez séparément les licences des poids ONNX ;
  4. faites exécuter Installer.command sur la machine de destination ;
  5. demandez à l’utilisateur de créer ses propres identités et de calibrer ses seuils.

macOS peut demander une autorisation lors du premier accès à un dossier externe via un alias Finder. C’est normal : accordez uniquement l’accès aux dossiers que vous souhaitez analyser.

16. Limites et améliorations possibles

La version actuelle représente chaque personne par la moyenne normalisée de toutes ses références valides. C’est simple et efficace, mais une galerie plus robuste pourrait :

La priorité doit rester la qualité des références et la validation humaine. Ajouter davantage de portraits n’améliore pas forcément une identité si ces portraits sont mauvais, redondants ou incorrectement étiquetés.

Conclusion

FaceSort fournit une solution locale, portable et contrôlable pour rechercher des personnes connues dans plusieurs milliers de photos. L’association de SCRFD, LVFace-B, ONNX Runtime et ExifTool permet d’obtenir un classement pratique tout en laissant les originaux intacts.

Sur Apple Silicon, la leçon la plus utile est qu’il faut mesurer plutôt que supposer : dans notre cas, le partage du travail entre Core ML pour la détection et le CPU pour la reconnaissance était légèrement plus rapide que le tout-CPU et nettement préférable au tout-Core ML. La seconde leçon est tout aussi importante : aucun score automatique ne remplace une vérification humaine, en particulier lorsqu’il s’agit de données biométriques.

Sources du projet

· macOS, Apple Silicon, Python, Core ML, reconnaissance faciale, photographie