Comment détecter et extraire des visages d’une image avec OpenCV et Python

L’auteur a sélectionné le Open Internet / Free Speech Fund pour recevoir un don dans le cadre du https://do.co/w4do-cta Programme [Write for DOnations] .

introduction

Les images constituent une grande quantité de données générées chaque jour, ce qui rend la capacité de traitement de ces images importante. Une méthode de traitement des images est via face detection. La détection des visages est une branche du traitement d’images qui utilise l’apprentissage automatique pour détecter les visages dans les images.

Une Haar Cascade est une méthode de détection d’objet utilisée pour localiser un objet d’intérêt dans les images. L’algorithme est entraîné sur un grand nombre d’échantillons positifs et négatifs, les échantillons positifs étant des images contenant l’objet qui nous intéresse. Les échantillons négatifs sont des images pouvant contenir autre chose que l’objet souhaité. Une fois formé, le classificateur peut ensuite localiser l’objet d’intérêt dans de nouvelles images.

Dans ce tutoriel, vous utiliserez un modèle pré-formé Haar Cascade de OpenCV et https: //www.python.org/[Python] pour détecter et extraire les visages d’une image. OpenCV est une bibliothèque de programmation open-source utilisée pour traiter des images.

Conditions préalables

Étape 1 - Configuration de l’environnement local

Avant de commencer à écrire votre code, vous allez d’abord créer un espace de travail contenant le code et installer quelques dépendances.

Créez un répertoire pour le projet avec la commande + mkdir +:

mkdir

Accédez au répertoire nouvellement créé:

cd

Ensuite, vous allez créer un environnement virtuel pour ce projet. Les environnements virtuels isolent différents projets de sorte que les différentes dépendances ne causent aucune interruption. Créez un environnement virtuel nommé + face_scrapper + à utiliser avec ce projet:

python3 -m venv

Activer l’environnement isolé:

source /bin/activate

Vous verrez maintenant que votre invite est préfixée du nom de votre environnement virtuel:

Maintenant que vous avez activé votre environnement virtuel, vous utiliserez + nano + ou votre éditeur de texte favori pour créer un fichier + Requirements.txt +. Ce fichier indique les dépendances Python nécessaires:

nano requirements.txt

Ensuite, vous devez installer trois dépendances pour compléter ce tutoriel:

  • + numpy +: numpy est une bibliothèque Python qui ajoute la prise en charge de grands tableaux multidimensionnels. Il comprend également une vaste collection de fonctions mathématiques à utiliser sur les tableaux.

  • + opencv-utils +: C’est la bibliothèque étendue pour OpenCV qui inclut des fonctions d’assistance.

  • + opencv-python +: C’est le module OpenCV principal utilisé par Python.

Ajoutez les dépendances suivantes au fichier:

conditions.txt

numpy
opencv-utils
opencv-python

Enregistrez et fermez le fichier.

Installez les dépendances en passant le fichier + Requirements.txt + au gestionnaire de paquets Python, + pip +. L’indicateur + -r + spécifie l’emplacement du fichier + Requirements.txt +.

pip install -r requirements.txt

Dans cette étape, vous configurez un environnement virtuel pour votre projet et avez installé les dépendances nécessaires. Vous êtes maintenant prêt à écrire le code pour détecter les visages à partir d’une image d’entrée à l’étape suivante.

Étape 2 - Écriture et exécution du script du détecteur de visage

Dans cette section, vous allez écrire du code qui prendra une image en entrée et renverra deux choses:

  • Le nombre de visages trouvés dans l’image d’entrée.

  • Une nouvelle image avec un tracé rectangulaire autour de chaque visage détecté.

Commencez par créer un nouveau fichier pour contenir votre code:

nano app.py

Dans ce nouveau fichier, commencez à écrire votre code en important d’abord les bibliothèques nécessaires. Vous allez importer deux modules ici: + cv2 + et + sys +. Le module + cv2 + importe la bibliothèque + OpenCV + dans le programme, et + sys + importe les fonctions Python courantes, telles que + argv +, que votre code utilisera.

app.py

import cv2
import sys

Ensuite, vous spécifierez que l’image d’entrée sera transmise au script lors de l’exécution. Pour lire le premier argument, Pythonic attribue la valeur renvoyée par la fonction + sys.argv [1] + à une variable:

app.py

...
imagePath = sys.argv[1]

Une pratique courante en traitement d’image consiste à convertir d’abord l’image d’entrée en échelle de gris. En effet, la détection de la luminance, par opposition à la couleur, donnera généralement de meilleurs résultats en matière de détection d’objet. Ajoutez le code suivant pour prendre une image d’entrée en argument et la convertir en niveaux de gris:

app.py

...
image = cv2.imread(imagePath)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

La fonction + .imread () + prend l’image d’entrée qui est transmise en tant qu’argument au script et la convertit en objet OpenCV. Ensuite, la fonction + .cvtColor () + d’OpenCV convertit l’objet image en entrée en objet en niveaux de gris.

