[PYTHON] L'IA peut-elle faire la distinction entre Carlos Gone et M. Bean (reconnaissance faciale à l'aide de repères faciaux)?

introduction

La nouvelle que Carlos Gone, l'ancien président de Nissan Motor Co., Ltd., a rompu les conditions de sauvetage et s'est rendu au Liban est un sujet brûlant. Je réfléchis depuis longtemps, mais c'est similaire à M. Bean ... images.jpeg

À gauche: Carlos Gone À droite: [M. Bean (Rowan Atkinson)](https://www.google.com/search?q=rowan+atkinson&biw=1386&bih=710&sxsrf=ACYBGNTsdddnLF7jgPr9RTePeEMGgREpyA:1577813660092&tbbnischlnisch&tbmischlnisch&tbmischlnisch&tbmischnisch&tbmischnisch&t

Comme c'était un jour férié pendant les vacances de fin d'année et de nouvel an, j'ai réalisé un petit classificateur à l'aide d'un réseau neuronal. Si vous google, beaucoup d'images des deux personnes sortiront, donc CNN allait bien, mais Cette fois, comme autre approche, je voudrais classer en fonction de la position des repères sur le visage.

Veuillez noter que le codage est approximatif.

Je vais donner le code source et les données d'image utilisées pour GitHub. face_identification

environnement

Flux de processus

  1. Détection de visage à l'aide de la cascade OpenCV
  2. Estimez 68 points de repère à l'aide de dlib en fonction de la zone faciale détectée
  3. Entrez la position de 68 points dans le classificateur
  4. Carlos si la sortie est 0, M. Bean si la sortie est 1.

Créer un jeu de données

Préparez 10 photos de Carlos et 10 du visage de Bean. Cela ne me dérange pas s'il n'y a que 20 images, je vais donc redimensionner et gonfler chaque image.

Utilisez la cascade d'opencv pour la reconnaissance faciale et dlib pour l'estimation des points de repère.

dataset_generator.py


#!/usr/bin/env python
#coding:utf-8
import cv2
import dlib
import numpy as np

cascade_path = "~/face_identification/model/haarcascade_frontalface_alt.xml"
cascade = cv2.CascadeClassifier(cascade_path)

model_path = "~/face_identification/model/shape_predictor_68_face_landmarks.dat"
predictor = dlib.shape_predictor(model_path)
detector = dlib.get_frontal_face_detector()

image_file_dir = "~/face_identification/images/carlos/"
#image_file_dir = "~/face_identification/images/rowan/"

save_file_path = "~/face_identification/dataset/carlos.csv"	
#save_file_path = "~/face_identification/dataset/rowan.csv"	

face_landmarks = []
for n in range(10):
	#image_file_name = "carlos"+str(n)+".jpeg "
	image_file_name = "rowan"+str(n)+".jpeg "
	
	raw_img = cv2.imread(image_file_dir+image_file_name)
	original_width, original_height = raw_img.shape[:2]
	multiple_list = [0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0]
	for m in multiple_list:	
		size = (int(original_height*m), int(original_width*m))
		img = cv2.resize(raw_img, size)

		gray_img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
		faces = cascade.detectMultiScale(gray_img)

		if len(faces) != 0:
			for(x, y, width, height) in faces:
				cv2.rectangle(img, (x, y), (x+width, y+height), (0, 0, 255), 1)
				rects = detector(gray_img, 1)
				landmarks = []
				for rect in rects:
					landmarks.append(np.array([[p.x, p.y] for p in predictor(gray_img, rect).parts()]))
	
				for landmark in landmarks:	
					face_landmark = []
					for i in range(len(landmark)):
						cv2.drawMarker(img, (landmark[i][0], landmark[i][1]), (21, 255, 12))
                                                #Normaliser la position du repère de coordonnées_x = (landmark[i][0]-x)*100.00/width
						landmark_y = (landmark[i][1]-y)*100.00/height
						face_landmark.append(landmark_x)
						face_landmark.append(landmark_y)
					face_landmarks.append(np.array(face_landmark).flatten())
					

		cv2.imshow("viewer", img)
		key = cv2.waitKey(100)
	
print "finish"
np_dataset = np.array(face_landmarks)
np.savetxt(save_file_path, np_dataset)

Produit les repères des visages de Carlos et Gone dans un fichier csv. (Remplacez la partie commentée de dataset_generator.py et exécutez-la deux fois.)

68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f3237333436322f66613562353639632d613130662d396462382d396566632d6562376132333232633230372e706e67.png

Vous pouvez obtenir 68 points de repère sur votre visage. Les coordonnées x et y de chaque point sont stockées dans un tableau dans l'ordre (par conséquent, la valeur qui peut être prise à partir d'une face est 68 x 2 = 136). De plus, comme la valeur des coordonnées change considérablement en fonction de la taille de la face, elle est normalisée. La compréhension de Coco et d'autres est encore subtile. (S'il vous plaît dites-moi s'il y a un bon moyen)

Configuration du réseau

Créez un réseau neuronal simple de type feed forward avec Keras. La couche intermédiaire est une configuration simple avec trois.

network_model.py


