Sommario:

Riconoscimento facciale in tempo reale: un progetto end-to-end: 8 passaggi (con immagini)
Riconoscimento facciale in tempo reale: un progetto end-to-end: 8 passaggi (con immagini)

Video: Riconoscimento facciale in tempo reale: un progetto end-to-end: 8 passaggi (con immagini)

Video: Riconoscimento facciale in tempo reale: un progetto end-to-end: 8 passaggi (con immagini)
Video: Elisa Esposito ha tradito gentisosa con Gilbert Nana 2024, Luglio
Anonim
Riconoscimento facciale in tempo reale: un progetto end-to-end
Riconoscimento facciale in tempo reale: un progetto end-to-end

Nel mio ultimo tutorial esplorando OpenCV, abbiamo imparato il TRACCIAMENTO AUTOMATICO DI OGGETTI DI VISIONE. Ora utilizzeremo la nostra PiCam per riconoscere i volti in tempo reale, come puoi vedere di seguito:

Immagine
Immagine

Questo progetto è stato realizzato con questa fantastica "Libreria di Computer Vision Open Source", la OpenCV. In questo tutorial, ci concentreremo su Raspberry Pi (quindi, Raspbian come sistema operativo) e Python, ma ho anche testato il codice sul mio Mac e funziona anche bene. OpenCV è stato progettato per l'efficienza computazionale e con una forte attenzione alle applicazioni in tempo reale. Quindi, è perfetto per il riconoscimento facciale in tempo reale utilizzando una fotocamera.

Per creare un progetto completo sul Face Recognition, dobbiamo lavorare su 3 fasi ben distinte:

  1. Rilevamento volti e raccolta dati
  2. Allena il Riconoscitore
  3. Riconoscimento facciale

Lo schema a blocchi seguente riassume queste fasi:

Immagine
Immagine

Passaggio 1: Distinta base - Distinta base

Parti principali:

  1. Raspberry Pi V3 - US$ 32,00
  2. 5 Megapixel 1080p Sensore OV5647 Mini Modulo Video Fotocamera - 13,00 USD

Passaggio 2: installazione del pacchetto OpenCV 3

Installazione del pacchetto OpenCV 3
Installazione del pacchetto OpenCV 3

Sto usando un Raspberry Pi V3 aggiornato all'ultima versione di Raspbian (Stretch), quindi il modo migliore per installare OpenCV è seguire l'eccellente tutorial sviluppato da Adrian Rosebrock: Raspbian Stretch: Installa OpenCV 3 + Python sul tuo Raspberry Pi.

Ho provato diverse guide per installare OpenCV sul mio Pi. Il tutorial di Adrian è il migliore. Ti consiglio di fare lo stesso, seguendo passo passo le sue linee guida.

Una volta terminato il tutorial di Adrian, dovresti avere un ambiente virtuale OpenCV pronto per eseguire i nostri esperimenti sul tuo Pi.

Andiamo nel nostro ambiente virtuale e confermiamo che OpenCV 3 è installato correttamente.

Adrian consiglia di eseguire il comando "source" ogni volta che apri un nuovo terminale per assicurarti che le variabili di sistema siano state impostate correttamente.

sorgente ~/.profilo

Successivamente, entriamo nel nostro ambiente virtuale:

lavoro sul curriculum

Se vedi il testo (cv) che precede il tuo prompt, allora sei nell'ambiente virtuale cv:

(cv) pi@raspberry:~$Adrian richiama l'attenzione sul fatto che l'ambiente virtuale cv Python è completamente indipendente e sequestrato dalla versione Python predefinita inclusa nel download di Raspbian Stretch. Quindi, qualsiasi pacchetto Python nella directory globale dei pacchetti del sito non sarà disponibile per l'ambiente virtuale cv. Allo stesso modo, qualsiasi pacchetto Python installato nei pacchetti del sito di cv non sarà disponibile per l'installazione globale di Python

Ora, inserisci nel tuo interprete Python:

pitone

e conferma che stai eseguendo la versione 3.5 (o superiore)

All'interno dell'interprete (apparirà il ">>>"), importa la libreria OpenCV:

importa cv2

