Aujourd’hui nous allons utiliser Dlib et OpenCV pour détecter les repères faciaux (facial landmarks) dans une image. Mais tout d’abord, qu’est-ce que c’est que des repères faciaux ?
L’analyse de visage a été étudié depuis longtemps par les ingénieurs et chercheurs en vision par ordinateur. L’application la plus évidente de l’analyse faciale est la reconnaissance de visage. La première étape dans la reconnaissance de visage est bien entendu la localisation de ce dernier. C’est ce que nous avions vu dans cet article.
Une fois que le visage est localisé, il est nécessaire de trouver des points caractéristiques du visage. Ces points vont être les coins des yeux, le nez, la bouche, les sourcils, …. Ces caractéristiques sont régulièrement appelées facial landmarks, que l’on peut traduire par repères faciaux.

Détecter des repères faciaux (facial landmarks)
La fonction développée par Dlib pour annoter un visage repose sur deux actions:
- Trouver le visage
- Extraire les points caractéristiques
Nous allons brièvement décrire ces deux étapes.
Trouver le visage
Contrairement ce que nous avons vu la dernière fois sur la détection de visage, la fonction implémentée par Dlib utilise le descripteur de HOG (Histogram of Oriented Gradient) pour rechercher les visages. Ce descripteur repose sur l’idée que l’apparence et la forme d’un objet peuvent être décrites par la distribution de l’intensité du gradient ou de l’orientation des contours.
Extraire les points caractéristiques
La méthode utilisée dans Dlib pour la détection des facial landmarks est une implémentation du papier de Kazemi et Sullivan(2014) : One Millisecond Face Alignment with an Ensemble of Regression Trees. Cette méthode consiste en l’apprentissage d’une cascade de régresseurs à partir d’un jeu de données. Les images du jeu de données sont annotés manuellement, en spécifiant les coordonnées (x,y) de chaque caractéristique. La méthode prend également en compte la distance probable entre deux paires de points.
La cascade de régresseur est entrainé à partir des données annotées afin d’estimer la position des points caractéristiques directement à partir de l’intensité des pixels.
Le détecteur utilisé par Dlib est utilisé pour détecter la localisation de 68 points qui représente la structure faciale d’un visage. Les données pour l’apprentissage proviennent du jeu de données iBUG 300-W.

Détecter les repères faciaux (facial landmarks) avec dlib
Maintenant le petit point méthode effectué, nous pouvons passer à la partie codée ! Commençons par créer un fichier facial_landmarks.py et rentrons dedans ce qui suit 🙂
Étape 1: Import des librairies
Nous commençons par importer les librairies nécessaires: OpenCV pour l’exploitation des images, Dlib pour la recherche des repères faciaux, numpy pour la manipulation des matrices et enfin argparse pour la prise en compte des arguments de notre programme.
import numpy as np import argparse import dlib import cv2
Étape 2: déclaration de fonctions d’affichages
Nous allons définir deux fonctions utilitaires afin de faciliter le traçage. Ces fonctions permettent de mettre en forme les données fournies par Dlib pour pouvoir être exploitée par les fonctions rectangle et cercle d’OpenCV.
La première fonction (draw_BB) permettra de tracer les rectangles encadrants autour des visages détectés. La seconde (draw_landmarks) pour dessiner les 68 repères faciaux sur les visages.
def draw_BB(rect,image): x = rect.left() y = rect.top() w = rect.right() - x h = rect.bottom() - y cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2) def draw_landmarks(landmarks,image): for i, part in enumerate(landmarks.parts()): px = int(part.x) py = int(part.y) cv2.circle(image, (px, py), 1, (0, 0, 255), -1)
Étape 3: chargement de l’image à traiter
Maintenant que nos fonctions sont définies, nous pouvons charger l’image à traiter. Pour ce faire, nous allons déterminer un argument d’entrée de notre fonction, afin de pouvoir spécifier le chemin de l’image à traiter:
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=False, help="chemin de l'image initiale")
args = vars(ap.parse_args())
path_img=args["image"]
image=cv2.imread(path_img)
image = cv2.resize(image,None,fx=1/2, fy=1/2, interpolation = cv2.INTER_CUBIC)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)Une fois le chemin récupéré, nous pouvons récupérer l’image, réduire sa taille et ensuite la convertir en niveau de gris pour les traitements qui suivent.
Étape 4: Initialisation du détecteur et du prédicteur
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat')La première ligne consiste à l’initialisation du détecteur de tête de dlib. La seconde liste permet d’initialiser le prédicteur. Nous fournissons en paramètre le détecteur de repères pré-entrainé. Vous pouvez trouver ce prédicteur ici
Mais avant de pouvoir détecter les points caractéristiques du visage, il est nécessaire de localiser le ou les visages présents dans l’image. Cette action est réalisée simplement grâce à la ligne suivante:
rects = detector(gray, 1)
Voilà nous avons détecté les visages présents dans l’image, nous pouvons donc passer à la recherche des facial landmarks.
Étape 5: détection des repères faciaux et affichage
for (i, rect) in enumerate(rects): draw_BB(rect,image) landmarks = predictor(gray, rect) draw_landmarks(landmarks,image)
Nous commençons donc par parcourir les différents visages détectés.
Pour chaque visage, nous utilisons le prédicteur pour obtenir les coordonnées de chaque repère facial. Nous fournissons au prédicteur l’image en niveau de gris, ainsi que la zone où se trouve le visage et nous récupérons en sortie les coordonnées des 68 points.
Il ne reste plus qu’à dessiner sur notre image les rectangles encadrants autour des visages, ainsi que les points que nous avons trouvés.
La dernière étape consistera en l’affichage de l’image modifiée:
cv2.imshow("Output", image)
cv2.waitKey(0)C’est fini ! nous pouvons passer au test de notre programme
Étape 5: Test du programme
python3 facial_landmarks -i Lena.png

python3 facial_landmarks.py -i bald_guys.jpg
Image provenant des exemples de Dlib, pouvant être téléchargée ici. J’ai modifié la taille des points tracés par la fonction draw_landmarks pour un souci de visibilité .

Dans cet article, nous avons vu une méthode pour calculer les points caractéristiques d’un visage. Ces points peuvent être utilisés pour calculer l’orientation d’un visage, de détecter un clignement d’oeil ou pour rajouter des masques sur un visage par exemple.