[PYTHON] Maintenant, essayons la reconnaissance faciale avec Chainer (phase de prédiction)

Aperçu

C'est une suite de Essayons la reconnaissance faciale avec Chainer (phase d'apprentissage), et cette fois c'est la phase de prédiction.

Essayons la reconnaissance faciale à l'aide d'une webcam connectée par USB.

environnement

-Software- Windows 10 Home Anaconda3 64-bit(Python3.7) Spyder -Library- Chainer 7.0.0 opencv-python 4.1.2.30 -Hardware- CPU: Intel core i9 9900K GPU: NVIDIA GeForce RTX2080ti RAM: 16GB 3200MHz (Il peut être exécuté même sur un PC si vous avez une webcam)

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)) site Référence de l'API Chainer

programme

Pour le moment, je le posterai sur Github. https://github.com/himazin331/Face-Recognition-Chainer- Le référentiel contient une phase d'apprentissage, une phase de prédiction, un programme de traitement de données et Haar-Cascade.

supposition

Un fichier Cascade avec des fonctionnalités Haar-Like est requis 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_recog_CH.py


from PIL import Image
import numpy as np
import cv2

import sys
import os
import argparse as arg

import chainer
import chainer.links as L
import chainer.functions as F
import chainer.serializers as S
  
# ==================================== face_recog_train_CH.Même configuration réseau que py====================================
class CNN(chainer.Chain):
    def __init__(self, n_out):
        super(CNN, self).__init__(
            conv1=L.Convolution2D(1, 16, 5, 1, 0),  
            conv2=L.Convolution2D(16, 32, 5, 1, 0),  
            conv3=L.Convolution2D(32, 64, 5, 1, 0),  
            link=L.Linear(None, 1024),  
            link_class=L.Linear(None, n_out),  
        )
    def __call__(self, x):
        h1 = F.max_pooling_2d(F.relu(self.conv1(x)), ksize=2)
        h2 = F.max_pooling_2d(F.relu(self.conv2(h1)), ksize=2)
        h3 = F.relu(self.conv3(h2))
        h4 = F.relu(self.link(h3))
        return self.link_class(h4)
# ================================================================================================================

