de Sigurður Skúli

Realizarea propriului sistem de recunoaștere a feței

Realizarea propriului sistem de recunoastere a fetei

Recunoașterea feței este cea mai recentă tendință în ceea ce privește autentificarea utilizatorului. Apple a lansat recent noul iPhone X pe care îl folosește Face ID pentru autentificarea utilizatorilor. OnePlus 5 este în curs de obținere caracteristica Face Unlock de la OnePlus 5T în curând. Și Baidu folosește recunoașterea feței în locul cărților de identitate pentru a permite angajaților lor să intre în birourile lor. Aceste aplicații pot părea magice pentru mulți oameni. Dar în acest articol ne propunem să demitizăm subiectul, învățându-vă cum să creați propria versiune simplificată a unui sistem de recunoaștere a feței în Python.

Link Github pentru cei cărora nu le place să citească și doresc doar codul

fundal

Înainte de a intra în detaliile implementării, vreau să discut despre detaliile FaceNet. Care este rețeaua pe care o vom folosi în sistemul nostru.

FaceNet

FaceNet este o rețea neuronală care învață o mapare de la imagini de față la un compact Spațiul euclidian unde distanțele corespund unei măsuri de asemănare a feței. Adică, cu cât cele două imagini ale feței sunt mai asemănătoare, cu atât este mai mică distanța dintre ele.

Pierderea tripletului

FaceNet utilizează o metodă distinctă de pierdere numită Triplet Loss pentru a calcula pierderea. Triplet Loss minimizează distanța dintre o ancoră și un pozitiv, imagini care conțin aceeași identitate și maximizează distanța dintre ancoră și un negativ, imagini care conțin identități diferite.

Realizarea propriului sistem de recunoastere a fetei
Figura 1: Ecuația pierderii tripletului
  • fa) se referă la codarea de ieșire a ancorei
  • f (p) se referă la codarea ieșirii pozitivului
  • f (n) se referă la codarea de ieșire a negativului
  • alfa este o constantă utilizată pentru a vă asigura că rețeaua nu încearcă să optimizeze spre f (a) – f (p) = f (a) – f (n) = 0.
  • […]+ este egal cu max (0, sumă)

Rețele siameze

1611455408 798 Realizarea propriului sistem de recunoastere a fetei
Figura 2: Un exemplu de rețea siameză care folosește imagini de fețe ca intrare și scoate o codificare a numărului de 128 de imagini. Sursă: Coursera

FaceNet este o rețea siameză. O rețea siameză este un tip de arhitectură de rețea neuronală care învață cum să diferențieze două intrări. Acest lucru le permite să afle ce imagini sunt similare și care nu. Aceste imagini pot conține fețe.

Rețelele siameze constau din două rețele neuronale identice, fiecare cu aceleași greutăți exacte. În primul rând, fiecare rețea ia ca intrare una dintre cele două imagini de intrare. Apoi, ieșirile ultimelor straturi ale fiecărei rețele sunt trimise către o funcție care determină dacă imaginile conțin aceeași identitate.

În FaceNet, acest lucru se face calculând distanța dintre cele două ieșiri.

Implementare

Acum că am clarificat teoria, putem sări direct în implementare.

În implementarea noastră vom folosi Keras și Tensorflow. În plus, folosim două fișiere utilitare de la care am primit repo de deeplearning.ai pentru a abstra toate interacțiunile cu rețeaua FaceNet .:

  • fr_utils.py conține funcții pentru alimentarea imaginilor în rețea și obținerea codificării imaginilor
  • inception_blocks_v2.py conține funcții pentru pregătirea și compilarea rețelei FaceNet

Compilarea rețelei FaceNet

Primul lucru pe care trebuie să-l facem este să compilăm rețeaua FaceNet, astfel încât să o putem folosi pentru sistemul nostru de recunoaștere a feței.

import osimport globimport numpy as npimport cv2import tensorflow as tffrom fr_utils import *from inception_blocks_v2 import *from keras import backend as K
K.set_image_data_format('channels_first')
FRmodel = faceRecoModel(input_shape=(3, 96, 96))
def triplet_loss(y_true, y_pred, alpha = 0.3):    anchor, positive, negative = y_pred[0], y_pred[1], y_pred[2]    pos_dist = tf.reduce_sum(tf.square(tf.subtract(anchor,               positive)), axis=-1)    neg_dist = tf.reduce_sum(tf.square(tf.subtract(anchor,                negative)), axis=-1)    basic_loss = tf.add(tf.subtract(pos_dist, neg_dist), alpha)    loss = tf.reduce_sum(tf.maximum(basic_loss, 0.0))       return loss
FRmodel.compile(optimizer="adam", loss = triplet_loss, metrics = ['accuracy'])load_weights_from_FaceNet(FRmodel)

Vom începe prin inițializarea rețelei noastre cu o formă de intrare de (3, 96, 96). Asta înseamnă că canalele roșu-verde-albastru (RGB) sunt prima dimensiune a volumului imaginii alimentat în rețea. Și că toate imaginile care sunt alimentate în rețea trebuie să aibă imagini de 96×96 pixeli.

În continuare vom defini funcția Triplet Loss. Funcția din fragmentul de cod de mai sus urmează definiția ecuației de pierdere a tripletului pe care am definit-o în secțiunea anterioară.

