J'ai créé un programme qui détecte les visages à l'aide de la fonction Haar-Like Cascade fournie par OpenCV et les coupe automatiquement.
-Software- Windows 10 Home Anaconda3 64-bit(Python3.7) Spyder -Library- opencv-python 4.1.2.30 natsort 7.0.0 -Hardware- CPU: Intel core i9 9900K RAM: 16GB 3200MHz
** Livres ** Programmation OpenCV4 à partir de Python Naohiro Kitayama (Auteur) ([Page Amazon](https://www.amazon.co.jp/Python%E3%81%A7%E5%A7%8B%E3%82%81%E3%82%8BOpenCV-4%E3%83% 97% E3% 83% AD% E3% 82% B0% E3% 83% A9% E3% 83% 9F% E3% 83% B3% E3% 82% B0-% E5% 8C% 97% E5% B1% B1 -% E7% 9B% B4% E6% B4% 8B / dp / 4877834613))
Je le posterai sur Github.
https://github.com/himazin331/Face-Cropping Le référentiel contient le programme de traitement des données Haar-Cascade
Un fichier Cascade avec des fonctionnalités Haar-Like est nécessaire pour le fonctionnement de ce programme. Cette fois, nous utiliserons Haar-Cascade d'OpenCV. Cascade est inclus dans le référentiel, vous n'avez donc pas besoin de le préparer séparément.
** Veuillez noter que le code est sale ... **
face_cut.py
import cv2
import os
import argparse as arg
import sys
from natsort import natsorted
#Traitement d'image
def face_cut(imgs_dir, result_out, img_size, label, HAAR_FILE):
# Haar-Comme la lecture du classificateur de type cascade
cascade = cv2.CascadeClassifier(HAAR_FILE)
#Traitement de l'information
for img_name in natsorted(os.listdir(imgs_dir)):
print("données d'image:{}".format(img_name))
#format jpg uniquement
_, ext = os.path.splitext(img_name)
if ext.lower() == '.jpg':
img_path = os.path.join(imgs_dir, img_name) #Combiner les chemins de fichiers
img = cv2.imread(img_path) #Lecture des données
img_g = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY) #Convertir en échelle de gris
face = cascade.detectMultiScale(img_g) #Détecter le visage
#Si aucun visage n'est détecté
if len(face) == 0:
print("Face not found.")
else:
for x,y,w,h in face:
#Découpez le visage
face_cut = img_g[y:y+h, x:x+w]
#redimensionner
face_img = cv2.resize(face_cut, (img_size, img_size))
#sauvegarder
result_img_name = '\data' + str(label) + '.jpg'
cv2.imwrite(os.path.join(result_out + result_img_name), face_img)
label += 1
print("Processing success!!")
else:
print("Unsupported file extension")
def main():
#Créer des options de ligne de commande
parser = arg.ArgumentParser(description='Face image cropping')
parser.add_argument('--imgs_dir', '-d', type=str, default=None,
help='Chemin du dossier d'image(Erreur si non spécifié)')
parser.add_argument('--out', '-o', type=str,
default=os.path.dirname(os.path.abspath(__file__))+'/result_crop'.replace('/', os.sep),
help='Enregistrer la destination des données de post-traitement(Valeur par défaut=./reslut_crop)')
parser.add_argument('--img_size', '-s', type=int, default=32,
help='redimensionner(N pour NxN,Valeur par défaut=32)')
parser.add_argument('--label', '-l', type=int, default=1,
help='dataN.Valeur initiale de N en jpg(Valeur par défaut=1)')
parser.add_argument('--haar_file', '-c', type=str, default=os.path.dirname(os.path.abspath(__file__))+'/haar_cascade.xml'.replace('/', os.sep),
help='haar-Spécification du chemin en cascade(Valeur par défaut=./haar_cascade.xml)')
args = parser.parse_args()
#Lorsque le dossier d'image n'est pas spécifié->exception
if args.imgs_dir == None:
print("\nException: Cropping target is not specified.\n")
sys.exit()
#Lorsqu'un dossier d'images inexistant est spécifié->exception
if os.path.exists(args.imgs_dir) != True:
print("\nException: {} does not exist.\n".format(args.imgs_dir))
sys.exit()
#Lorsque Cascade qui n'existe pas est spécifié->exception
if os.path.exists(args.haar_file) != True:
print("\nException: {} does not exist.\n".format(args.haar_file))
sys.exit()
#Réglage de la sortie des informations
print("=== Setting information ===")
print("# Images folder: {}".format(os.path.abspath(args.imgs_dir)))
print("# Output folder: {}".format(args.out))
print("# Images size: {}".format(args.img_size))
print("# Start index: {}".format(args.label))
print("# Haar-cascade: {}".format(args.haar_file))
print("===========================\n")
#Créer un dossier de sortie(Ne pas créer si le dossier existe)
os.makedirs(args.out, exist_ok=True)
#En traitement
face_cut(args.imgs_dir, args.out, args.img_size, args.label, args.haar_file)
print("")
if __name__ == '__main__':
main()
Les images préparées sont les suivantes. Tatsuya Okawa.
** Si "Visage introuvable." Est émis, cela signifie que le visage n'a pas pu être détecté, en d'autres termes, il n'a pas pu être reconnu comme un visage **. Dans cet exemple, les deux derniers ne pouvaient pas être reconnus comme des faces.
Les deux ont des faces inclinées. Il n'y a pas de problème s'il est incliné dans une certaine mesure, mais il semble que cela ne sert à rien s'il est incliné à un angle comme l'image. Si vous voulez vraiment découper le visage, vous devez effectuer une conversion affine sur l'image.
Autre que ces deux, comme ça
Il a été mis à l'échelle des gris et seul le visage a été découpé et redimensionné. Peu importe si vous portez des lunettes. (Le port de lunettes de soleil et de masques peut être difficile ...)
commander
python face_cut.py -d <dossier d'image> (-o <destination> -s <redimensionner> -l <index> -c <cascade>)
La destination de sauvegarde des données d'image traitées est «. / Result_crop» par défaut.
La spécification Haar-cascade est par défaut . / Haar_cascade.xml
.
De plus, le redimensionnement est de 32x32px et l'index est 1 par défaut.
Utilisez la fonction face_cut pour en niveaux de gris, couper et redimensionner le visage.
Tout d'abord, chargez la cascade Haar utilisée pour détecter et découper le visage.
# Haar-Comme la lecture du classificateur de type cascade
cascade = cv2.CascadeClassifier(HAAR_FILE)
HAAR_FILE
est le chemin Haar-cascade spécifié par l'option de commande.
Le traitement ci-dessous charge l'image, la met en niveaux de gris et détecte le visage.
#Traitement de l'information
for img_name in natsorted(os.listdir(imgs_dir)):
print("données d'image:{}".format(img_name))
#format jpg uniquement
_, ext = os.path.splitext(img_name)
if ext.lower() == '.jpg':
img_path = os.path.join(imgs_dir, img_name) #Combiner les chemins de fichiers
img = cv2.imread(img_path) #Lecture des données
img_g = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY) #Convertir en échelle de gris
face = cascade.detectMultiScale(img_g) #Détecter le visage
Cette fois, seuls ** les fichiers JPEG sont ciblés **,
ʻSi ext.lower () == '. Jpg': to
'.png'ou
'. Bmp'`, vous pouvez traiter le fichier.
Convertissez une image RVB en image en niveaux de gris avec cv2.cvtColor ()
.
Après cela, cascade.detectMultiScale ()
est utilisé pour détecter le visage en utilisant Haar-cascade.
img_g = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY) #Convertir en échelle de gris
face = cascade.detectMultiScale(img_g) #Détecter le visage
cascade.detectMultiScale ()
renvoie ** les coordonnées x et y, la largeur et la hauteur de l'emplacement détecté ** lorsqu'un visage est détecté.
Si le visage n'est pas détecté, rien ne sera retourné.
#Si aucun visage n'est détecté
if len(face) == 0:
print("Face not found.")
else:
for x,y,w,h in face:
#Découpez le visage
face_cut = img_g[y:y+h, x:x+w]
#redimensionner
face_img = cv2.resize(face_cut, (img_size, img_size))
#sauvegarder
result_img_name = '\data' + str(label) + '.jpg'
cv2.imwrite(os.path.join(result_out + result_img_name), face_img)
label += 1
print("Processing success!!")
else:
print("Unsupported file extension")
Dans le processus ci-dessous, le visage est découpé en fonction des informations renvoyées.
#Découpez le visage
face_cut = img_g[y:y+h, x:x+w]
Cela ressemble à la figure ci-dessous. (C'est difficile à voir ...)
Après la coupe, redimensionner à la taille spécifiée avec cv2.resize ()
et enregistrer.
c'est tout. Je ne pense pas qu'il soit nécessaire d'expliquer la fonction principale, je vais donc l'omettre.
J'ai utilisé le scraping de données et ce programme pour collecter des données d'entraînement. À moins que vous ne soyez particulier à ce sujet, vous pouvez l'utiliser suffisamment.
Cependant, comme mentionné dans Résultat d'exécution Il y a des limites. Dans le cas du profil, Haar-cascade pour le profil est également inclus, vous pouvez donc l'utiliser. De plus, ** il y a des faux positifs, donc le nettoyage des données ** (élimination des images avec des coupes sans visage) ** est requis **
Recommended Posts