def main():

    #Arguments facultatifs de la ligne de commande
    parser = arg.ArgumentParser(description='Face Recognition Program(Chainer)')
    parser.add_argument('--param', '-p', type=str, default=None,
                        help='Spécification des paramètres appris(Erreur si non spécifié)')
    parser.add_argument('--cascade', '-c', type=str, default=os.path.dirname(os.path.abspath(__file__))+'/haar_cascade.xml'.replace('/', os.sep),
                        help='Haar-spécification de cascade(Valeur par défaut=./haar_cascade.xml)')
    parser.add_argument('--device', '-d', type=int, default=0,
                        help='Spécification de l'ID de l'appareil photo(Valeur par défaut=0)')
    args = parser.parse_args()

    #Lorsque le fichier de paramètres n'est pas spécifié->exception
    if args.param == None:
        print("\nException: Trained Parameter-File not specified.\n")
        sys.exit()
    #Lorsqu'un fichier de paramètres inexistant est spécifié->exception
    if os.path.exists(args.param) != True:
        print("\nException: Trained Parameter-File {} is not found.\n".format(args.param))
        sys.exit()
    #Haar qui n'existe pas-Quand la cascade est spécifiée->exception
    if os.path.exists(args.cascade) != True:
        print("\nException: Haar-cascade {} is not found.\n".format(args.cascade))
        sys.exit()

    #Réglage de la sortie des informations
    print("=== Setting information ===")
    print("# Trained Prameter-File: {}".format(os.path.abspath(args.param)))
    print("# Haar-cascade: {}".format(args.cascade))
    print("# Camera device: {}".format(args.device))
    print("===========================")

    #Génération d'instances de caméra
    cap = cv2.VideoCapture(args.device)
    #Réglage de la valeur FPS
    cap.set(cv2.CAP_PROP_FPS, 60)
    
    #Ensemble de détecteurs de visage
    detector = cv2.CascadeClassifier(args.cascade)

    #Chargement des paramètres appris
    model = L.Classifier(CNN(2))
    S.load_npz(args.param, model)

    red = (0, 0, 255)
    green = (0, 255, 0)
    p = (10, 30)
    
    while True:

        #Obtenir le cadre
        _, frame = cap.read()

        #Reconnaissance de la caméra impossible->exception
        if _ == False:
            print("\nException: Camera read failure.\n".format(args.param))
            sys.exit()

        #Détection facial
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        faces = detector.detectMultiScale(gray)
 
        #Visage non détecté->continue
        if len(faces) == 0:

            cv2.putText(frame, "face is not found",
                    p, cv2.FONT_HERSHEY_SIMPLEX, 1.0, red, thickness=2)
            cv2.imshow("frame", frame)
            
            if cv2.waitKey(1) & 0xFF == ord('q'):
                break

            continue
        
        #Quand le visage est détecté
        for (x, y, h, w) in faces:
            
            #Affichage de la zone du visage
            cv2.rectangle(frame, (x, y), (x+w, y+h), red, thickness=2) 
            
            #À travers si le visage est trop petit
            if h < 50 and w < 50:
                cv2.putText(frame, "detected face is too small",
                    p, cv2.FONT_HERSHEY_SIMPLEX, 1.0, red, thickness=2)
                cv2.imshow("frame", frame)
                break
                
            #Afficher le visage détecté
            cv2.imshow("gray", cv2.resize(gray[y:y + h, x:x + w], (250, 250)))
                    
            #Traitement d'image
            face = gray[y:y + h, x:x + w]
            face = Image.fromarray(face)
            face = np.asarray(face.resize((32, 32)), dtype=np.float32)
            recog_img = face[np.newaxis, :, :]
                    
            #Identification du visage
            y = model.predictor(chainer.Variable(np.array([recog_img])))
            c = F.softmax(y).data.argmax()
            
            if c == 0:
                cv2.putText(frame, "Unknown",
                    p, cv2.FONT_HERSHEY_SIMPLEX, 1.0, green, thickness=2)     
            elif c == 1:
                cv2.putText(frame, "Kohayakawa",
                    p, cv2.FONT_HERSHEY_SIMPLEX, 1.0, green, thickness=2)    
                
            cv2.imshow("frame", frame)

        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
  
    
    #Libération des ressources
    cap.release()
    cv2.destroyAllWindows()

if __name__ == "__main__":
    main()

Résultat d'exécution

Cette fois, j'ai essayé d'identifier Shinzo Abe et Taro Aso. Le nombre de données d'entraînement est de 100 pour les deux. abe.png aso.png

commander

python face_recog_CH.py -p <fichier de paramètres> -c <cascade> (-d <ID appareil photo>)

La description

Puisqu'il s'agit de la phase de prédiction, c'est un programme qui identifie le visage à l'aide d'une caméra.

Modèle de réseau

Classe CNN, mais exactement la même que le modèle de réseau de la phase d'apprentissage (face_recog_train_CH.py) Veuillez décrire tel quel. Cela ne fonctionnera pas si la structure est légèrement différente. Différents hyperparamètres et couches ont différents nombres de paramètres tels que des poids, donc des paramètres optimisés pour l'apprentissage. Ne peut pas être appliqué.

Classe CNN


# ==================================== face_recog_train_CH.Même configuration réseau que py====================================
class CNN(chainer.Chain):
    def __init__(self, n_out):
        super(CNN, self).__init__(
            conv1=L.Convolution2D(1, 16, 5, 1, 0),  
            conv2=L.Convolution2D(16, 32, 5, 1, 0),  
            conv3=L.Convolution2D(32, 64, 5, 1, 0),  
            link=L.Linear(None, 1024),  
            link_class=L.Linear(None, n_out),  
        )
    def __call__(self, x):
        h1 = F.max_pooling_2d(F.relu(self.conv1(x)), ksize=2)
        h2 = F.max_pooling_2d(F.relu(self.conv2(h1)), ksize=2)
        h3 = F.relu(self.conv3(h2))
        h4 = F.relu(self.link(h3))
        return self.link_class(h4)
# ================================================================================================================

installer

Il crée une instance de caméra, charge une cascade et importe des paramètres.

    #Génération d'instances de caméra
    cap = cv2.VideoCapture(args.device)
    #Réglage de la valeur FPS
    cap.set(cv2.CAP_PROP_FPS, 60)
    
    #Ensemble de détecteurs de visage
    detector = cv2.CascadeClassifier(args.cascade)

Appliquez des paramètres au modèle de réseau avec chainer.serializers.load_npz (). Notez que dans la phase d'apprentissage j'ai enveloppé le modèle avec L.Classifier () et créé une instance, Vous devez également envelopper le modèle dans L.Classifier () dans la phase de prédiction.

    #Chargement des paramètres appris
    model = L.Classifier(CNN(2))
    S.load_npz(args.param, model)

Reconnaissance de visage

Tout d'abord, prenez une photo avec l'appareil photo. Vous pouvez tirer avec cap.read (). Si vous exécutez cap.read () une fois, vous obtiendrez une image fixe. Utilisez l'instruction while et l'instruction for pour exécuter cap.read () séquentiellement, et sortez les images fixes obtenues en continu pour donner l'impression qu'elles sont en mouvement.

cap.read () renvoie deux valeurs. Le premier est un drapeau (_ dans le code) indiquant si la prise de vue est possible ou non. La deuxième image fixe réellement prise («frame» dans le code).

Ci-après, l'image fixe est appelée cadre.

    while True:

        #Obtenir le cadre
        _, frame = cap.read()

        #Reconnaissance de la caméra impossible->exception
        if _ == False:
            print("\nException: Camera read failure.\n".format(args.param))
            sys.exit()

        #Détection facial
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        faces = detector.detectMultiScale(gray)
 
        #Visage non détecté->continue
        if len(faces) == 0:

            cv2.putText(frame, "face is not found",
                    p, cv2.FONT_HERSHEY_SIMPLEX, 1.0, red, thickness=2)
            cv2.imshow("frame", frame)
            
            if cv2.waitKey(1) & 0xFF == ord('q'):
                break

            continue

Après l'acquisition du cadre, le cadre est mis en échelle de gris et la détection des visages est effectuée à l'aide de Cascade, qui est une fonction de type Haar. detect.MultiScale () renvoie les informations de position de détection (coordonnées et hauteur de largeur) lorsqu'un visage est détecté, et s'il ne peut pas être détecté, Je ne retournerai rien.

Lorsqu'un visage ne peut pas être détecté, «le visage est introuvable» s'affiche dans la fenêtre et continue.


J'expliquerai le traitement lorsqu'un visage est détecté.

