Il Machine Learning è divertente! — Parte 4

Riconoscimento facciale attraverso il Deep Learning

Questo articolo è il secondo di una lunga serie, se lo hai già letto puoi saltare direttamente alla parte 5, parte 6, parte 7 o parte 8 cliccando i link diretti.

Avete notato che Facebook ha sviluppato una straordinaria capacità di riconoscere i vostri amici nelle foto? Ai vecchi tempi, Facebook permetteva di taggare gli amici nelle foto cliccando sulla loro faccia e digitando il loro nome. Ora, non appena si carica una foto, Facebook ha già taggato tutti come per magia:

Facebook tagga automaticamente le persone nelle foto. Non sono sicuro se questo è utile o raccapricciante!

Questa tecnologia si chiama Face Recognition (Riconoscimento Facciale). Gli algoritmi di Facebook sono in grado di riconoscere i volti dei vostri amici dopo che sono stati etichettati anche solo un paio di volte. E’ una tecnologia piuttosto sorprendente — Facebook può riconoscere i volti con il 98% di precisione, più o meno lo stesso livello degli esseri umani!

In questo articolo impareremo come funzionano gli algoritmi di riconoscimento facciale e vedremo come svilupparne uno con strumenti open source disponibili a tutti!

Ma essere in grado di riconoscere i tuoi amici è un obiettivo troppo facile da raggiungere. In realtà, possiamo usare questa tecnologia per risolvere un problema molto più sottile e complesso — distinguere tra Will Ferrell (famoso attore) e Chad Smith (famoso musicista rock)!

Una di queste persone è Will Ferrell. L’altro è Chad Smith. Giuro che sono persone diverse!

Come usare il Machine Learning per risolvere un problema molto complesso

Finora nella parte 1, 2 e 3, abbiamo usato il Machine Learning per risolvere problemi isolati che comportavano un solo passaggio — stimare il prezzo di una casa, generare nuovi dati sulla base di dati esistenti e capire se un’immagine contenga un certo oggetto. Tutti questi problemi possono essere risolti con lo stesso procedimento: scegli l’algoritmo di Machine Learning, alimentalo con dei dati e ottieni il risultato.

Ma il riconoscimento del volto è in realtà una serie di problemi connessi:

  1. Essere in grado di trovare tutte le facce in una determinata immagine
  2. Essere in grado di identificare la stessa faccia a prescindere dalla luminosità della foto, dall’espressione e dalla direzione in cui è girata la testa
  3. Capire quali sono le caratteristiche uniche di ogni volto che possono essere usate per distinguerlo in maniera univoca — come la dimensione degli occhi, la distanza tra gli occhi, etc.
  4. Identificare la persona in maniera univoca confrontando le caratteristiche uniche specifiche del suo volto con le caratteristiche uniche specifiche di tutti gli altri volti esistenti

Negli esseri umani, questo processo è fatto in modo automatico dal cervello.

Gli esseri umani sono fin troppo bravi a riconoscere i volti e finiscono per vederli anche dove non ci sono:

I computer non sono capaci di questo livello di astrazione (almeno non ancora …), quindi dobbiamo insegnare loro come risolvere tutti i problemi descritti sopra, uno per uno.

Dobbiamo costruire un processo che risolva ogni passaggio separatamente e che trasferisca il risultato del passaggio corrente al passaggio successivo. In poche parole, dobbiamo concatenare insieme una serie di algoritmi di Machine Learning, ognuno tarato per risolvere un problema specifico del processo di Face Recognition.

Ecco come potrebbero funzionare i diversi passaggi del nostro processo di Face Recognition

Face Recognition — Un passo alla volta

Ad ogni passaggio, useremo un algoritmo di Machine Learning diverso. Per evitare che l’articolo si trasformi in un libro, non entrerò nei dettagli di ciascuno ma descriverò in ogni caso le idee principali ed i passaggi da seguire per sviluppare un sistema di riconoscimento facciale in Python usando OpenFace e dlib.

Primo passaggio: Face Detection

Il primo passaggio è la Face Detection, ovvero l’individuazione di tutte le facce presenti nell’immagine. Il motivo di questo primo passaggio è ovvio: abbiamo bisogno di individuare i volti in una foto prima di poter cercare di distinguerli!

Se hai utilizzato qualsiasi fotocamera negli ultimi 10 anni, probabilmente hai visto questo algoritmo in funzione:

Face Detection è una funzionalità utilissima che al giorno d’oggi è presente in praticamente qualsiasi macchina fotografica. L’utilità sta nel fatto che quando la macchina fotografica è in grado di individuare automaticamente i volti, può fare in modo che siano tutti messi a fuoco prima di scattare la foto.

Nel nostro caso però, l’algoritmo di Face Recognition verrà usato per uno scopo diverso — trovare le aree dell’immagine che vogliamo trasferire come input nell’algoritmo successivo.

