Analyse des émotions avec DeepFace à partir de votre webcam

A

Le script vous permettra de réaliser une analyse des émotions via le flux de votre webcam (en temps réel) de votre Mac ou PC, en utilisant la bibliothèque DeepFace, développée par Meta.
Cet article s’inscrit dans la continuité de mes (recherches) autour de l’analyse des émotions, initialement explorés avec le modèle FER. L’objectif est de faire un état des lieux de la question.
À ma grande surprise, j’ai découvert les paramètres de DeepFace, qui laissent entrevoir une orientation marquée vers le contrôle, la surveillance et la sécurité – des aspects qui peuvent susciter des interrogations sur les intentions dans l’utilisation de la reconnaissance faciale.

Pour entrer dans le vif du sujet, le modèle pré-entraîné permet, pour chaque visage détecté, de prédire et d’afficher des attributs comme l’âge, le genre (masculin ou féminin), l’ethnicité, et les émotions.
Cela peut sembler un peu étrange, voire inquiétant… Ces outils d’analyse de reconnaissance faciale soulèvent donc des questions sur leur utilité et leur usage, notamment dans des contextes de surveillance ou de profilage.

Précisions sur l’analyse des émotions avec DeepFace

Pour l’analyse des émotions, DeepFace utilise un modèle pré-entraîné spécialisé, distinct des (autres) modèles de reconnaissance faciale paramétrables comme VGG-Face ou Facenet. En plus de ces modèles, DeepFace offre plusieurs hyper-paramètres personnalisables, notamment le choix des backends de détection, permettant à l’utilisateur d’ajuster la précision et la vitesse selon ses besoins.

Les modèles disponibles et les plus populaires dans DeepFace sont VGG-Face, Facenet512, OpenFace, DeepID, ArcFace, Dlib, SFace…, tandis que les backends de détection incluent RetinaFace, MTCNN, SSD, OpenCV

Différents modèles paramétrables dans DeepFace

 

La sélection d’un modèle (comme VGG-Face, Facenet,) influence directement la performance en termes de précision et de temps de calcul.
Ce choix est essentiel pour des applications spécifiques, surtout si vous envisagez de fine-tuner DeepFace avec votre propre jeux de données.

DeepFace utilise par défaut un modèle spécialisé pour la détection d’émotions, indépendamment des autres modèles qu’il est possible de choisir pour optimiser la détection (comme VGG-Face, Facenet…,) il est donc dans ce cadre inutile de spécifier un (autre) modèle au risque engendrer un « bug »!
Le script fonctionnera mais la détection du visage ainsi que les scores d’émotions ne seront pas opérationnels.
Ainsi le paramètre "model_name" ne sert à rien dans notre utilisation car DeepFace applique automatiquement son modèle d’émotion dédié pour cette tâche.
Autrement dit, même si on spécifie model_name='VGG-Face' (par exemple) cela n’aura aucun effet sur l’analyse (vitesse / précision) des émotions.

# Utilisation de VGG-Face avec OpenCV pour analyser les émotions
  resultats = DeepFace.analyze(rgb_frame, actions=['emotion'], enforce_detection=False,
  model_name='VGG-Face', detector_backend='opencv')
Résultat de : model_name=’VGG-Face’

 

En revanche vous pourrez paramétrer le backend (detector_backend), qui sert à localiser les visages dans l’image avant l’analyse des émotions.

Les backend de détection de visage

Pour détecter la position des visages dans une image avant d’analyser les émotions, DeepFace utilise un backend de détection de visage. Dans le script j’utilise le backend « RetinaFace », car il est précis et bien adapté à la localisation des visages.
Cependant, d’autres options comme OpenCV, MTCNN,… peuvent être spécifiées pour adapter la vitesse et la précision en fonction des besoins.

Bien choisir le backend ?

Dans un prochain script, je vous présenterai une analyse comparative de la vitesse et de la précision des différents backends.
Le meilleur backend pour la détection de visages dans DeepFace dépend des priorités de votre application : précision, vitesse, ou équilibre des deux.
Dans le script j’utilise le backend « RetinaFace ».

