Riconoscimento Facciale con Python | Programmare in Python

Riconoscimento Facciale con Python

Pubblicato il 20 Dicembre 2019



Ciao a tutti ragazzi e ragazze, e benvenuti a questo nuovo tutorial di programmareinpython.it.

Oggi vedremo assieme come usare Python per effettuare operazioni di riconoscimento facciale facilmente, tramite un package chiamato face recognition.

Vedremo come sia possibile verificare che una foto ritragga o meno una determinata persona, come ad esempio me, voi stessi o un qualsiasi altro individuo scelto.

In un tutorial successivo vedremo poi come fare ciò anche direttamente tramite la webcam, ovvero vedremo come effettuare riconoscimento facciale in real time.

Passare prima per questa fase, partendo da immagini, permetterà di acquisire maggiore familiarità col package, anche per i developer con meno esperienza!

Iniziamo come sempre dall'installazione del software necessario.

Per quanto le istruzioni e i comandi che daremo siano gli stessi per qualsiasi sistema operativo, c'è da dire che face_recognition supporta ufficialmente solo Linux e Mac OS.

Fortunatamente per tutti quelli di voi che ancora usano Windows, seppur questo non sia ufficialmente supportato è disponibile una guida dedicata e potete inoltre scaricare un'immagine con tutti i package preinstallati per VMWare o VirtualBox, ovvero i famosi software per la creazione e gestione di macchine virtuali.

La prima cosa che volete provare a fare qualora vi troviate su Linux o Mac OS è quindi creare un ambiente virtuale e dare il comando "pip install face_recognition" o "pip3 install face_recognition".

Qualora non riusciate ad installare il package per via di un errore, dovrete allora assicurarvi di installare tutto il software necessario al suo utilizzo a livello del sistema operativo.

Dovrete assicurarvi di installare 'dlib', una libreria scritta in c++ contenente algoritmi di Machine Learning, utilizzata da face_recognition.

E per installare dlib... avrete bisogno anche di cmake e (probabilmente), gcc.

Su Manjaro Linux ad esempio ho dovuto installare cmake e python-dlib (con AUR abilitato) e quest'ultimo ha installato tutti i moduli Python nell'ambito dell'installazione principale a livello di sistema.

Possiamo finalmente iniziare con la scrittura del codice!

La facilità d'utilizzo dell'API fornita da face_recognition è davvero sorprendente, sopratutto considerando il fatto che questo genere di operazioni sono tutt'altro che semplici da effettuare manualmente.

Come contesto, supponiamo di avere due immagini: una contenente per certo il volto di una persona nota (nel nostro caso Enrico Mentana), e di voler verificare che questa persona sia presente o meno anche nella seconda immagine.

Una volta importato il modulo face_recognition, vogliamo caricare le due immagini da comparare usando la funzione load_image_file:


import face_recognition

known_image = face_recognition.load_image_file("enrico_mentana.jpg")
unknown_image = face_recognition.load_image_file("other.jpg")


load_image_file caricherà le due immagini come array numpy:

print(type(known_image))
print(f"{known_image=}")
# output
<class 'numpy.ndarray'>
known_image=array([[[ 55, 164, 167],
        [ 53, 162, 165],
        [ 56, 165, 168],
        ...,
        [169, 189, 200],
        [169, 189, 200],
        [169, 189, 200]],
(...)
        [ 34,  50,  66],
        [ 33,  49,  65],
        [ 31,  47,  63]]], dtype=uint8)


Ora che le immagini sono caricate e pronte per esser quindi comparate facilmente dobbiamo domandarci: come fare ciò?

Come può un algoritmo riconoscere i volti presenti in due foto, e dirci se si tratti della stessa persona?

Come esseri umani, facciamo tutto ciò a livello inconscio, grazie a un livello di intuizione affinato da milioni di anni di evoluzione.

Ebbene, nel nostro caso, l'algoritmo di Machine Learning utilizzato dal face_recognition è allenato in maniera tale da riconoscere 128 punti (detti measurements, misurazioni) in ogni viso.

Non sappiamo esattamente quali questi punti siano noi esseri umani valutiamo ad esempio occhi, orecchie, bocca, naso... ma le cose che per noi sono banali, si dimostrano spesso complesse da insegnare ad un algoritmo, e per questo motivo lasciamo a lui il compito di trovare questi punti.

Per una spiegazione più approfondita ti consiglio di dare uno sguardo a questo articolo, citato anche nel repo GitHub di face_recognition.

Passando uno di questi array numpy alla funzione face_encodings, possiamo quindi ottenere questa rappresentazione in 128 misurazioni del volto:

