[PYTHON] Kann AI zwischen Carlos Gone und Mr. Bean unterscheiden (Gesichtserkennung anhand von Gesichtspunkten)?

Einführung

Die Nachricht, dass Carlos Gone, der frühere Vorsitzende von Nissan Motor Co., Ltd., die Freigabebedingungen gebrochen und in den Libanon gereist ist, ist ein heißes Thema. Ich habe lange nachgedacht, aber es ist ähnlich wie Mr. Bean ... images.jpeg

Links: Carlos Gone Rechts: [Mr. Bean (Rowan Atkinson)](https://www.google.com/search?q=rowan+atkinson&biw=1386&bih=710&sxsrf=ACYBGNTsdddnLF7jgPr9RTePeEMGgREpyA:1577813660092&source=lnms&b

Da es ein Feiertag während der Jahresend- und Neujahrsferien war, habe ich einen kleinen Klassifikator unter Verwendung eines neuronalen Netzwerks erstellt. Wenn Sie googeln, werden viele Bilder der beiden Personen herauskommen, also war CNN in Ordnung, aber Dieses Mal möchte ich als weiteren Ansatz anhand der Position der Orientierungspunkte im Gesicht klassifizieren.

Bitte beachten Sie, dass die Codierung grob ist.

Ich werde den Quellcode und die Bilddaten an GitHub weitergeben. face_identification

Umgebung

Prozessablauf

  1. Gesichtserkennung mit OpenCV-Kaskade
  2. Schätzen Sie 68 Orientierungspunkte mit dlib basierend auf dem erkannten Gesichtsbereich
  3. Geben Sie die Position von 68 Punkten in den Klassifikator ein
  4. Carlos, wenn die Ausgabe 0 ist, Mr. Bean, wenn die Ausgabe 1 ist.

Erstellen eines Datensatzes

Bereite 10 Fotos von Carlos und 10 von Beans Gesicht vor. Es macht mir nichts aus, wenn es nur 20 Bilder gibt, also werde ich die Größe jedes Bildes ändern und es aufblasen.

Verwenden Sie die Kaskade von opencv für die Gesichtserkennung und dlib für die Schätzung von Orientierungspunkten.

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))
                                                #Normalisieren Sie die Position des Orientierungspunkts_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)

Gibt die Wahrzeichen von Carlos und Gones Gesichtern in eine CSV-Datei aus. (Ersetzen Sie den auskommentierten Teil von dataset_generator.py und führen Sie ihn zweimal aus.)

68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f3237333436322f66613562353639632d613130662d396462382d396566632d6562376132333232633230372e706e67.png

Sie können 68 Orientierungspunkte auf Ihrem Gesicht erhalten. Die x- und y-Koordinaten jedes Punktes werden in der angegebenen Reihenfolge in einem Array gespeichert (daher beträgt der Wert, der von einer Fläche übernommen werden kann, 68 x 2 = 136). Da sich der Koordinatenwert in Abhängigkeit von der Größe des Gesichts stark ändert, wird er normalisiert. Das Verständnis von Coco und anderen ist immer noch subtil. (Bitte sag mir, ob es einen guten Weg gibt)

Netzwerkkonfiguration

Erstellen Sie mit Keras ein einfaches neuronales Netzwerk vom Typ Feed-Forward. Die mittlere Schicht ist eine einfache Konfiguration mit drei.

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))#Passen Sie die Anzahl der richtigen Etiketten an
        self.model.add(Activation('softmax'))

Lernen

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 ist 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 ist 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."

Ich denke, das Lernen wird in weniger als 5 Minuten abgeschlossen sein.

Ergebnis

result0.jpeg Richtige Antwort result2.jpeg Richtige Antwort

result4.jpeg Richtige Antwort

result_.jpeg Richtige Antwort

result1.jpeg Fehler Carlos erkennt sein Gesicht nicht. Mr. Bean konnte nicht klassifizieren.

result3.jpeg Fehler

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])
			
		#Zeichen schreiben
		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)

Am Ende

Carlos Gone ist hart.

Recommended Posts

Kann AI zwischen Carlos Gone und Mr. Bean unterscheiden (Gesichtserkennung anhand von Gesichtspunkten)?
Ähnliche Gesichtsbilderkennung mit Gesichtserkennung und PCA- und K-Mittel-Clustering