La Face Detection è diventata di uso comune nei primi anni del 2000 quando Paolo Viola e Michael Jones hanno inventato un modo per rilevare i volti che fosse abbastanza veloce da essere inserito nelle macchine fotografiche a basso costo. Tuttavia, esistono ora soluzioni molto più affidabili e precise come l’Histogram of Oriented Gradients (HOG), metodo inventato nel 2005 e che utilizzeremo per lo scopo di questo articolo.

Per trovare i volti in un’immagine, come prima cosa trasformeremo la nostra immagine in bianco e nero, perché le informazioni di colore sono del tutto superflue:

Poi analizzeremo ogni pixel nell’immagine singolarmente, uno alla volta. E per ognuno faremo un analisi comparativa con tutti i pixel che lo circondano:

Il nostro obiettivo è quello di capire quanto sia scuro il pixel corrente rispetto ai pixel che lo circondano direttamente. Una volta completata la nostra analisi, disegneremo una freccia indicante la direzione in cui la serie di pixel analizzata si sta inscurendo:

Guardando solo questo pixel e i pixel che lo toccano, l’immagine è sempre più scura verso l’angolo in alto a destra.

Ripetendo questo processo per ogni singolo pixel nell’immagine, finiremo per sostituire tutti i pixel con delle frecce. Queste frecce si chiamano gradienti e rappresentano il flusso dalla luce al buio sull’intera immagine:

Questa potrebbe sembrare una cosa completamente inutile, ma c’è una buona ragione per sostituire i pixel con i gradienti di luce. Se analizziamo direttamente i pixel, immagini molto buie e immagini molto luminose della stessa persona avranno valori di pixel completamente diverse. Ma considerando solo la direzione verso la quale si verifica il cambio di luminosità, otterremo la stessa rappresentazione indipendentemente dal fatto che l’immagine sia molto buia o molto luminosa. Questo rende il nostro problema molto più facile da risolvere!

Ma salvare il gradiente per ogni singolo pixel ci dà un risultato troppo dettagliato. Rischiamo di perdere la foresta tra gli alberi. Sarebbe meglio se potessimo vedere il flusso di luce dal chiaro allo scuro ad un livello superiore.

A questo scopo, scomponiamo l’immagine in quadratini di 16x16 pixel ciascuno. Per ogni quadratino, contiamo quanti gradienti puntino nella stessa direzione (quanti a destra, quanti in alto, etc…). Poi sostituiamo il quadratino con un altro gradiente che rappresenta la direzione nella quale la maggior parte dei gradienti stavano puntando.

Il risultato finale è una rappresentazione che cattura la struttura di base di un volto in modo schematico:

L’immagine originale è trasformato in una rappresentazione HOG che cattura le principali caratteristiche dell’immagine indipendentemente dal livello di luminosità.

Per trovare i volti in questa immagine HOG, non dobbiamo far altro che trovare la parte dell’immagine che assomigli di più a un modello HOG codificato in precedenza per rappresentare schematicamente la struttura media di qualsiasi volto umano:

Utilizzando questa tecnica, si può ora facilmente trovare volti all’interno di qualsiasi immagine:

Se volete provare questo passaggio da soli utilizzando Python e dlib, ecco il codice che mostra come generare rappresentazioni HOG delle immagini.

Step 2: Posizione e proiezione dei volti

Finalmente, abbiamo isolato i volti nella nostra immagine. Ma ora abbiamo a che fare con un altro problema, per il computer la stessa faccia volta in direzioni diverse non è la stessa faccia!

Gli esseri umani possono facilmente riconoscere che entrambe le immagini sono di Will Ferrell, ma i computer vedono queste immagini, come due persone completamente diverse.

Per risolvere questo problema, cercheremo di deformare ogni immagine in modo che gli occhi e le labbra siano sempre nella stessa posizione nella quale il computer ha imparato a trovarle nel dataset HOG di riferimento. In questo modo sarà molto più facile mettere a confronto i volti nelle fasi successive.

A questo scopo, utilizzeremo un algoritmo chiamato: Face Landmark Estimation. Ci sono molti modi per farlo, noi useremo l’approccio inventato nel 2014 da Vahid Kazemi e Josephine Sullivan.

L’idea di base è che su ogni volto sono presenti 68 punti specifici (chiamati punti di interesse o Landmark) — la parte superiore del mento, il bordo esterno di ciascun occhio, il bordo interno di ogni sopracciglio, etc… Non dobbiamo far altro che insegnare all’algoritmo di Machine Learning a cercare e identificare questi 68 punti su qualsiasi volto:

Le 68 punti di riferimento che saranno localizzare su ogni volto. Questa immagine è stata creata da Brandon Amos di CMU che lavora su OpenFace.