#!/usr/bin/env python
#coding:utf-8
from keras.models import Sequential
from keras.layers import Activation, Dense, Dropout

class DNNModel():
    def __init__(self):
        self.model = Sequential()
        self.model.add(Dense(1024, input_dim=136)) 
        self.model.add(Activation('relu'))
        self.model.add(Dropout(0.1))

        self.model.add(Dense(512))
        self.model.add(Activation('relu'))
        self.model.add(Dropout(0.1))

        self.model.add(Dense(256))
        self.model.add(Activation('relu'))
        self.model.add(Dropout(0.1))

        self.model.add(Dense(2))#Faites correspondre le nombre d'étiquettes correctes
        self.model.add(Activation('softmax'))

Apprentissage

train.py


#!/usr/bin/env python
#coding:utf-8
import numpy as np
import keras

from network_model import DNNModel
from keras.optimizers import RMSprop, SGD, Adam
from keras.utils import to_categorical
from keras.utils import np_utils

carlos_data_path = "~/face_identification/dataset/carlos.csv"
rowan_data_path = "~/face_identification/dataset/rowan.csv"

weight_file_path = "~/face_identification/model/weight.hdf5"

landmarks = []
labels = []

with open(carlos_data_path, "r") as f:
	carlos_lines = f.read().split("\n")	
	f.close()

with open(rowan_data_path, "r") as f:
	rowan_lines = f.read().split("\n")
	f.close()

for i in range(len(carlos_lines)-1):
	carlos_line = carlos_lines[i].split(" ")
	landmarks.append(np.array(carlos_line).flatten())
	labels.append(0) #Carlos a 0

for i in range(len(rowan_lines)-1):
	rowan_line = rowan_lines[i].split(" ")
	landmarks.append(np.array(rowan_line).flatten())
	labels.append(1) #Mr.Bean vaut 1

landmarks = np.asarray(landmarks).astype("float32")
labels = np_utils.to_categorical(labels, 2)

model = DNNModel().model
model.summary()
model.compile(loss='binary_crossentropy', optimizer=Adam(lr=0.0001), metrics=['accuracy'])

history = model.fit(landmarks, labels,
    batch_size=64,
    epochs=3000)

model.save_weights(weight_file_path)
print "model was saved."

Je pense que l'apprentissage sera complété en moins de 5 minutes.

résultat

result0.jpeg Bonne réponse result2.jpeg Bonne réponse

result4.jpeg Bonne réponse

result_.jpeg Bonne réponse

result1.jpeg Échec Carlos ne parvient pas à détecter son visage. M. Bean n'a pas réussi à classer.

result3.jpeg Échec

test.py


#!/usr/bin/env python
#coding:utf-8
import cv2
import dlib
import numpy as np
import tensorflow as tf

from network_model import DNNModel

cascade_path = "~/face_identification/model/haarcascade_frontalface_alt.xml"
cascade = cv2.CascadeClassifier(cascade_path)

model_path = "~/face_identification/model/shape_predictor_68_face_landmarks.dat"
predictor = dlib.shape_predictor(model_path)
detector = dlib.get_frontal_face_detector()

trained_model_path = "~/face_identification/model/weight.hdf5"
model = DNNModel().model    
model.load_weights(trained_model_path)
graph = tf.get_default_graph()

test_image_path = "~/face_identification/images/test.jpeg "
result_image_path = "~/face_identification/images/result.jpeg "

img = cv2.imread(test_image_path)
gray_img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
faces = cascade.detectMultiScale(gray_img, minSize=(30, 30))

if len(faces) != 0:
	for(x, y, width, height) in faces:
		cv2.rectangle(img, (x, y), (x+width, y+height), (0, 0, 255), 1)
		rects = detector(gray_img, 1)
		landmarks = []
		for rect in rects:
			landmarks.append(np.array([[p.x, p.y] for p in predictor(gray_img, rect).parts()]))

		for landmark in landmarks:
			input_data = []	
			face_landmark = []
			for i in range(len(landmark)):
				landmark_x = (landmark[i][0]-x)*100.00/width
				landmark_y = (landmark[i][1]-y)*100.00/height
				face_landmark.append(landmark_x)
				face_landmark.append(landmark_y)
			
			face_landmark = np.array(face_landmark).flatten()			
			input_data.append(face_landmark)
			with graph.as_default():
				pred = model.predict(np.array(input_data))
			
			result_idx = np.argmax(pred[0])
			if result_idx == 0:
				text = "Carlos:" + str(pred[0][result_idx])
			else:
				text = "Rowan:" + str(pred[0][result_idx])
			
		#Écriture de caractères
		cv2.putText(img, text, (x, y), cv2.FONT_HERSHEY_SIMPLEX, 0.5,(0,0,255))

			
#cv2.imshow("viewer", img)
cv2.imwrite(result_image_path, img)

À la fin

Carlos Gone est dur.

Recommended Posts

L'IA peut-elle faire la distinction entre Carlos Gone et M. Bean (reconnaissance faciale à l'aide de repères faciaux)?
Détection d'image de visage similaire utilisant la reconnaissance faciale et le clustering PCA et K-means