Dacă nu sunteți familiarizați cu oricare dintre funcțiile Tensorflow utilizate pentru efectuarea calculului, vă recomand să citiți documentația (pentru care am adăugat linkuri pentru fiecare funcție), deoarece vă va îmbunătăți înțelegerea codului. Dar compararea funcției cu ecuația din Figura 1 ar trebui să fie suficientă.

Odată ce avem funcția de pierdere, ne putem compila modelul de recunoaștere a feței folosind Keras. Și vom folosi Optimizator Adam pentru a minimiza pierderea calculată de funcția Triplet Loss.

Pregătirea unei baze de date

Acum că am compilat FaceNet, vom pregăti o bază de date cu indivizi pe care dorim să îi recunoască sistemul nostru. Vom folosi toate imaginile conținute în imagini director pentru baza noastră de date de persoane.

NOTĂ: Vom folosi doar o imagine a fiecărei persoane în implementarea noastră. Motivul este că rețeaua FaceNet este suficient de puternică pentru a avea nevoie doar de o singură imagine a unei persoane care să le recunoască!

def prepare_database():    database = {}
    for file in glob.glob("images/*"):        identity = os.path.splitext(os.path.basename(file))[0]        database[identity] = img_path_to_encoding(file, FRmodel)
    return database

Pentru fiecare imagine, vom converti datele imaginii într-o codificare de 128 de numere flotante. Facem acest lucru apelând funcția img_path_to_encoding. Funcția intră pe o cale către o imagine și alimentează imaginea către rețeaua noastră de recunoaștere a feței. Apoi, returnează ieșirea din rețea, care se întâmplă să fie codificarea imaginii.

Odată ce am adăugat codificarea pentru fiecare imagine în baza noastră de date, sistemul nostru poate începe în cele din urmă să recunoască persoane!

Recunoașterea unei fețe

După cum sa discutat în secțiunea Background, FaceNet este instruit pentru a minimiza distanța dintre imaginile aceluiași individ și pentru a maximiza distanța dintre imaginile diferiților indivizi. Implementarea noastră folosește aceste informații pentru a determina ce persoană este cea mai probabilă nouă imagine introdusă în sistemul nostru.

def who_is_it(image, database, model):    encoding = img_to_encoding(image, model)        min_dist = 100    identity = None        # Loop over the database dictionary's names and encodings.    for (name, db_enc) in database.items():        dist = np.linalg.norm(db_enc - encoding)
        print('distance for %s is %s' %(name, dist))
        if dist < min_dist:            min_dist = dist            identity = name        if min_dist > 0.52:        return None    else:        return identity

Funcția de mai sus alimentează noua imagine într-o funcție utilitară numită img_to_encoding. Funcția procesează o imagine utilizând FaceNet și returnează codarea imaginii. Acum că avem codificarea, putem găsi individul căruia îi aparține imaginea.

Pentru a găsi individul, parcurgem baza de date și calculăm distanța dintre noua noastră imagine și fiecare individ din baza de date. Individul cu cea mai mică distanță față de noua imagine este apoi ales ca cel mai probabil candidat.

În cele din urmă, trebuie să stabilim dacă imaginea candidată și noua imagine conțin sau nu aceeași persoană. Deoarece până la sfârșitul buclei noastre am determinat doar cel mai probabil individ. Aici intră în joc următorul fragment de cod.

if min_dist > 0.52:    return Noneelse:    return identity
  • Dacă distanța este peste 0,52, atunci determinăm că individul din imaginea nouă nu există în baza noastră de date.
  • Dar, dacă distanța este egală sau mai mică de 0,52, atunci stabilim că sunt aceiași individ!

Acum partea dificilă aici este că valoarea 0,52 a fost atinsă prin încercări și erori în numele meu pentru setul meu de date specific. Cea mai bună valoare poate fi mult mai mică sau puțin mai mare și va depinde de implementare și date. Vă recomand să încercați diferite valori și să vedeți ce se potrivește cel mai bine sistemului dvs.!

Construirea unui sistem folosind recunoașterea feței

Acum, că cunoaștem detaliile despre modul în care recunoaștem o persoană folosind un algoritm de recunoaștere a feței, putem începe să ne distrăm cu ea.

În depozitul Github la care am făcut legătura la începutul acestui articol este o demonstrație care folosește camera web a unui laptop pentru a alimenta cadre video către algoritmul nostru de recunoaștere a feței. Odată ce algoritmul recunoaște o persoană în cadru, demonstrația redă un mesaj audio care întâmpină utilizatorul folosind numele imaginii sale în baza de date. Figura 3 prezintă un exemplu al demonstrației în acțiune.

1611455409 226 Realizarea propriului sistem de recunoastere a fetei
Figura 3: O imagine capturată în momentul exact în care rețeaua a recunoscut persoana în imagine. Numele imaginii din baza de date a fost „skuli.jpg”, astfel încât mesajul audio redat a fost „Bun venit skuli, o zi plăcută!”

Concluzie

Până acum ar trebui să fiți familiarizați cu modul în care funcționează sistemele de recunoaștere a feței și cum să vă creați propriul sistem de recunoaștere a feței simplificat folosind o versiune pre-instruită a rețelei FaceNet în python!

Dacă doriți să vă jucați cu demonstrația din depozitul Github și să adăugați imagini cu oameni pe care îi cunoașteți, continuați și bifați depozitul.

Distrează-te cu demonstrația și impresionează-ți toți prietenii cu cunoștințele tale minunate despre recunoașterea feței!