La dernière fois nous avons vu comment installer Dlib pour l’utilisation avec Python. 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.

Facial landmarks
Repères faciaux (source)

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.

Landmarks 68 points
Position des 68 points (source)

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 cv2
import dlib
import numpy as np
import argparse

É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)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

Une fois le chemin récupéré, nous pouvons récupérer l’image 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):
  landmarks = predictor(gray, rect)
  draw_BB(rect,image)
  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
facial landmarks Lena
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é .

Facial landmarks Bald_guys

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.


0 commentaire

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.