Ecco i 68 punti identificati nella nostra immagine di riferimento:

NOTA: i filtri 3D di SnapChat si basano esattamente su questo concetto

Ora che sappiamo dove sono gli occhi e la bocca, faremo semplicemente ruotare, scalare e traslare l’immagine in modo che gli occhi e la bocca siano sempre orientati nel miglior modo possibile. Tutto questo però, facendo attenzione a non entrare nel campo delle trasfigurazioni 3D che non farebbero altro che complicare il nostro processo.

Utilizzeremo solamente trasformazioni di immagine semplici come la rotazione e il ridimensionamento che conservino il parallelismo tra le linee (chiamate anche trasformazioni affini):

Ora, a prescindere dalla direzione in cui è girata la persona nella foto, siamo in grado di centrare gli occhi e la bocca più o meno nella stessa posizione al centro dell’immagine.

Se volete provare questo passaggio da soli utilizzando Python e dlib, ecco il codice per la ricerca di punti di riferimento ed il codice per trasformare l’immagine utilizzando i punti di riferimento.

Terzo passaggio: codificare le facce

Ora siamo arrivati al nocciolo del problema — ovvero dove le cose si fanno davvero interessanti!

L’approccio più semplice per affrontare il riconoscimento facciale è quello di confrontare direttamente il volto sconosciuto che abbiamo trovato nel secondo passaggio, con tutte le foto di persone che sono già state identificate in precedenza. Quando troviamo un volto già identificato che assomigli al volto che stiamo cercando di identificare, dovremmo aver la persona che stiamo cercando.

Sembra una buona idea, giusto?

Sbagliato! In realtà questo approccio ha un grosso problema. Un sito come Facebook con miliardi di utenti e un trilione di foto non può scorrere ogni faccia taggata in precedenza per confrontarla con ogni foto che viene caricata. Ci vuole troppo tempo mentre siti come Facebook hanno bisogno identificare volti in millisecondi e non ore.

Abbiamo bisogno di un modo per estrarre alcune misure di base da ogni faccia. Cosi facendo saremo in grado di comparare queste misure di base con le misure di base di altri volti già taggati. Ad esempio, potremmo misurare la dimensione di ogni orecchio, la distanza tra gli occhi, la lunghezza del naso, etc.. Se hai mai visto almeno un episodio di CSI, sai di cosa sto parlando:

Proprio come in Tv #scienza

Il modo più affidabile per misurare una faccia

Ok, quindi, quali misure dovremmo raccogliere da ogni faccia per costruire il nostro database di volti noti? Dimensioni delle orecchie? Lunghezza del naso? Colore degli occhi? Qualcos’altro?

In realtà le misure che sembrano ovvie per noi esseri umani (come il colore degli occhi) in realtà non hanno nessun senso per un computer che analizza le immagini un pixel alla volta. I ricercatori hanno concluso che l’approccio più accurato è quello di lasciare il computer libero di decidere quali misurazioni siano più appropriate da raccogliere.

Gli algoritmi di Deep Learning sono molto più efficaci degli esseri umani nel decidere quali elementi di un volto abbia senso prendere in considerazione per massimizzare la velocità alla quale il sistema è in grado di comparare e riconoscere i volti.

La soluzione è quella di costruire un Deep Convolutional Neural Network (proprio come abbiamo fatto nella parte 3). Ma invece di insegnare al Neural Network a riconoscere uccelli all’interno di un immagine, come abbiamo fatto l’ultima volta, questa volta gli insegneremo a generare 128 misurazioni per ogni faccia.

Il processo di apprendimento del Neural Network lavora analizzando 3 immagini contemporaneamente:

  1. Un’immagine di insegnamento che contenga il volto di una persona conosciuta
  2. Un’altra immagine della stessa persona conosciuta
  3. Una foto di una persona completamente diversa

A questo punto l’algoritmo esamina le misure che sta generando per ciascuna di queste tre immagini. E poi aggiusta i pesi della Rete Neurale in modo da assicurarsi che le misure generate per le facce # 1 e # 2 siano leggermente più vicine, mentre le misure per le facce # 2 e # 3 siano leggermente più distanti:

Dopo aver ripetuto questo passo milioni di volte per milioni di immagini di migliaia di persone diverse, la Rete Neurale impara a generare in modo affidabile 128 misurazioni per ogni persona. Ogni dieci immagini diverse della stessa persona l’algoritmo dovrebbe dare più o meno le stesse misure.

Gli esperti di Machine Learning chiamano questo insieme di 128 misurazioni: Embeddings.

L’idea di ridurre dati grezzi complessi come un’immagine in un elenco di numeri generati dal computer è molto comune nell’ambito del Machine Learning (soprattuto per la traduzione delle lingue). L’approccio per le facce che stiamo usando è stato inventato nel 2015 dai ricercatori di Google, ma ne esistono molti altri.