Se non vengono visualizzati messaggi di errore, OpenCV è installato correttamente SUL TUO AMBIENTE VIRTUALE PYTHON.

Puoi anche controllare la versione OpenCV installata:

cv2._versione_

Dovrebbe apparire la 3.3.0 (o una versione superiore che può essere rilasciata in futuro). Il precedente Terminal PrintScreen mostra i passaggi precedenti.

Passaggio 3: test della fotocamera

Testare la tua fotocamera
Testare la tua fotocamera

Dopo aver installato OpenCV nel tuo RPi, verifichiamo che la tua fotocamera funzioni correttamente.

Suppongo che tu abbia già installato una PiCam sul tuo Raspberry Pi.

Inserisci il seguente codice Python sul tuo IDE:

importa numpy come np

import cv2 cap = cv2. VideoCapture(0) cap.set(3, 640) # set Width cap.set(4, 480) # set Height while(True): ret, frame = cap.read() frame = cv2. flip(frame, -1) # Capovolgi la telecamera verticalmente gray = cv2.cvtColor(frame, cv2. COLOR_BGR2GRAY) cv2.imshow('frame', frame) cv2.imshow('gray', gray) k = cv2.waitKey(30) & 0xff if k == 27: # premi 'ESC' per uscire break cap.release() cv2.destroyAllWindows()

Il codice sopra catturerà il flusso video che verrà generato dalla tua PiCam, visualizzando entrambi, in modalità colore BGR e Gray.

Nota che ho ruotato la mia fotocamera verticalmente a causa del modo in cui è assemblata. Se non è il tuo caso, commenta o cancella la riga di comando "capovolgi".

In alternativa puoi scaricare il codice dal mio GitHub: simpleCamTest.py

Per eseguire, inserisci il comando:

python simpleCamTest.py

Per terminare il programma, è necessario premere il tasto [ESC] sulla tastiera.

Fare clic con il mouse sulla finestra del video, prima di premere [ESC]

L'immagine sopra mostra il risultato.

Alcuni produttori hanno riscontrato problemi durante il tentativo di aprire la fotocamera (messaggi di errore "Asserzione non riuscita"). Ciò potrebbe accadere se la fotocamera non è stata abilitata durante l'installazione di OpenCv e quindi i driver della fotocamera non sono stati installati correttamente. Per correggere, usa il comando:

sudo modprobe bcm2835-v4l2

Puoi anche aggiungere bcm2835-v4l2 all'ultima riga del file /etc/modules in modo che il driver venga caricato all'avvio.

Per saperne di più su OpenCV, puoi seguire il tutorial: loading -video-python-opencv-tutorial

Passaggio 4: rilevamento del volto

Riconoscimento facciale
Riconoscimento facciale
Riconoscimento facciale
Riconoscimento facciale

L'attività di base sul riconoscimento facciale è ovviamente "Rilevamento facciale". Prima di tutto, devi "catturare" un volto (Fase 1) per riconoscerlo, se confrontato con un nuovo volto catturato in futuro (Fase 3).

Il modo più comune per rilevare un volto (o qualsiasi oggetto) è utilizzare il "classificatore Haar Cascade"

Il rilevamento di oggetti mediante classificatori a cascata basati su funzionalità di Haar è un metodo efficace di rilevamento di oggetti proposto da Paul Viola e Michael Jones nel loro articolo "Rilevamento rapido di oggetti utilizzando una cascata potenziata di funzionalità semplici" nel 2001. Si tratta di un approccio basato sull'apprendimento automatico in cui un la funzione a cascata viene addestrata da molte immagini positive e negative. Viene quindi utilizzato per rilevare oggetti in altre immagini.

Qui lavoreremo con il rilevamento dei volti. Inizialmente, l'algoritmo ha bisogno di molte immagini positive (immagini di volti) e immagini negative (immagini senza volti) per addestrare il classificatore. Quindi dobbiamo estrarre le funzionalità da esso. La buona notizia è che OpenCV viene fornito con un trainer e un rilevatore. Se vuoi addestrare il tuo classificatore per qualsiasi oggetto come auto, aerei, ecc. puoi usare OpenCV per crearne uno. I suoi dettagli completi sono forniti qui: Formazione sul classificatore a cascata.