# Analyse des émotions avec RetinaFace
resultats = DeepFace.analyze(rgb_frame, actions=['emotion'], enforce_detection=False, detector_backend='retinaface')

La précision de ce backend est très élevée, mais cela se fait au détriment de la vitesse, qui est modérée par rapport à d’autres backends.
Vous pouvez modifier la ligne de code ci-dessus pour tester différents backends, comme « opencv » ou « mtcn », qui offre une vitesse supérieure.

# Analyse des émotions avec MTCNN pour une meilleure précision
resultats = DeepFace.analyze(rgb_frame, actions=['emotion'], enforce_detection=False, detector_backend='mtcnn')

Pour améliorer la fluidité, j’ai également réduit la taille de la fenêtre d’affichage de la webcam.

# Réduire la résolution pour améliorer la fluidité
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 480)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 360)

Il faut l’admettre, le backend « RetinaFace » est assez exigeant en ressources machine… Préparez-vous à une montée en température de votre Mac !

La fréquence d’image de la webcam

Utiliser l’analyse et la détection à une fréquence de 25 fps offre un affichage des émotions très dynamique, et donc assez difficile à lire à l’écran.
Comme vu précédemment, il serait intéressant de moyenner le score des émotions chaque seconde. Dans notre cas, nous allons analyser toutes les trames, au risque de faire chauffer la machine !
Ne soyez pas surpris si vous observez un décalage entre l’image et le score de l’émotion, car l’affichage n’est pas hyper fluide, notamment en raison de l’utilisation du backend RetinaFace, qui est gourmand en ressources.
La situation idéale serait d’extraire et de stocker les images de la webcam dans une base de données pour effectuer des calculs approfondis et, peut-être, utiliser la « puissance » de DeepFace dans le cadre de comparaisons avant/après – par exemple, visioconférence (date) vs visioconférence (date).
C’est une idée à explorer dans le domaine de la santé mentale, avec des patients participants à un programme de thérapie comportementale et cognitive (TCC) par exemple.

La fréquence d’image (ou frame) de la webcam intégrée dans mon MacBook équipé de la puce M2 est de 30 images par seconde (30 fps).

# Obtenir et afficher la fréquence d'images de la webcam
  fps = cap.get(cv2.CAP_PROP_FPS)
  print(f"Fréquence d'images de la webcam : {fps} FPS")

De mon côté, le résultat est décevant… le script m’indique que ma webcam est limitée à 15 fps. Une contrainte imposée par DeepFace ?

Une conversion de la couleurs nécessaire

La conversion de l’image de BGR à RGB est nécessaire car DeepFace utilise des conventions de couleur différentes. Par exemple OpenCV capture les images dans un format BGR (Bleu, Vert, Rouge). En convertissant l’image de BGR à RGB avant de la passer au modèle, on garantit que les couleurs sont interprétées correctement, ce qui est essentiel pour la fiabilité des prédictions.

# Conversion de l'image de BGR à RGB
  rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

Le code source

Au préalable, vous devez installer les librairies suivantes :

pip install deepface opencv-python-headless numpy pandas matplotlib requests tf_keras

Lancez le script à partir de votre terminal de votre éditeur de code Python :

python main.py

Quitter le script ?
Il vous suffit de de cliquer sur le touche échappe ou « q » de votre Mac.

# Appuyer sur 'q' ou 'ESC' pour quitter la boucle 
key = cv2.waitKey(30) & 0xFF if key == ord('q') or key == 27: # 27 est le code pour la touche ESC break

L’intégralité du code source :

# pip install deepface opencv-python-headless numpy pandas matplotlib requests tf_keras

import cv2
from deepface import DeepFace


