Ravi de vous rencontrer. Je m'appelle @eve_yk et je suis ingénieur stagiaire dans une startup appelée Liaro. Cette fois, nous approfondirons notre compréhension de la technologie que Liaro utilise chaque jour, produirons et partagerons activement nos connaissances et, espérons-le, demanderons à un professionnel sur la route de lancer un Masakari pointu. Il a été décidé "d'écrire un blog!" Pour le but. Il n'y a pas beaucoup de contenu qui puisse être écrit, mais j'aimerais en écrire autant que possible. Merci beaucoup ~!
Cette fois, je vais créer un classificateur d'image de visage en utilisant le Convelutional Neural Network (CNN).
La tâche de classification des visages est de Facebook DeepFace et de Google FaceNet. /1503.03832) etc.
Pourquoi contester l'identification des images faciales? Pour expliquer cela, j'aimerais que vous jetiez un œil à l'image suivante.
Tout d'abord, l'icône que j'ai enregistrée sur Facebook.
Ce sera un joli sourire. Ensuite, il s'agit de M. Kazuhiko Tanaka de "Super Maradona", finaliste du Grand Prix M-1 2015.
!?!?!?
Super comme! !! !! Ce fut une expérience très choquante pour moi, à qui je n'avais jamais dit de ressembler à quelqu'un. Je pense que je n'ai pas d'autre choix que de faire un classificateur qui me distingue de M. Tanaka. C'est une raison idiote.
Cette fois, je l'ai testé dans l'environnement suivant.
Si vous utilisez pyenv pour créer l'environnement, ce sera facile. Je pense que vous devriez vous référer aux liens ci-dessous.
Création d'un environnement de développement d'applications d'apprentissage automatique avec Python
numpy et opencv peuvent être installés avec anaconda, et chainer et ProgressBar2 peuvent être installés avec pip.
Ensuite, rassemblez les images utilisées pour la formation. Il n'est pas exagéré de dire que la collecte des données à utiliser est la tâche la plus difficile de l'apprentissage automatique. Dans ce cas, ** c'est particulièrement difficile car il y a trop peu de demande à cet effet. Je ferai de mon mieux pour le récupérer manuellement.
Pour le moment, 80 images de moi-même et 68 images de M. Tanaka ont été recueillies. (J'ai été surpris que seul cela ait été recueilli même si j'ai attrapé mon smartphone, PC, Facebook) Évitez 5 d'entre eux comme images de test. Nous allons créer un ensemble de données en utilisant les 75,63 images restantes comme images d'entraînement. Le nombre est trop petit, mais cette fois c'est une pièce de théâtre, alors faisons ceci.
Afin de classer le visage, nous traiterons un peu l'image. Les 4 prochaines étapes.
Tout d'abord, découpez la zone de la partie du visage dans l'image. Pour cela, nous utilisons un classificateur en cascade qui utilise les fonctionnalités Haar-Like fournies par OpenCV. Je n'apprendrai pas le classificateur cette fois. Puis redimensionnez l'image à 64 * 64px. Le chaîneur peut calculer des entités de n'importe quelle taille de longueur fixe quelle que soit la taille de l'image d'entrée [Spatial Pyramid Pooling](http://docs.chainer.org/en/stable/reference/functions.html#chainer.functions .spatial_pyramid_pool_2d) est également implémenté, mais je ne l'ai pas utilisé cette fois. Après cela, les données sont développées. Lors de la classification des images, l'image originale est traitée par inversion, mouvement parallèle, rotation, changement de couleur, lissage, etc., et la quantité de données est gonflée. Cette fois, l'image d'origine est inversée et tournée pour augmenter la quantité de données.
Si vous codez le processus ci-dessus, il ressemblera à ceci.
face_data_augmentation.py
# coding:utf-8
"""
Extraire la zone du visage existant dans l'image dans le dossier spécifié
Inverser et faire pivoter l'image pour l'agrandir
"""
import os
import glob
import argparse
import cv2
import numpy as np
CASCADE_PATH = "/path/to/haarcascade/haarcascade_frontalface_alt.xml"
cascade = cv2.CascadeClassifier(CASCADE_PATH)
def detectFace(image):
"""
Extraire la partie de l'image du visage
"""
image_gray = cv2.cvtColor(image, cv2.cv.CV_BGR2GRAY)
facerect = cascade.detectMultiScale(image_gray, scaleFactor=1.1, minNeighbors=3, minSize=(50, 50))
return facerect
def resize(image):
"""
Redimensionnement de l'image
"""
return cv2.resize(image, (64,64))
def rotate(image, r):
"""
Rotation de r degrés autour du centre de l'image
"""
h, w, ch = image.shape #Taille du tableau d'images
M = cv2.getRotationMatrix2D((w/2, h/2), r, 1) #Matrice de rotation pour tourner autour de l'image
rotated = cv2.warpAffine(image, M, (w, h))
return rotated
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='clip face-image from imagefile and do data argumentation.')
parser.add_argument('-p', required=True, help='set files path.', metavar='imagefile_path')
args = parser.parse_args()
#Créer s'il n'y a pas de répertoire de sortie
result_dir = args.p + "_result"
if not os.path.exists(result_dir):
os.makedirs(result_dir)
face_cnt = 0
#Obtenir le fichier jpg
files = glob.glob(args.p+"\*.jpg ")
print args.p+"\*.jpg "
for file_name in files:
#Charger l'image
image = cv2.imread(file_name)
if image is None:
#Échec de lecture
continue
# -12~Faites pivoter 3 degrés dans une plage de 12 degrés
for r in xrange(-12,13,4):
image = rotate(image, r)
#Extraction d'image de visage
facerect_list = detectFace(image)
if len(facerect_list) == 0: continue
for facerect in facerect_list:
#Découpe d'une partie d'image de visage
croped = image[facerect[1]:facerect[1]+facerect[3],facerect[0]:facerect[0]+facerect[2]]
#production
cv2.imwrite(result_dir+"/"+str(face_cnt)+".jpg ", resize(croped))
face_cnt += 1
#L'image inversée est également sortie
fliped = np.fliplr(croped)
cv2.imwrite(result_dir+"/"+str(face_cnt)+".jpg ", resize(fliped))
face_cnt += 1
Les images générées par ce code incluent les images de visage d'autres personnes et les images faussement détectées dans la photo, nous allons donc supprimer manuellement les images inutiles une par une. Voici le jeu de données complet.
…。 C'est un sentiment. Comme images d'entraînement, j'ai fait 393 images de moi-même et 187 images de M. Tanaka.
Enfin, créez les données converties au format np.ndarray pour les manipuler par chainer. Puisqu'il est supposé que les données de type np.ndarray seront entrées dans la classe Variable utilisée par le chainer, convertissez-les au préalable dans ce format. À ce stade, notez que le format d'image géré par OpenCV de Python et le format d'image géré par CNN de chainer sont différents.
OpenCV => (height, width, channel) chainer => (channel, height, width)
Convertissez avec le code suivant.
make_dataset.py
# coding:utf-8
import os
import sys
import argparse
import glob
import cv2
import numpy as np
"""
Créer un ensemble de données à utiliser avec CNN
Convertir l'image au format d'entrée CNN
Le format de l'ensemble de données est le suivant
- dataset
- train
- [class_name_1]
- hogehoge.jpg
- foofoo.jpg
- ...
- [class_name_2]
- hogehoge.jpg
- ...
- ...
- test
- [class_name_1]
- hogehoge.jpg
- ...
- ...
"""
def transpose_opencv2chainer(x):
"""
Conversion du format opencv npy au format chainer npy
opencv => (height, width, channel)
chainer => (channel, height, width)
"""
return x.transpose(2,0,1)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Créer un ensemble de données pour CNN')
parser.add_argument('--input_path', required=True, type=str)
parser.add_argument('--output_path', required=True, type=str)
args = parser.parse_args()
#Obtenir la liste des fichiers jpg
train_files = glob.glob(args.input_path+"/train/*/*.jpg ")
test_files = glob.glob(args.input_path+"/test/*/*.jpg ")
#Créer s'il n'y a pas de répertoire de sortie
if not os.path.exists(args.output_path):
os.makedirs(args.output_path)
train_data = []
train_label = []
test_data = []
test_label = []
label_dict = {}
#Création de données de formation
for file_name in train_files:
image = cv2.imread(file_name)
if image is None:
#Échec de lecture
continue
#Obtenir le nom de la classe à partir de la structure du répertoire
class_name = file_name.replace("\\", "/").split("/")[-2]
#Convertir au format de chaîne
image = transpose_opencv2chainer(image)
train_data.append(image)
train_label.append(label_dict.setdefault(class_name, len(label_dict.keys())))
#Création / sauvegarde de données
train_data = np.array(train_data)
train_label = np.array(train_label)
np.save(args.output_path+"/train_data.npy" , train_data)
np.save(args.output_path+"/train_label.npy", train_label)
for file_name in test_files:
image = cv2.imread(file_name)
if image is None:
#Échec de lecture
continue
#Obtenir le nom de la classe à partir de la structure du répertoire
class_name = file_name.replace("\\", "/").split("/")[-2]
#Convertir au format de chaîne
image = transpose_opencv2chainer(image)
test_data.append(image)
test_label.append(label_dict.setdefault(class_name, len(label_dict.keys())))
#Création / sauvegarde de données
test_data = np.array(test_data)
test_label = np.array(test_label)
np.save(args.output_path+"/test_data.npy" , test_data)
np.save(args.output_path+"/test_label.npy" , test_label)
C'est un peu court, mais cette fois, c'est ici. La prochaine fois, j'aimerais décrire un modèle du classificateur et apprendre et évaluer la discrimination de visage. impatient de!
https://github.com/mitmul/chainer-cifar10
Essayez de classer CIFAR-10 avec le journal Chainer-A d'un ingénieur décontracté
Profil de l'artiste Yoshimoto Kogyo Co., Ltd. | Super Maradona
Recommended Posts