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.
-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)
** 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
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.
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.
** 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()
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.
commander
python face_recog_CH.py -p <fichier de paramètres> -c <cascade> (-d <ID appareil photo>)
Puisqu'il s'agit de la phase de prédiction, c'est un programme qui identifie le visage à l'aide d'une caméra.
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)
# ================================================================================================================
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)
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".
À 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