Se non vuoi creare il tuo classificatore, OpenCV contiene già molti classificatori pre-addestrati per viso, occhi, sorriso, ecc. Questi file XML possono essere scaricati dalla directory haarcascades.

Basta teoria, creiamo un rilevatore di volti con OpenCV!

Scarica il file: faceDetection.py dal mio GitHub.

importa numpy come np

import cv2 faceCascade = cv2. CascadeClassifier('Cascades/haarcascade_frontalface_default.xml') cap = cv2. VideoCapture(0) cap.set(3, 640) # set Width cap.set(4, 480) # set Height while True: ret, img = cap.read() img = cv2.flip(img, -1) gray = cv2.cvtColor(img, cv2. COLOR_BGR2GRAY) faces = faceCascade.detectMultiScale(gray, scaleFactor=1.2, minNeighbors=5, minSize=(20, 20)) per (x, y, w, h) nelle facce: cv2.rectangle(img, (x, y), (x+w, y+h), (255, 0, 0), 2) roi_gray = grigio[y:y+h, x:x+w] roi_color = img[y:y+h, x:x+w] cv2.imshow('video', img) k = cv2.waitKey(30) & 0xff if k == 27: # premi 'ESC' per uscire break cap.release() cv2.destroyAllWindows()

Che ci crediate o no, le poche righe di codice sopra sono tutto ciò che serve per rilevare un volto, usando Python e OpenCV.

Quando confronterai con l'ultimo codice utilizzato per testare la fotocamera, ti renderai conto che sono state aggiunte poche parti. Nota la riga sotto:

faceCascade = cv2. CascadeClassifier('Cascades/haarcascade_frontalface_default.xml')

Questa è la riga che carica il "classificatore" (che deve trovarsi in una directory denominata "Cascades/", nella directory del progetto).

Quindi, imposteremo la nostra fotocamera e all'interno del loop, caricheremo il nostro video di input in modalità scala di grigi (la stessa che abbiamo visto prima).

Ora dobbiamo chiamare la nostra funzione classificatore, passandole alcuni parametri molto importanti, come fattore di scala, numero di vicini e dimensione minima del volto rilevato.

facce = faceCascade.detectMultiScale(grigio, fattore di scala=1,2, minVicini=5, minSize=(20, 20))

In cui si,

  • grigio è l'immagine in scala di grigi in ingresso.
  • scaleFactor è il parametro che specifica di quanto viene ridotta la dimensione dell'immagine ad ogni scala dell'immagine. Viene utilizzato per creare la piramide di scala.
  • minNeighbors è un parametro che specifica quanti vicini dovrebbe avere ogni rettangolo candidato per mantenerlo. Un numero più alto dà falsi positivi più bassi.
  • minSize è la dimensione minima del rettangolo per essere considerata una faccia.

La funzione rileverà i volti sull'immagine. Successivamente, dobbiamo "segnare" i volti nell'immagine, utilizzando, ad esempio, un rettangolo blu. Questo viene fatto con questa parte del codice:

per (x, y, w, h) nelle facce:

cv2.rectangle(img, (x, y), (x+w, y+h), (255, 0, 0), 2) roi_gray = grigio[y:y+h, x:x+w] roi_color = img[y:y+h, x:x+w]

Se vengono trovati volti, restituisce le posizioni dei volti rilevati come un rettangolo con l'angolo in alto a sinistra (x, y) e con "w" come larghezza e "h" come altezza ==> (x, y, w, h). Si prega di vedere l'immagine sopra.

Una volta ottenute queste posizioni, possiamo creare una "ROI" (rettangolo disegnato) per la faccia e presentare il risultato con la funzione imshow().

Esegui lo script python sopra sul tuo ambiente python, usando il terminale Rpi:

python faceDetection.py

Il risultato:

Immagine
Immagine

Puoi anche includere classificatori per "rilevamento occhi" o anche "rilevamento sorrisi". In questi casi, includerai la funzione classificatore e il disegno del rettangolo all'interno del loop del viso, perché non avrebbe senso rilevare un occhio o un sorriso al di fuori di un viso.

Nota che su un Pi, avere più classificatori nello stesso codice rallenterà l'elaborazione, una volta che questo metodo di rilevamento (HaarCascades) utilizza una grande quantità di potenza di calcolo. Su un desktop, è più facile eseguirlo.

