[PYTHON] Depuis qu'il y avait Doppelgenger, j'ai essayé de le distinguer avec l'intelligence artificielle (rires) (Partie 1)

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

Objectif

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.

537059_256924114444730_821185260_n.jpg

Ce sera un joli sourire. Ensuite, il s'agit de M. Kazuhiko Tanaka de "Super Maradona", finaliste du Grand Prix M-1 2015.

tanaka.jpg

!?!?!?

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.

0. Créer un environnement de développement

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.

1. Collectez des images pour apprendre.

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.

2. Prétraitez l'image

Afin de classer le visage, nous traiterons un peu l'image. Les 4 prochaines étapes.

  1. Découpez la partie du visage de l'image
  2. Redimensionner
  3. Expansion des données (inversion, rotation)
  4. Convertir au format np.ndarray

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.

dataset.JPG

…。 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!

référence

Création d'un environnement de développement d'applications d'apprentissage automatique avec Python --qiita

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

Depuis qu'il y avait Doppelgenger, j'ai essayé de le distinguer avec l'intelligence artificielle (rires) (Partie 1)
Dans IPython, quand j'ai essayé de voir la valeur, c'était un générateur, donc je l'ai inventé quand j'étais frustré.
Un débutant a essayé de colorier un dessin au trait avec un chainer. J'ai pu le faire.
Je voulais utiliser la feuille de calcul Google avec AWS lambda, alors je l'ai essayé [Partie 2]
Un mémorandum lors de l'acquisition automatique avec du sélénium
J'étais accro à essayer Cython avec PyCharm, alors prenez note
Quand j'ai essayé de créer un VPC avec AWS CDK mais que je n'ai pas pu le faire
J'ai pu me moquer d'AWS-Batch avec python, moto, donc je vais le laisser
Notez que j'étais accro à la configuration de TensowFlow
Je voulais connaître le nombre de lignes dans plusieurs fichiers et j'ai essayé de l'obtenir avec une commande
Les débutants en Python ont créé un chat BOT alors j'ai essayé de résumer comment le faire
J'ai essayé d'implémenter une ligne moyenne mobile de volume avec Quantx
[IOS] Animation GIF avec Pythonista3. J'en étais accro.
J'ai essayé de créer automatiquement un rapport avec la chaîne de Markov
Quand j'ai essayé d'installer PIL et matplotlib dans un environnement virtualenv, j'en étais accro.
J'ai essayé de résoudre le problème d'optimisation des combinaisons avec Qiskit
J'ai créé un serveur avec socket Python et ssl et j'ai essayé d'y accéder depuis le navigateur
J'ai essayé de commencer avec Hy ・ Définir une classe
Le livre de PyTorch était difficile à comprendre, alors je l'ai complété
J'ai trébuché lorsque j'ai essayé d'installer Basemap, donc un mémorandum
J'ai essayé de trier une colonne FizzBuzz aléatoire avec un tri à bulles.
J'ai essayé d'écrire dans un modèle de langage profondément appris
Je n'ai pas le sens du "quiz demandant un sens de l'investissement", alors j'ai essayé de le résoudre avec la force brute (simulation Python Monte Carlo)
Ce à quoi j'étais accro dans Collective Intelligence Chaprter 3. Ce n'est pas une faute de frappe, donc je pense que quelque chose ne va pas avec mon code.
Quand j'ai essayé de gratter en utilisant des requêtes en python, j'étais accro à SSLError, donc un mémo de contournement
J'ai essayé de l'étendre pour que la base de données puisse être utilisée avec le logiciel d'analyse de Wiire
J'étais frustré par Kaggle, alors j'ai essayé de trouver une bonne propriété locative en grattant et en apprentissage automatique
[5e] J'ai essayé de créer un certain outil de type Authenticator avec python
[2nd] J'ai essayé de créer un certain outil de type Authenticator avec python
[Python] J'ai essayé d'implémenter un tri stable, alors notez
[3ème] J'ai essayé de créer un certain outil de type Authenticator avec python
J'ai essayé de créer une liste de nombres premiers avec python
J'ai essayé de faire un processus d'exécution périodique avec Selenium et Python
J'ai essayé de résumer ce qui était sorti avec Qiita avec Word cloud
Une note à laquelle j'étais accro lors de la création d'une table avec SQL Alchemy
J'ai essayé de créer une application de notification de publication à 2 canaux avec Python
J'ai essayé de créer des taureaux et des vaches avec un programme shell
J'ai essayé de créer une application todo en utilisant une bouteille avec python
[4th] J'ai essayé de créer un certain outil de type Authenticator avec python
[1er] J'ai essayé de créer un certain outil de type Authenticator avec python
J'ai essayé de faire une étrange citation pour Jojo avec LSTM
J'ai essayé de créer un mécanisme de contrôle exclusif avec Go
Je suis tombé sur un filtre d'image avec un nom clairement japonais appelé filtre Kuwahara, et quand je l'ai essayé, c'était incroyable, alors je vais le présenter.
L'éditeur Cloud Shell de GCP était encombré par l'environnement de développement Python, j'ai donc réussi à le reconstruire comme un terrain vacant.
Puisqu'il n'y a pas de description sur la façon de créer un environnement pour nnabla avec Docker, y compris le GPU, je l'ai essayé moi-même Partie 1
[Python] Quand j'ai essayé de créer un outil de décompression avec un fichier zip que je connaissais juste, j'étais accro à sys.exit ()
J'ai essayé de communiquer avec un serveur distant par communication Socket avec Python.
J'ai essayé de mettre en œuvre une blockchain qui fonctionne réellement avec environ 170 lignes
Lorsque j'ai essayé d'exécuter Python, j'ai été ignoré dans le Microsoft Store
J'ai essayé de créer un programme qui convertit les nombres hexadécimaux en nombres décimaux avec python
J'étais accro à la création d'un environnement Python venv avec VS Code
Une histoire à laquelle j'étais accro à essayer d'obtenir une URL de vidéo avec tweepy
J'ai essayé de créer un plug-in avec HULFT IoT Edge Streaming [Development] (2/3)
J'ai essayé de créer un LINE BOT "Sakurai-san" avec API Gateway + Lambda