Maintenant que vous avez ajouté le code pour charger une image, vous allez ajouter le code qui détecte les visages dans l’image spécifiée:

app.py

...
faceCascade = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_frontalface_default.xml")
faces = faceCascade.detectMultiScale(
       gray,
       scaleFactor=1.3,
       minNeighbors=3,
       minSize=(30, 30)
)

print("Found {0} Faces!".format(len(faces)))

Ce code créera un objet + faceCascade + qui chargera le fichier Haar Cascade avec la méthode + cv2.CascadeClassifier +. Cela permet à Python et à votre code d’utiliser la cascade de Haar.

Ensuite, le code applique la méthode + .detectMultiScale () + d’OpenCV sur l’objet + faceCascade +. Cela génère une liste de rectangles pour tous les visages détectés dans l’image. La liste des rectangles est une collection d’emplacements de pixels de l’image, sous la forme + Rect (x, y, w, h) +.

Voici un résumé des autres paramètres utilisés par votre code:

  • + gray +: Ceci spécifie l’utilisation de l’objet image OpenCV en niveaux de gris que vous avez chargé précédemment.

  • + scaleFactor +: Ce paramètre spécifie le taux de réduction de la taille de l’image à chaque échelle. Votre modèle a une échelle fixe pendant la formation. Vous pouvez donc réduire les images d’entrée pour une meilleure détection. Ce processus s’arrête après avoir atteint un seuil défini par + maxSize + et + minSize +.

  • + minNeighbors +: Ce paramètre spécifie le nombre de voisins ou de détections que chaque rectangle candidat devrait avoir à le conserver. Une valeur plus élevée peut entraîner moins de faux positifs, mais une valeur trop élevée peut éliminer les vrais positifs.

  • + minSize +: Ceci vous permet de définir la taille d’objet minimale possible mesurée en pixels. Les objets plus petits que ce paramètre sont ignorés.

Après avoir généré une liste de rectangles, les faces sont comptées avec la fonction + len +. Le nombre de visages détectés est ensuite renvoyé en sortie après l’exécution du script.

Ensuite, vous utiliserez la méthode + .rectangle () + de OpenCV pour dessiner un rectangle autour des visages détectés:

app.py

...
for (x, y, w, h) in faces:
   cv2.rectangle(image, (x, y), (x+w, y+h), (0, 255, 0), 2)

Ce code utilise un for loop pour parcourir la liste des emplacements de pixels renvoyés par la méthode + faceCascade.detectMultiScale + pour chaque objet détecté. La méthode + rectangle + prendra quatre arguments:

  • + image + indique au code de dessiner des rectangles sur l’image d’origine.

  • + (x, y), (x + w, y + h) + sont les quatre emplacements de pixel pour l’objet détecté. + rectangle + les utilisera pour localiser et dessiner des rectangles autour des objets détectés dans l’image d’entrée.

  • + (0, 255, 0) + est la couleur de la forme. Cet argument est transmis en tant que tuple pour BGR. Par exemple, vous utiliseriez + (255, 0, 0) + pour le bleu. Nous utilisons le vert dans ce cas.

  • + 2 + est l’épaisseur de la ligne mesurée en pixels.

Maintenant que vous avez ajouté le code pour dessiner les rectangles, utilisez la méthode + .imwrite () + d’OpenCV pour écrire la nouvelle image sur votre système de fichiers local en tant que + faces_detected.jpg +. Cette méthode retournera + true + si l’écriture a réussi et + false + s’il n’a pas été possible d’écrire la nouvelle image.

app.py

...
status = cv2.imwrite('faces_detected.jpg', image)

Enfin, ajoutez ce code pour imprimer le retour à la console du statut + true + ou + false + de la fonction + .imwrite () +. Cela vous permettra de savoir si l’écriture a réussi après l’exécution du script.

app.py

...
print ("Image faces_detected.jpg written to filesystem: ",status)

Le fichier complet ressemblera à ceci:

app.py

import cv2
import sys

imagePath = sys.argv[1]

image = cv2.imread(imagePath)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

faceCascade = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_frontalface_default.xml")
faces = faceCascade.detectMultiScale(
   gray,
   scaleFactor=1.3,
   minNeighbors=3,
   minSize=(30, 30)
)

print("[INFO] Found {0} Faces!".format(len(faces)))

for (x, y, w, h) in faces:
   cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)

status = cv2.imwrite('faces_detected.jpg', image)
print("[INFO] Image faces_detected.jpg written to filesystem: ", status)

Une fois que vous avez vérifié que tout est entré correctement, enregistrez et fermez le fichier.

Votre code est complet et vous êtes prêt à exécuter le script.

Étape 3 - Exécution du script

Dans cette étape, vous utiliserez une image pour tester votre script. Lorsque vous trouvez une image à tester, enregistrez-la dans le même répertoire que votre script + app.py +. Ce tutoriel utilisera l’image suivante:

image: https: //assets.digitalocean.com/articles/CART-63965/people_with_phones.png [Image d’entrée de quatre personnes regardant des téléphones]