Sul mio GitHub troverai altri esempi:

faceEyeDetection.py

faceSmileDetection.py

faceSmileEyeDetection.py

E nell'immagine sopra, puoi vedere il risultato.

Puoi anche seguire il tutorial qui sotto per capire meglio Face Detection:

Haar Cascade Object Detection Face & Eye OpenCV Python Tutorial

Passaggio 5: raccolta dati

Raccolta di dati
Raccolta di dati
Raccolta di dati
Raccolta di dati

Prima di tutto, devo ringraziare Ramiz Raja per il suo ottimo lavoro sul Face Recognition sulle foto:

RICONOSCIMENTO VOLTO CON OPENCV E PYTHON: UNA GUIDA PER PRINCIPIANTI

e anche Anirban Kar, che ha sviluppato un tutorial molto completo utilizzando video:

RICONOSCIMENTO VOLTO - 3 parti

Consiglio vivamente di dare un'occhiata a entrambi i tutorial.

Detto questo, iniziamo la prima fase del nostro progetto. Quello che faremo qui, è partire dall'ultimo passaggio (Rilevamento del volto), creeremo semplicemente un set di dati, dove memorizzeremo per ogni ID, un gruppo di foto in grigio con la parte che è stata utilizzata per il rilevamento del volto.

Innanzitutto, crea una directory in cui sviluppi il tuo progetto, ad esempio FacialRecognitionProject:

mkdir FacialRecognitionProject

In questa directory, oltre ai 3 script python che creeremo per il nostro progetto, dobbiamo aver salvato su di essa il classificatore facciale. Puoi scaricarlo dal mio GitHub: haarcascade_frontalface_default.xml

Quindi, crea una sottodirectory in cui memorizzeremo i nostri campioni facciali e chiameremo "dataset":

set di dati mkdir

E scarica il codice dal mio GitHub: 01_face_dataset.py

importa cv2

import os cam = cv2. VideoCapture(0) cam.set(3, 640) # imposta la larghezza del video cam.set(4, 480) # imposta l'altezza del video face_detector = cv2. CascadeClassifier('haarcascade_frontalface_default.xml') # Per ogni persona, inserisci un ID faccia numerico face_id = input('\n inserisci l'ID utente end premi ==> ') print("\n [INFO] Inizializzazione acquisizione volti. Guarda la fotocamera e attendi …") # Inizializza il conteggio dei singoli volti di campionamento = 0 while(True): ret, img = cam.read() img = cv2.flip(img, -1) # capovolgi l'immagine video verticalmente gray = cv2.cvtColor(img, cv2. COLOR_BGR2GRAY) faces = face_detector.detectMultiScale(grigio, 1.3, 5) per (x, y, w, h) nelle facce: cv2.rectangle(img, (x, y), (x+w, y+h), (255, 0, 0), 2) count += 1 # Salva l'immagine catturata nella cartella dei dataset cv2.imwrite("dataset/User." + str(face_id) + '.' + str(count) + ".jpg", gray[y:y+ h, x:x+w]) cv2.imshow('image', img) k = cv2.waitKey(100) & 0xff # Premi 'ESC' per uscire dal video se k == 27: break elif count >= 30: # Prendi un campione di 30 volti e interrompi l'interruzione del video # Fai ab it of cleanup print("\n [INFO] Chiusura del programma e roba di pulizia") cam.release() cv2.destroyAllWindows()

Il codice è molto simile al codice che abbiamo visto per il rilevamento dei volti. Quello che abbiamo aggiunto è stato un "comando di input" per acquisire un ID utente, che dovrebbe essere un numero intero (1, 2, 3, ecc.)

