[PYTHON] Coupons le visage de l'image

Aperçu

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.

environnement

-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

référence

** 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))

programme

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

supposition

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.

Code source

** 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()

Résultat d'exécution

Les images préparées sont les suivantes. Tatsuya Okawa. image.png

image.png

** 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. image.png

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 image.png

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.

La description

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 ...) image.png

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.

en conclusion

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

Coupons le visage de l'image
Cherchons à partir de la ligne
Supprimer le cadre de l'image
Devinons l'état de développement de la ville à partir de l'image satellite.
J'ai essayé de couper une image fixe de la vidéo
Détection de visage à partir de plusieurs fichiers image avec openCV, découpez et enregistrez
Télécharger des images à partir d'un fichier texte contenant l'URL
Appliquons la couleur de l'image de marque à la carte des couleurs de matplotlib!
J'ai essayé de détecter l'iris à partir de l'image de la caméra
Identifiez le nom de l'image de la fleur avec des keras (flux tenseur)
Texte extrait de l'image
Ajoutons-le à la variable d'environnement à partir de la commande ~
Je veux découper uniquement le visage d'une image de personne avec Python et l'enregistrer ~ Détection de visage et rognage avec face_recognition ~
Enregistrez la vidéo d'entrée du tableau de capture sous forme d'image
J'ai essayé de reconnaître le visage de la vidéo (OpenCV: version python)
Point selon l'image
Faisons tourner l'air gacha
J'ai tweeté depuis le terminal!
Couper le graphe de calcul PyTorch
Décrivez le visage avec Dlib (1)
L'image est Namekuji
Recherche par image de la pellicule en utilisant Pythonista3
Touchons l'API Vision de Google de Python pour le moment