# Fonction principale pour la détection d'émotions en utilisant DeepFace
def detect_emotions_deepface():
    cap = cv2.VideoCapture(0)

    # Réduire la résolution pour améliorer la fluidité
    cap.set(cv2.CAP_PROP_FRAME_WIDTH, 480)
    cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 360)

    # Forcer la fréquence d'images à 25 FPS
    cap.set(cv2.CAP_PROP_FPS, 25)

    # Obtenir et afficher la fréquence d'images de la webcam
    fps = cap.get(cv2.CAP_PROP_FPS)
    print(f"Fréquence d'images de la webcam : {fps} FPS")

    if not cap.isOpened():
        print("Erreur : Impossible d'ouvrir la webcam.")
        return

    while True:
        ret, frame = cap.read()
        if not ret:
            print("Erreur : Impossible de lire une image depuis la webcam.")
            break

        # Effacer tous les anciens cadres verts en réinitialisant le cadre
        display_frame = frame.copy()

        # Conversion de l'image de BGR à RGB
        rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

        try:
            # Analyse des émotions avec MTCNN pour une meilleure précision
            resultats = DeepFace.analyze(rgb_frame, actions=['emotion'], enforce_detection=False,
                                         detector_backend='retinaface')

            # Afficher le dernier résultat d'émotion si disponible
            if isinstance(resultats, list):  # Plusieurs visages détectés
                for res in resultats:
                    x, y, w, h = res['region']['x'], res['region']['y'], res['region']['w'], res['region']['h']
                    emotion_dominante = res['dominant_emotion']
                    probabilite = res['emotion'][emotion_dominante]

                    # Dessiner un rectangle autour du visage et afficher l'émotion dominante
                    cv2.rectangle(display_frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
                    cv2.putText(display_frame, f"{emotion_dominante}: {probabilite:.2f}", (x, y - 10),
                                cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 255, 0), 2)

            else:  # Un seul visage détecté
                x, y, w, h = resultats['region']['x'], resultats['region']['y'], resultats['region']['w'], \
                resultats['region']['h']
                emotion_dominante = resultats['dominant_emotion']
                probabilite = resultats['emotion'][emotion_dominante]

                # Dessiner un rectangle autour du visage et afficher l'émotion dominante
                cv2.rectangle(display_frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
                cv2.putText(display_frame, f"{emotion_dominante}: {probabilite:.2f}", (x, y - 10),
                            cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 255, 0), 2)

        except Exception as e:
            print("Erreur d'analyse de DeepFace : ", str(e))

            # Afficher le flux vidéo avec les annotations
        cv2.imshow('Détection des émotions en temps réel', display_frame)

        # Appuyer sur 'q' ou 'ESC' pour quitter la boucle
        key = cv2.waitKey(30) & 0xFF
        if key == ord('q') or key == 27:  # 27 est le code pour la touche ESC
            break

        # Libérer les ressources et fermer les fenêtres
    cap.release()
    cv2.destroyAllWindows()


# Lancer la détection d'émotions
detect_emotions_deepface()

Et si vous préférez, le code source est également sur mon Github !

Réflexion(s)

Je pars d’une analyse technique de la reconnaissance faciale appliquée à l’analyse des émotions, pour en extraire une problématique sociale, ancrée dans la question de la surveillance, telle que Michel Foucault l’a conceptualisée.
En examinant comment cette technologie capte et interprète les expressions faciales, nous passons d’un simple outil d’identification émotionnelle à un mécanisme de contrôle plus insidieux, où chaque émotion devient un élément de surveillance potentielle.

La reconnaissance faciale, devient ainsi le support d’un « panoptique » moderne, une structure où la possibilité d’être observé constamment (pourrait) modifier nos comportements (par le biais de l’auto-censure).

Il apparaît que la captation et l’analyse des émotions par la vidéo surveillance, la visioconférence (par exemple) ne sont pas simplement une avancée technologique mais également un vecteur de transformation des rapports sociaux et de l’identité numérique (un « moi » numérique).

L’individu, une fois informé qu’il est soumis à une surveillance permanente, va inévitablement chercher à développer des stratégies d’évitement pour se soustraire à ce regard constant. Cette adaptation prendra (peut être) la forme de ce que l’on pourrait appeler un « moi numérique » : une identité parallèle, soigneusement construite et contrôlée, qui fonctionnerai comme un masque destiné à tromper les mécanismes de surveillance.

A propos de l'auteur

Stéphane Meurisse

Ajouter un commentaire

Stéphane Meurisse