Si vous souhaitez tester avec la même image, utilisez la commande suivante pour la télécharger:

curl -O https://assets.digitalocean.com/articles/CART-63965/people_with_phones.png

Une fois que vous avez une image pour tester le script, exécutez-le et indiquez le chemin de l’image en tant qu’argument:

python app.py

Une fois le script exécuté, vous recevrez une sortie comme ceci:

Output[INFO] Found 4 Faces!
[INFO] Image faces_detected.jpg written to filesystem:

La sortie + true + vous indique que l’image mise à jour a été écrite avec succès sur le système de fichiers. Ouvrez l’image sur votre ordinateur local pour voir les modifications apportées au nouveau fichier:

image: https: //assets.digitalocean.com/articles/CART-63965/people_with_phones_detection.png [Image de sortie avec des visages détectés]

Vous devriez voir que votre script a détecté quatre visages dans l’image d’entrée et dessiné des rectangles pour les marquer. Dans l’étape suivante, vous utiliserez les emplacements de pixels pour extraire les visages de l’image.

Étape 4 - Extraire des faces et les enregistrer localement (facultatif)

Dans l’étape précédente, vous avez écrit du code pour utiliser OpenCV et une cascade de Haar afin de détecter et de dessiner des rectangles autour des visages d’une image. Dans cette section, vous allez modifier votre code pour extraire les visages détectés de l’image dans leurs propres fichiers.

Commencez par rouvrir le fichier + app.py + avec votre éditeur de texte:

nano app.py

Ensuite, ajoutez les lignes en surbrillance sous la ligne + cv2.rectangle +:

app.py

...
for (x, y, w, h) in faces:
   cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)



...

L’objet + roi_color + trace les emplacements des pixels de la liste + faces + sur l’image d’entrée d’origine. Les variables + x +, '+ y + ,' + h + et + w + sont les emplacements des pixels pour chacun des objets détectés à l’aide de la méthode + faceCascade.detectMultiScale +. Le code imprime ensuite la sortie en indiquant qu’un objet a été trouvé et sera enregistré localement.

Une fois que cela est fait, le code enregistre le tracé en tant que nouvelle image à l’aide de la méthode + cv2.imwrite +. Il ajoute la largeur et la hauteur du tracé au nom de l’image sur laquelle vous écrivez. Le nom restera unique si plusieurs visages sont détectés.

Le script + app.py + mis à jour ressemblera à ceci:

app.py

import cv2
import sys

imagePath = sys.argv[1]

image = cv2.imread(imagePath)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

faceCascade = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_frontalface_default.xml")
faces = faceCascade.detectMultiScale(
   gray,
   scaleFactor=1.3,
   minNeighbors=3,
   minSize=(30, 30)
)

print("[INFO] Found {0} Faces.".format(len(faces)))

for (x, y, w, h) in faces:
   cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
   roi_color = image[y:y + h, x:x + w]
   print("[INFO] Object found. Saving locally.")
   cv2.imwrite(str(w) + str(h) + '_faces.jpg', roi_color)

status = cv2.imwrite('faces_detected.jpg', image)
print("[INFO] Image faces_detected.jpg written to filesystem: ", status)

Pour résumer, le code mis à jour utilise les emplacements de pixels pour extraire les faces de l’image dans un nouveau fichier. Une fois que vous avez terminé la mise à jour du code, enregistrez et fermez le fichier.

Maintenant que vous avez mis à jour le code, vous êtes prêt à exécuter le script une nouvelle fois:

python app.py

Vous verrez une sortie similaire une fois que votre script aura fini de traiter l’image:

Output[INFO] Found 4 Faces.
[INFO] Object found. Saving locally.
[INFO] Object found. Saving locally.
[INFO] Object found. Saving locally.
[INFO] Object found. Saving locally.
[INFO] Image faces_detected.jpg written to file-system:

Selon le nombre de visages contenus dans votre exemple d’image, vous pouvez voir plus ou moins de résultats.

Si vous examinez le contenu du répertoire de travail après l’exécution du script, vous verrez des fichiers pour les portraits de tous les visages trouvés dans l’image d’entrée.

image: https: //assets.digitalocean.com/articles/CART-63965/directory.png [Liste du répertoire]

Vous verrez maintenant des images de tête extraites de l’image d’entrée collectée dans le répertoire de travail:

image: https: //assets.digitalocean.com/articles/CART-63965/extreated_faces.png [Visages extraits]

Dans cette étape, vous avez modifié votre script pour extraire les objets détectés de l’image d’entrée et les enregistrer localement.

Conclusion

Dans ce didacticiel, vous avez écrit un script utilisant OpenCV et Python pour détecter, compter et extraire les visages à partir d’une image d’entrée. Vous pouvez mettre à jour ce script pour détecter différents objets en utilisant un Haar Cascade pré-entraîné de la bibliothèque OpenCV, ou vous pouvez apprendre comment https://docs.opencv.org/3.3.0/dc/d88/tutorial_traincascade.html [forme toi-même] Haar Cascade.