face_id = input('\n inserisci l'ID utente e premi ==> ')

E per ognuno dei frame catturati, dovremmo salvarlo come file su una directory "dataset":

cv2.imwrite("dataset/Utente." + str(face_id) + '.' + str(count) + ".jpg", gray[y:y+h, x:x+w])

Nota che per salvare il file sopra, devi aver importato la libreria "os". Il nome di ogni file seguirà la struttura:

User.face_id.count.jpg

Ad esempio, per un utente con face_id = 1, il quarto file di esempio nella directory dataset/ sarà qualcosa del tipo:

Utente.1.4.jpg

come mostrato nella foto sopra dal mio Pi. Sul mio codice, sto catturando 30 campioni da ciascun id. Puoi cambiarlo sull'ultimo "elif". Il numero di campioni viene utilizzato per interrompere il ciclo in cui vengono catturati i campioni di volti.

Esegui lo script Python e acquisisci alcuni ID. Devi eseguire lo script ogni volta che vuoi aggregare un nuovo utente (o cambiare le foto per uno già esistente).

Passaggio 6: allenatore

Allenatore
Allenatore

In questa seconda fase, dobbiamo prendere tutti i dati dell'utente dal nostro set di dati e "addestrare" l'OpenCV Recognizer. Questo viene fatto direttamente da una specifica funzione OpenCV. Il risultato sarà un file.yml che verrà salvato in una directory "trainer/".

Quindi, iniziamo a creare una sottodirectory in cui memorizzeremo i dati addestrati:

mkdir trainer

Scarica dal mio GitHub il secondo script Python: 02_face_training.py

importa cv2

import numpy as np from PIL import Image import os # Percorso per il database delle immagini del viso path = 'dataset' requirer = cv2.face. LBPHFaceRecognizer_create() detector = cv2. CascadeClassifier("haarcascade_frontalface_default.xml"); # funzione per ottenere le immagini e i dati dell'etichetta def getImagesAndLabels(path): imagePaths = [os.path.join(path, f) for f in os.listdir(path)] faceSamples= ids = for imagePath in imagePaths: PIL_img = Image.open(imagePath).convert('L') # convertirlo in scala di grigi img_numpy = np.array(PIL_img, 'uint8') id = int(os.path.split(imagePath)[-1]. split(".")[1]) faces = detector.detectMultiScale(img_numpy) for (x, y, w, h) in faces: faceSamples.append(img_numpy[y:y+h, x:x+w]) ids.append(id) return faceSamples, ids print ("\n [INFO] Training faces. Ci vorranno alcuni secondi. Aspetta …") faces, ids = getImagesAndLabels(path) requirer.train(faces, np.array(ids)) # Salva il modello in trainer/trainer.yml riconoscer.write('trainer/trainer.yml') # riconoscer.save() ha funzionato su Mac, ma non su Pi # Stampa il numero di volti addestrati e termina la stampa del programma ("\n [INFO] {0} volti addestrati. Uscita dal programma".format(len(np.unique(ids))))

Conferma se hai la libreria PIL installata sul tuo Rpi. In caso contrario, esegui il comando seguente in Terminale:

pip installa il cuscino

Useremo come riconoscitore, il Face Recognizer LBPH (LOCAL BINARY PATTERNS HISTOGRAMS), incluso nel pacchetto OpenCV. Lo facciamo nella riga seguente:

riconoscitore = cv2.face. LBPHFaceRecognizer_create()

La funzione "getImagesAndLabels (percorso)", scatterà tutte le foto nella directory: "dataset/", restituendo 2 array: "Ids" e "faces". Con quegli array come input, "addestreremo il nostro riconoscitore":

riconosciutor.train(facce, ID)

Di conseguenza, un file chiamato "trainer.yml" verrà salvato nella directory del trainer che è stata precedentemente creata da noi.

Questo è tutto! Ho incluso l'ultima dichiarazione di stampa in cui ho visualizzato per conferma, il numero di volti dell'utente che abbiamo addestrato.

Ogni volta che si esegue la Fase 1, deve essere eseguita anche la Fase 2

Passaggio 7: Riconoscitore

Riconoscitore
Riconoscitore
Riconoscitore
Riconoscitore

Ora siamo giunti alla fase finale del nostro progetto. Qui, cattureremo un nuovo volto sulla nostra fotocamera e se questa persona ha già catturato e addestrato il suo volto, il nostro riconoscitore farà una "previsione" restituendo il suo ID e un indice, a dimostrazione della sicurezza del riconoscitore con questa corrispondenza.

Scarichiamo lo script Python della terza fase dal mio GitHub: 03_face_recognition.py.

importa cv2

import numpy as np import os requirer = cv2.face. LBPHFaceRecognizer_create() requirer.read('trainer/trainer.yml') cascadePath = "haarcascade_frontalface_default.xml" faceCascade = cv2. CascadeClassifier(cascadePath); font = cv2. FONT_HERSHEY_SIMPLEX #iniciate id contatore id = 0 # nomi relativi agli id: esempio ==> Marcelo: id=1, etc nomi = ['Nessuno', 'Marcelo', 'Paula', 'Ilza', 'Z ', 'W'] # Inizializza e avvia la cattura video in tempo reale cam = cv2. VideoCapture(0) cam.set(3, 640) # imposta la larghezza del video cam.set(4, 480) # imposta l'altezza del video # Definisce la dimensione minima della finestra per essere riconosciuto come una faccia minW = 0.1*cam.get(3) minH = 0.1*cam.get(4) mentre True: ret, img =cam.read() img = cv2.flip(img, -1) # Capovolgi verticalmente grigio = cv2.cvtColor(img, cv2. COLOR_BGR2GRAY) faces = faceCascade.detectMultiScale(gray, scaleFactor = 1.2, minNeighbors = 5, minSize = (int(minW), int(minH)),) for(x, y, w, h) nelle facce: cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 2) id, confidenza = riconoscitore.predict(grigio[y:y+h, x:x+w]) # Controlla se la fiducia è minore di loro 100 ==> "0" è corrispondenza perfetta if (fiducia < 100): id = nomi[id] confidenza = " {0}% ".format(round(100 - confidenza)) else: id = "sconosciuto" confidenza = " {0}%".format(round(100 - conf idence)) cv2.putText(img, str(id), (x+5, y-5), font, 1, (255, 255, 255), 2) cv2.putText(img, str(fiducia), (x+5, y+h-5), font, 1, (255, 255, 0), 1) cv2.imshow('camera', img) k = cv2.waitKey(10) & 0xff # Premi 'ESC' per uscire dal video if k == 27: break # Eseguire un po' di pulizia print("\n [INFO] Chiusura del programma e cose di pulizia") cam.release() cv2.destroyAllWindows()

Stiamo includendo qui un nuovo array, quindi mostreremo "nomi", invece di ID numerati:

nomi = ['Nessuno', 'Marcelo', 'Paula', 'Ilza', 'Z', 'W']

Quindi, per esempio: Marcelo farà l'utente con id = 1; Paola: id=2, ecc.

Successivamente, rileveremo un volto, come abbiamo fatto prima con il classificatore haasCascade. Avendo un volto rilevato possiamo chiamare la funzione più importante nel codice sopra:

id, confidenza = riconoscitore.predict (parte grigia della faccia)

Il riconoscitore.predict(), prenderà come parametro una porzione catturata del volto da analizzare e restituirà il suo probabile proprietario, indicando il suo id e quanta fiducia ha il riconoscitore in relazione a questa corrispondenza.

Nota che l'indice di confidenza restituirà "zero" se sarà considerato una corrispondenza perfetta

E infine, se il riconoscitore potesse prevedere un volto, mettiamo un testo sull'immagine con l'id probabile e quanto è la "probabilità" in % che la corrispondenza sia corretta ("probabilità" = 100 - indice di confidenza). In caso contrario, viene applicata un'etichetta "sconosciuto".

Di seguito una-g.webp

Immagine
Immagine

Nell'immagine sopra, mostro alcuni test fatti con questo progetto, dove ho anche usato delle foto per verificare se il riconoscitore funziona.

Passaggio 8: conclusione

Conclusione
Conclusione

Come sempre, spero che questo progetto possa aiutare gli altri a trovare la loro strada nell'eccitante mondo dell'elettronica!

Per i dettagli e il codice finale, visita il mio deposito GitHub: OpenCV-Face-Recognition

Per altri progetti, visita il mio blog: MJRoBot.org

Di seguito un assaggio di un futuro tutorial, in cui esploreremo "tracking automatico del volto e altri metodi per il rilevamento del volto":

Immagine
Immagine

Saludos dal sud del mondo!

Ci vediamo nel mio prossimo istruibile!

Grazie, Marcelo

Consigliato: