Aggiungiamo al nostro programma di riconoscimento facciale la capacità di riconoscere non solo lil tipo di oggetto (il volto), ma anche il relativo proprietario.
Nello scorso articolo abbiamo analizzato gli strumenti e i moduli necesssari per estrarre le informazioni necessarie al riconoscimento facciale con Python.
Oggi faremo un passo avanti, e impareremo ad usare i metodi per “riconoscere” non solo le forme all’interno delle immagini, ma anche a “taggarle”, qualora tali immagini corrispondano a qualcuno presente nel nostro archivio di riconoscimento.
Il tutto, sempre con una manciata di righe di Python.
Buon divertimento!
Il programma
Per prima cosa occorre lanciare il programma approfondito nel precedente articolo, creare e salvare un paio di volti di riferimento, sui quali eseguire i confronti (per il nostro esempio ne abbiamo salvati quattro).
Apriamo quindi il nostro programma, importiamo i moduli face_recognition, PIL e numpy (per la gestione di array complessi).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
import face_recognition from PIL import Image, ImageDraw import numpy as np # This is an example of running face recognition on a single image # and drawing a box around each person that was identified. picard_image = face_recognition.load_image_file("picard.jpg") picard_face_encoding = face_recognition.face_encodings(picard_image)[0] data_image = face_recognition.load_image_file("data.jpg") data_face_encoding = face_recognition.face_encodings(data_image)[0] worf_image = face_recognition.load_image_file("worf.jpg") worf_face_encoding = face_recognition.face_encodings(worf_image)[0] riker_image = face_recognition.load_image_file("riker.jpg") riker_face_encoding = face_recognition.face_encodings(riker_image)[0] # Create arrays of known face encodings and their names known_face_encodings = [ picard_face_encoding, data_face_encoding, worf_face_encoding, riker_face_encoding ] known_face_names = [ "Jean-Luc Picard", "Data", "Worf", "William Riker" ] # Load an image with an unknown face unknown_image = face_recognition.load_image_file("st_tng.jpg") # Find all the faces and face encodings in the unknown image face_locations = face_recognition.face_locations(unknown_image) face_encodings = face_recognition.face_encodings(unknown_image, face_locations) # Convert the image to a PIL-format image so that we can draw on top of it with the Pillow library # See http://pillow.readthedocs.io/ for more about PIL/Pillow pil_image = Image.fromarray(unknown_image) # Create a Pillow ImageDraw Draw instance to draw with draw = ImageDraw.Draw(pil_image) # Loop through each face found in the unknown image for (top, right, bottom, left), face_encoding in zip(face_locations, face_encodings): # See if the face is a match for the known face(s) matches = face_recognition.compare_faces(known_face_encodings, face_encoding) name = "Unknown" # If a match was found in known_face_encodings, just use the first one. # if True in matches: # first_match_index = matches.index(True) # name = known_face_names[first_match_index] # Or instead, use the known face with the smallest distance to the new face face_distances = face_recognition.face_distance(known_face_encodings, face_encoding) best_match_index = np.argmin(face_distances) if matches[best_match_index]: name = known_face_names[best_match_index] # Draw a box around the face using the Pillow module draw.rectangle(((left, top), (right, bottom)), outline=(0, 0, 255)) # Draw a label with a name below the face text_width = right - left text_height = bottom - (bottom - 10) draw.rectangle(((left, bottom - text_height - 10), (right, bottom)), fill=(0, 0, 255), outline=(0, 0, 255)) draw.text((left + 6, bottom - text_height - 5), name, fill=(255, 255, 255, 255)) # Remove the drawing library from memory as per the Pillow docs del draw # Display the resulting image pil_image.show() # You can also save a copy of the new image to disk if you want by uncommenting this line pil_image.save("image_with_boxes.jpg") |
Quindi carichiamo le immagini di riferimento (nel nostro caso Picard, Data, Worf e Riker, saalvate in precedenza) in due variabili espressamente create, e codifichiamole in modo che la libreria possa interpretarle correttamente.
Infine creiamo due liste che contengano una le variabili con le codifiche, l’altra i nomi delle persone relative.
Carichiamo quidi l’immagine completa contenente le mappe dei volti da riconoscere e la loro relativa codifica. Inseriamo ciascuna coppia di dati nelle relative variabili (face_locations, come ricorderete, è una lista contenente tante tuple di 4 elementi, le coordinate dei volti quanti sono i volti nelle immagini).
Convertiamo l’immagine sulla quale effettuare la ricerca in formato PIL, per potervi disegnare i simboli di riconoscimento. Creiamo poi un oggetto tavolozza per poter utilizzare tale immagine.
Iniziamo il loop di ricerca.
Con un loop, estraiamo le quattro coordinate e la codifica di ciascun volto dalla foto di gruppo, utilizzando le variabili face_locations e face_encodings create in precedenza.
Quindi confrontiamo ciascun encoding sui singoli volti con l’encoding estratto dalla foto di gruppo e azzeriamo la variabile name.
L’algoritmo conenuto in face_distance() ci permette di confrontare le similitudini tra due immagini.
Se esso troverà riscontro nella foto di confronto, fornendo true, associerà la variabile del nome a quella della persona o dell’oggetto rintracciato.
A questo punto non ci resta altro da fare che tracciare un segnalino attorno a ciascun elemento verificato, e inserire un tag con scritto il nome della persona o dell’oggetto ricercato, utilizzando l’oggetto (software) draw.
Attenzione: la versione 10 del modulo PIL non funziona con gli esempi riportati nella GIT degli sviluppatori, utilizziamo quest’altra tecnica a riga 69-70 per poter ottenere un risultato
Ed ecco l’effetto finale.
E’ infine possibile salvare su disco l’immagine di riferimento con le tracce dei volti riconosciuti.
Con un archivio di oggetti sufficientemente vasto è possibile applicare questo programma a qualsiasi immagine. E’ altresì possibile utilizzare librerie online contenenti milioni di elementi già categorizzati, ma di questo parleremo un’altra volta.
Link utili:
Join our groups on Telegram…