import face_recognition

known_image = face_recognition.load_image_file("enrico_mentana.jpg")
unknown_image = face_recognition.load_image_file("other.jpg")
known_encoding = face_recognition.face_encodings(known_image)[0]
unknown_encoding = face_recognition.face_encodings(unknown_image)[0]


Volendo, possiamo dare uno sguardo all'encoding così ottenuto, per farci un'idea più chiara di come questo appaia visivamente:


print(known_encoding)
# output:
[-0.11233788  0.0851004   0.1110497  -0.01893739 -0.08053697 -0.0858957
 -0.10455699 -0.07527749  0.0749362  -0.05087133  0.25046924 -0.08364171
 -0.22168593 -0.05065609 -0.03268618  0.13122961 -0.11662673 -0.11585327
 -0.11603787 -0.06964761 -0.01104837 -0.06330365  0.00256769  0.00111833
 -0.08768467 -0.35832414 -0.13881631 -0.15070605  0.05952905 -0.07453616
 -0.03482205  0.00854951 -0.13885909 -0.06617728  0.04388525  0.05016357
  0.02835207  0.03263851  0.24390836 -0.01745271 -0.14750871  0.0548184
  0.04611176  0.23021351  0.23018567  0.1045877   0.0168637   0.00165874
  0.07412874 -0.28702334  0.08039071  0.17411457  0.16432548  0.09768818
  0.12948139 -0.07740101  0.06346712  0.1018469  -0.1588065   0.06241526
  0.05848081 -0.12720881 -0.04169943  0.02881771  0.22134973  0.13912779
 -0.05311121 -0.04999805  0.22321707 -0.13465768 -0.01776722  0.02407345
 -0.11769787 -0.0827048  -0.26931885  0.03207767  0.42904216  0.13900565
 -0.23185894  0.00872655 -0.08789653 -0.01616874  0.0526951  -0.08056282
 -0.12515272 -0.10174762 -0.08823015  0.0268474   0.20508151 -0.04043303
  0.07147699  0.14764462  0.00624189  0.06535596  0.06227911  0.02255582
 -0.01452096 -0.1229032  -0.09229601  0.01187559  0.05720782 -0.10336162
 -0.00334224  0.06183746 -0.24879934  0.06217309 -0.01809638 -0.07467485
 -0.04503675  0.08669685 -0.00523551  0.00384739  0.19368017 -0.20686358
  0.2585125   0.23501292 -0.07462282  0.06183482  0.00615327  0.02624974
 -0.04922679 -0.0724382  -0.08653736 -0.16384755 -0.01922923 -0.00742123
 -0.00526905  0.05108431]


Ottenuti gli encoding di entrambe le immagini, possiamo ora usare la funzione compare_faces per scoprire se effettivamente, si tratti o meno della stessa persona, in entrambe le foto.

Di seguito, il codice completo che potete eseguire:

import face_recognition

known_image = face_recognition.load_image_file("enrico_mentana.jpg")
unknown_image = face_recognition.load_image_file("other.jpg")

known_encoding = face_recognition.face_encodings(known_image)[0]
unknown_encoding = face_recognition.face_encodings(unknown_image)[0]

results = face_recognition.compare_faces([known_encoding], unknown_encoding)
answer = "Si" if results[0] else "No"
print(f"L'immagine sconosciuta raffigura Enrico Mentana? { answer }")

Per rendere questo tutorial e il video allegato quanto più piacevole possibile, ho diviso il tutto in due parti... e qui di seguito puoi trovare la seconda parte!


In questa seconda parte vedremo come ottenere valori più attendibili tramite l'analisi della "distanza" tra i due volti analizzati.

Ed ecco il codice usato in questa seconda parte:


import face_recognition

known_image = face_recognition.load_image_file("volto_noto.jpg")
unknown_image = face_recognition.load_image_file("other.jpg")

known_encoding = face_recognition.face_encodings(known_image)[0]
unknown_encoding = face_recognition.face_encodings(unknown_image)[0]

face_distance = face_recognition.face_distance([known_encoding], unknown_encoding)
match = True if face_distance[0] <= 0.6 else False

print("Range Distanza: [0.0 - 1.0]")
print(f"I volti analizzati hanno una distanza di {face_distance[0]:.2} dall'immagine conosciuta")
print(f"Match: { match }")

Se preferisci GitHub, sul mio profilo GitHub qui puoi trovare il repo dedicato.

Ci vediamo nel prossimo Tutorial, e come al solito: Buono Studio, Buon Lavoro ed Happy Coding!