Le traitement d'image est effectué en utilisant les coordonnées x et y, la largeur et la hauteur de l'emplacement de détection renvoyé.

        #Quand le visage est détecté
        for (x, y, h, w) in faces:
            
            #Affichage de la zone du visage
            cv2.rectangle(frame, (x, y), (x+w, y+h), red, thickness=2) 
            
            #À travers si le visage est trop petit
            if h < 50 and w < 50:
                cv2.putText(frame, "detected face is too small",
                    p, cv2.FONT_HERSHEY_SIMPLEX, 1.0, red, thickness=2)
                cv2.imshow("frame", frame)
                break
                
            #Afficher le visage détecté
            cv2.imshow("gray", cv2.resize(gray[y:y + h, x:x + w], (250, 250)))
                    
            #Traitement d'image
            face = gray[y:y + h, x:x + w]
            face = Image.fromarray(face)
            face = np.asarray(face.resize((32, 32)), dtype=np.float32)
            recog_img = face[np.newaxis, :, :]
                    
            #Identification du visage
            y = model.predictor(chainer.Variable(np.array([recog_img])))
            c = F.softmax(y).data.argmax()
            
            if c == 0:
                cv2.putText(frame, "Abe Sinzo",
                    p, cv2.FONT_HERSHEY_SIMPLEX, 1.0, green, thickness=2)     
            elif c == 1:
                cv2.putText(frame, "Aso Taro",
                    p, cv2.FONT_HERSHEY_SIMPLEX, 1.0, green, thickness=2)    
                
            cv2.imshow("frame", frame)

        if cv2.waitKey(1) & 0xFF == ord('q'):
            break

Le traitement d'image est concret ① Découpez la zone du visage du cadre ② Convertissez une fois de tableau en image pour redimensionner la zone du visage ③ Redimensionner à 32px x 32px ④ Ajouter la dimension du tableau (addition du nombre de canaux, [nombre de canaux, hauteur, largeur]) Je fais.

Maintenant, si nous pouvons traiter les données sous une forme identifiable, il est enfin temps de reconnaître le visage. y = model.predictor(chainer.Variable(np.array([recog_img]))) Commencez la prédiction avec. chainer.Variable () est une fonction qui associe des données à une règle de chaîne. Ensuite, passez le résultat de la prédiction via la fonction softmax avec c = F.softmax (y) .data.argmax (), puis avec argmax Le plus grand élément (index) est renvoyé.

Et enfin, à l'aide de l'instruction if, le nom de classe correspondant à l'élément (index) est affiché.

Cette fois, il y a deux classes, Shinzo Abe et Taro Aso, mais apprenons un visage qui n'est ni l'un ni l'autre. Lorsque vous entrez un visage qui n'est ni Shinzo Abe ni Taro Aso, il est possible de sortir quelque chose comme "ni".

en conclusion

À l'origine, ces programmes ont été développés dans le cadre de la recherche sur les affectations au lycée (recherche de fin d'études), le code est donc approprié. Vous pouvez facilement modifier le nombre de classes à classer tant que vous disposez de données d'apprentissage, alors faites ce que vous voulez.

Recommended Posts

Maintenant, essayons la reconnaissance faciale avec Chainer (phase de prédiction)
Maintenant, essayons la reconnaissance faciale avec Chainer (phase d'apprentissage)
Essayez la reconnaissance faciale avec Python
Essayez de prédire les courses de chevaux avec Chainer
Essayez la reconnaissance faciale avec python + OpenCV
Première reconnaissance faciale d'anime avec Chainer
[Python3] [Ubuntu16] [Docker] Essayez la reconnaissance faciale avec OpenFace
Reconnaissance faciale avec Edison
Essai de reconnaissance faciale facile avec Jetson Nano et caméra Web
Reconnaissance faciale avec OpenCV de Python
Essayez d'implémenter RBM avec chainer.
Reconnaissance faciale par Amazon Rekognition
Reconnaissance faciale / coupe avec OpenCV
Reconnaissance faciale avec caméra avec opencv3 + python2.7
Essayez l'apprentissage de la représentation commune avec le chainer
Reconnaissons les émotions avec Azure Face
J'ai essayé la reconnaissance faciale avec OpenCV
Essayez avec Chainer Deep Q Learning - Lancement
Essayons gRPC avec Go et Docker
Reconnaissance faciale des personnages d'anime avec Keras
[python, openCV] base64 Reconnaissance faciale dans les images
API de reconnaissance faciale sans serveur conçue avec Python
Catégoriser les images de visage de personnages d'anime avec Chainer
Essayez de monter votre visage avec le test AB
Reconnaissance d'image avec le modèle Caffe Chainer Yo!