Ricodificare le nostre informazioni in un volto specifico

Questo processo basato sulla creazione di un Convolutional Neural Network richiede un sacco di dati e di allenamento. Anche con una costosa scheda video NVidia Telsa, ci vogliono circa 24 ore di formazione continua per ottenere un buon risultato.

Ma una volta che la rete è stata addestrata, può generare misurazioni per ogni faccia, anche quelle che non ha mai visto prima! Quindi, l’allenamento del network va fatto una volta sola. Fortunatamente per noi, i genietti di OpenFace lo hanno già fatto al posto nostro e hanno reso pubbliche molte reti pre-addestrate che possiamo usare direttamente. Grazie Brandon Amos e squadra!

A questo punto, tutto quello che rimane da fare per ottenere le 128 misurazioni per ogni faccia è processare le immagini dei volti attraverso i Neural Networks pre-formati da OpenFace.

Ecco le misure per la nostra immagine di prova:

Quali parti del viso sono rappresentate da questi 128 numeri? In realtà nessuno ne ha la più pallida idea e questo non ha ha nessuna importanza. Tutto ciò che ci interessa è che la Rete Neurale generi quasi gli stessi numeri ogni volta che nelle immagini è rappresentata la stessa persona.

Se volete provare da soli, OpenFace fornisce uno script LUA che genera gli embeddings per tutte le immagini contenute in una cartella e li salva in formato CSV. Si usa cosī.

Fase 4: Trovare il nome della persona dalla codifica

L’ultimo passaggio è in realtà quello più semplice di tutti. E’ sufficiente trovare la persona nel nostro database di persone note in base alle misure definite dal Network.

È possibile farlo utilizzando algoritmo di Machine Learning volto alla classificazione di dati. Non sono necessari trucchi magici di Deep Learning in quest’ultimo passaggio. Basta usare un semplice classificatore SVM lineare, ma un sacco di altri algoritmi di classificazione potrebbero funzionare allo stesso modo.

E’ sufficiente addestrare un classificatore a prendere le misure da un’immagine e dire a quale persona conosciuta corrisponda la sequenza di 128 numeri più simile. L’esecuzione di questo classificatore è velocissima, si parla di millisencondi. Il risultato è il nome della persona!

Mettiamo alla prova il nostro sistema!

In primo luogo, ho allenato un classificatore con le 128 misurazioni di circa 20 immagini di Will Ferrell, Chad Smith e Jimmy Falon:

Poi ho applicato il classificatore su ogni fotogramma del famoso video di YouTube di Will Ferrell e Chad Smith fingendo di essere l’un l’altro nello show di Jimmy Fallon:

Funziona!!!

Funziona! E guarda come funziona bene per le facce in diverse pose — anche quando orientate lateralmente!

Prova da solo

Rivediamo i passaggi che abbiamo seguito:

  1. Codifica una foto utilizzando l’algoritmo HOG per creare una versione semplificata dell’immagine. Usando questa immagine semplificata, cerca nell’immagine la parte che assomigli di più alla codifica generica di un viso HOG .
  2. Interpreta la posa del volto trovando i principali punti di riferimento sulla faccia. Una volta trovati, usali per deformare l’immagine in modo che gli occhi e la bocca siano centrati.
  3. Passare l’immagine del volto centrato attraverso una rete neurale che sa come misurare le caratteristiche del viso e salvare le 128 misurazioni che ne risultano.
  4. Guardando tutti i volti che sono stati misurati in passato, trovare quale persona ha le misure più vicine alla misurazione generata nel passaggio precedente. Et voilá!

Ora che sapete come funziona, ecco le istruzioni dall’inizio alla fine di come eseguire l’intero processo di riconoscimento facciale sul proprio computer utilizzando OpenFace:


Vai alla parte 5: Traduzione multilingua con il Deep Learning e la magia del Sequence-to-Sequence

Qui invece trovi le traduzioni della parte 1, parte 2, parte 3 e parte 5. Le parti 6 e 7 sono in fase di traduzione.

Puoi trovarmi su Twitter @giovannitoschi, scrivermi per mail o cercarmi su Linkedin.


Nota: questa è una traduzione dell’articolo “Machine Learning is Fun!” — part 4 scritto da Adam Geitgey.

L’articolo originale in inglese si trova qui mentre per i chi preferisce c’e anche la versione 普通话

Se ti è piaciuto l’articolo, considera di iscriverti alla mailing list di Adam Geitgey: Il Machine Learning” è divertente! Adam manda mail solo quando ha qualcosa di nuovo e interessante da condividere.

Puoi seguire Adam Geitgey su Twitter @ageitgey, scrivergli direttamente per email o cercarlo su linkedin.

We’re a team of bot creatives and AI scientists with one common goal:

blowing business objectives out of the water with bots and cognitive solutions