- Rilevamento di oggetti tramite SIFT
- Rilevamento di oggetti tramite ORB
- Istogramma dei gradienti orientati (HOG)
- Istogramma dei gradienti orientati (HOG), passo dopo passo:
- Classificatori a cascata HAAR
- Rilevamento di viso e occhi
- Rilevamento di viso e occhi in tempo reale
- Sintonizzazione dei classificatori a cascata
- Rilevamento di auto e pedoni nei video
Abbiamo iniziato con l'installazione di python OpenCV su Windows e finora abbiamo eseguito l'elaborazione di base delle immagini, la segmentazione delle immagini e il rilevamento di oggetti utilizzando Python, che sono trattati nei tutorial seguenti:
- Iniziare con Python OpenCV: installazione ed elaborazione di immagini di base
- Manipolazioni di immagini in Python OpenCV (Parte 1)
- Manipolazioni di immagini in OpenCV (Parte 2)
- Segmentazione dell'immagine utilizzando OpenCV - Estrazione di aree specifiche di un'immagine
Abbiamo anche appreso vari metodi e algoritmi per il rilevamento degli oggetti in cui sono stati identificati alcuni punti chiave per ogni oggetto utilizzando algoritmi diversi. In questo tutorial useremo questi algoritmi per rilevare oggetti della vita reale, qui useremo SIFT e ORB per il rilevamento.
Rilevamento di oggetti tramite SIFT
Qui il rilevamento degli oggetti verrà eseguito utilizzando lo streaming live della webcam, quindi se riconosce l'oggetto menzionerebbe l'oggetto trovato. Nel codice la parte principale è giocata dalla funzione chiamata rivelatore SIFT, la maggior parte dell'elaborazione viene eseguita da questa funzione.
E nell'altra metà del codice, iniziamo con l'apertura del flusso della webcam, quindi carichiamo il modello dell'immagine, ovvero l'immagine di riferimento, ovvero il programma sta effettivamente guardando attraverso il flusso della webcam.
Successivamente, acquisiamo continuamente le immagini dal flusso della webcam con l'aiuto del ciclo while infinito, quindi acquisiamo l'altezza e la larghezza corrispondenti del frame della webcam, quindi definiamo i parametri della casella della regione di interesse (ROI) in cui il nostro oggetto può adattarsi prendendo l'altezza e la larghezza corrispondenti della cornice della webcam. E poi disegniamo il rettangolo dai parametri ROI che avevamo definito sopra. Quindi finalmente ritaglia il rettangolo e inseriscilo nella parte del codice del rivelatore SWIFT.
Ora il rilevatore SIFT ha fondamentalmente due ingressi, uno è l'immagine ritagliata e l'altro è il modello di immagine che abbiamo definito in precedenza e quindi ci fornisce alcune corrispondenze, quindi le corrispondenze sono fondamentalmente il numero di oggetti o punti chiave che sono simili nell'immagine ritagliata e l'immagine di destinazione. Quindi definiamo un valore di soglia per le corrispondenze, se il valore delle corrispondenze è maggiore della soglia, inseriamo l'immagine trovata sul nostro schermo con il colore verde del rettangolo ROI.
Ora torniamo alla parte principale del codice, la funzione che si chiama rivelatore SIFT, prende l'input come due immagini una è l'immagine dove sta cercando l'oggetto e l'altra è l'oggetto che stiamo cercando di abbinare a (modello di immagine). Quindi scala di grigi la prima immagine e definisci il modello di immagine come seconda immagine. Quindi creiamo un oggetto rilevatore SIFT ed eseguiamo la funzione di rilevamento e calcolo SIFT di OpenCV, in modo da rilevare i punti chiave e calcolare i descrittori, i descrittori sono fondamentalmente i vettori che memorizzano le informazioni sui punti chiave, ed è molto importante mentre facciamo l'abbinamento tra i descrittori delle immagini.
E poi definisci il matcher basato su FLANN, non entreremo nella teoria matematica dell'abbinamento dietro di esso, ma puoi facilmente Google su di esso. Per prima cosa, definiamo l'indice kdtree a zero e poi impostiamo l'indice e i parametri di ricerca nel formato del dizionario, definiamo semplicemente l'algoritmo che useremo che è KDTREE, e il numero di alberi che useremo, più albero usiamo il più complicato diventa e più lento. E nel parametro di ricerca definire il numero di controlli, che è fondamentalmente il numero di corrispondenze che verrà completato.
Quindi crea il nostro oggetto matcher basato su FLANN caricando il parametro che abbiamo definito in precedenza che sono parametri di indice e parametri di ricerca e in base a questo crea il nostro matcher basato su FLANN, che è un matcher KNN dove KNN è K-vicini più vicini, fondamentalmente è un modo in cui cerchiamo corrispondenze e descrittori più vicini e facciamo il confronto con la costante di inizializzazione k. Ora questo abbinatore basato su FLANN restituisce il numero di corrispondenze che otteniamo.
L'abbinamento basato su FLANN è solo un'approssimazione, quindi per aumentare l'accuratezza del matcher basato su FLANN eseguiamo un test del rapporto di Lowe e quello che fa è cercare le corrispondenze dal matcher basato su flann knn e definire alcuni parametri matric che è la distanza qui, per la quale la distanza è una funzione numpy, e una volta che soddisfa i criteri, aggiungi le corrispondenze alle buone corrispondenze e restituisce le buone corrispondenze trovate, quindi il flusso video live indica il numero di corrispondenze trovate nell'angolo dello schermo.
Ora diamo un'occhiata al codice per la descrizione sopra:
import cv2 import numpy come np def sift_detector (new_image, image_template): # Funzione che confronta l'immagine di input con il template # Quindi restituisce il numero di corrispondenze SIFT tra di loro image1 = cv2.cvtColor (new_image, cv2.COLOR_BGR2GRAY) image2 = image_template # Crea Oggetto rilevatore SIFT #sift = cv2.SIFT () sift = cv2.xfeatures2d.SIFT_create () # Ottieni i punti chiave e i descrittori utilizzando i punti chiave SIFT_1 , descrittori_1 = sift.detectAndCompute (immagine1, Nessuno) punti chiave_2, descrittori_2 = sift.detectAnd Nessuno) # Definisci i parametri per il nostro Flann Matcher FLANN_INDEX_KDTREE = 0 index_params = dict (algoritmo = FLANN_INDEX_KDTREE, alberi = 3) search_params = dict (checks = 100) # Crea l'oggetto Flann Matcher flann = cv2.FlannBasedMatcher (index_params, search_params) # Ottieni corrispondenze utilizzando il metodo K-Nearest Neighbor # il risultato 'matchs' è il numero di corrispondenze simili trovate in entrambe le corrispondenze di immagini = flann.knnMatch (descriptors_1, descriptors_2, k = 2) # Memorizza le buone corrispondenze utilizzando il test del rapporto di Lowe good_matches = per m, n nelle corrispondenze: se m.distance <0.7 * n.distance: good_matches.append (m) return len (good_matches) cap = cv2.VideoCapture (0) # Carica il nostro modello di immagine, questa è la nostra immagine di riferimento image_template = cv2.imread ('phone.jpg', 0) mentre True: # Ottieni immagini dalla webcam ret, frame = cap.read () # Ottieni l'altezza e la larghezza del frame della webcam height, width = frame.shape # Definisci le dimensioni del riquadro ROI top_left_x = int (width / 3) top_left_y = int ((height / 2) + (height / 4)) bottom_right_x = int ((width / 3) * 2) bottom_right_y = int ((height / 2) - (height / 4)) # Disegna una finestra rettangolare per la nostra regione di interesse cv2.rectangle (frame, (top_left_x, top_left_y), (bottom_right_x, bottom_right_y), 255, 3) # Ritaglia la finestra di osservazione che abbiamo definito sopra cropped = frame # Capovolgi l'orientamento del frame orizzontalmente frame = cv2.flip (frame, 1) # Ottieni il numero di corrispondenze SIFT corrisponde = sift_detector (ritagliato, image_template) # Visualizza la stringa di stato che mostra il n. di corrispondenze cv2.putText (frame, str (corrisponde a), (450,450), cv2.FONT_HERSHEY_COMPLEX, 2, (0,255,0), 1) # La nostra soglia per indicare il rilevamento di oggetti # Usiamo 10 poiché il rilevatore SIFT restituisce pochi falsi positivi soglia = 10 # Se le corrispondenze superano la nostra soglia, l'oggetto è stato rilevato se corrisponde> soglia: cv2.rectangle (frame, (top_left_x, top_left_y), (bottom_right_x, bottom_right_y), (0,255,0), 3) cv2.putText (frame, 'Object Found', (50,50), cv2.FONT_HERSHEY_COMPLEX, 2, (0,255,0), 2) cv2.imshow ('Object Detector using SIFT', frame) if cv2.waitKey (1) == 13: # 13 è il tasto Invio interruzione cap.release () cv2.destroyAllWindows ()
Rilevamento di oggetti tramite ORB
Il rilevamento di oggetti utilizzando SIFT è molto interessante e preciso, poiché genera un numero molto accurato di corrispondenze in base ai punti chiave, tuttavia è brevettato e questo rende difficile utilizzarlo per le applicazioni commerciali, l'altra via d'uscita è l'algoritmo ORB per il rilevamento di oggetti.
Simile al metodo di rilevamento degli oggetti tramite SIFT in cui abbiamo diviso il programma in due parti, lo stesso verrà seguito qui.
In primo luogo, definiamo la funzione ORB_detector che prende due ingressi uno è l'immagine in streaming live proveniente dalla webcam e l'altro è il modello di immagine sulla base del quale andremo ad abbinare la nostra immagine. Quindi ridimensioniamo in scala di grigi la nostra immagine della webcam e inizializziamo il nostro rilevatore ORB, e lo impostiamo qui su 1000 punti chiave e parametri di scala di 1.2. puoi facilmente giocare con questi parametri, quindi rilevare i punti chiave (kp) e i descrittori (des) per entrambe le immagini e il secondo parametro che stiamo definendo nella funzione detectANDCompute è NESSUNO, richiede o meno l'uso della maschera immagine e lo stiamo negando qui.
Quindi passare al rilevatore in precedenza abbiamo utilizzato il matcher basato su FLANN, ma qui useremo BFMatcher e all'interno di BFMatcher definiamo due parametri uno è NORM_HAMMING e l'altro è il crossCheck il cui valore è TRUE.
Quindi calcola le corrispondenze tra quelle due immagini utilizzando i descrittori definiti sopra, che in tutto restituisce il numero di corrispondenze poiché queste corrispondenze non sono approssimative e quindi non è necessario eseguire il test di rapporto di Lowe, invece ordiniamo le corrispondenze in base alla distanza, meno la distanza più la corrispondenza è migliore (qui la distanza significa distanza tra i punti), e alla fine restituiamo il numero di corrispondenze utilizzando la funzione di lunghezza.
E nella funzione principale impostiamo la soglia su un valore molto più alto, poiché il rilevatore di sfere genera molto rumore.
Ora esaminiamo il codice per il rilevamento basato su ORB
import cv2 import numpy come np def ORB_detector (new_image, image_template): # Funzione che confronta l'immagine in ingresso con il template # Quindi restituisce il numero di corrispondenze ORB tra loro image1 = cv2.cvtColor (new_image, cv2.COLOR_BGR2GRAY) # Crea rilevatore ORB con 1000 punti chiave con un fattore di scala piramidale di 1.2 orb = cv2.ORB_create (1000, 1.2) # Rileva i punti chiave dell'immagine originale (kp1, des1) = orb.detectAndCompute (immagine1, Nessuno) # Rileva i punti chiave dell'immagine ruotata (kp2, des2) = orb.detectAndCompute (image_template, None) # Crea matcher # Nota che non stiamo più usando la corrispondenza basata su Flann bf = cv2.BFMatcher (cv2.NORM_HAMMING, crossCheck = True) # Fai corrispondenze = bf.match (des1, des2) # Ordina le partite in base alla distanza. La distanza minima # è migliore corrisponde = ordinato (corrispondenze, chiave = lambda val: val.distance) return len (corrispondenze) cap = cv2.VideoCapture (0) # Carica il nostro modello di immagine, questa è la nostra immagine di riferimento image_template = cv2.imread ('phone.jpg', 0) # image_template = cv2.imread ('images / kitkat.jpg', 0) while true: # Get webcam immagini ret, frame = cap.read () # Get altezza e la larghezza del telaio webcam altezza, width = frame.shape # Definisci le dimensioni della casella ROI (nota che alcune di queste cose dovrebbero essere al di fuori del ciclo) top_left_x = int (width / 3) top_left_y = int ((height / 2) + (height / 4)) bottom_right_x = int ((width / 3) * 2) bottom_right_y = int ((height / 2) - (height / 4)) # Disegna una finestra rettangolare per il nostro regione di interesse cv2.rectangle (frame, (top_left_x, top_left_y), (bottom_right_x, bottom_right_y), 255, 3) # Ritaglia la finestra di osservazione che abbiamo definito sopra cropped = frame # Capovolgi l'orientamento del frame orizzontalmente frame = cv2.flip (frame, 1) # Ottieni il numero di corrispondenze ORB = ORB_detector (cropped, image_template) # Visualizza la stringa di stato che mostra il numero corrente. di corrispondenze output_string = "Matches =" + str (corrisponde a) cv2.putText (frame, output_string, (50,450), cv2.FONT_HERSHEY_COMPLEX, 2, (250,0,150), 2) # La nostra soglia per indicare il rilevamento di oggetti # Per nuove immagini o condizioni di illuminazione potrebbe essere necessario sperimentare un po ' # Nota: il rilevatore ORB per ottenere le prime 1000 corrispondenze, 350 è essenzialmente una soglia di corrispondenza minima del 35% = 250 # Se le corrispondenze superano la nostra soglia allora l'oggetto è stato rilevato se corrisponde a> soglia: cv2.rectangle (frame, (top_left_x, top_left_y), (bottom_right_x, bottom_right_y), (0,255,0), 3) cv2.putText (frame, 'Object Found', (50, 50), cv2.FONT_HERSHEY_COMPLEX, 2, (0,255,0), 2) cv2.imshow ('Object Detector using ORB', frame) if cv2.waitKey (1) == 13: # 13 is the Enter Key break cap.release () cv2.destroyAllWindows ()
Istogramma dei gradienti orientati (HOG)
Ora parliamo di un diverso descrittore che è Histogram of Oriented Gradients (HOG's).
Gli HOG sono descrittori piuttosto interessanti e utili e sono ampiamente e con successo utilizzati per il rilevamento di oggetti, come visto in precedenza i descrittori di immagini come SIFT e ORB in cui dobbiamo calcolare i punti chiave e quindi dobbiamo calcolare i descrittori da quei punti chiave, gli HOG fanno quel processo diversamente. Esso rappresenta gli oggetti come un unico vettore di caratteristiche rispetto a un insieme di vettori di caratteristiche dove ognuno rappresenta un segmento dell'immagine. Significa che abbiamo una singola funzione vettoriale per l'intera immagine.
Viene calcolato da un rilevatore di finestra scorrevole su un'immagine, in cui un descrittore HOG viene calcolato per ciascuna posizione. Quindi ogni posizione viene combinata per un singolo vettore di caratteristiche.
Come SIFT, la scala dell'immagine viene regolata mediante piramide.
In precedenza abbiamo utilizzato matcher come FLANN e BFMatcher, ma gli HOG lo fanno in modo diverso con l'aiuto dei classificatori SVM (support vector machine), dove ogni descrittore HOG calcolato viene inviato a un classificatore SVM per determinare se l'oggetto è stato trovato o meno.
Ecco il link a un Great Paper di Dalal & Triggs sull'uso di HOGs for Human Detection:
Istogramma dei gradienti orientati (HOG), passo dopo passo:
La comprensione di HOG potrebbe essere piuttosto complessa, ma qui ci occuperemo solo della teoria di HOG senza approfondire la matematica ad essa correlata.
Quindi prendiamo questa foto che è un po 'pixelata e nell'angolo superiore c'è un riquadro di 8x8 pixel qui, quindi in questo riquadro calcoliamo il vettore del gradiente o gli orientamenti dei bordi su ciascun pixel. Quindi significa che in questa casella calcoliamo il vettore gradiente dell'immagine dei pixel all'interno del riquadro (sono una sorta di direzione o flusso dell'intensità dell'immagine stessa), e questo genera 64 (8 x 8) vettori gradiente che vengono quindi rappresentati come un istogramma. Quindi immagina un istogramma che rappresenta ogni vettore gradiente. Quindi, se tutti i punti o le intensità si trovassero in una direzione, l'istogramma per quella direzione diciamo 45 gradi, l'istogramma avrebbe un picco a 45 gradi.
Quindi quello che facciamo ora è dividere ogni cella in bin angolari, dove ogni bin corrisponde a una direzione del gradiente (ad esempio x, y). Nella carta Dalal e Triggs, sono stati utilizzati 9 contenitori 0-180 ° (20 ° ciascuno). Ciò riduce efficacemente 64 vettori a soli 9 valori. Quindi quello che abbiamo fatto è stato ridurre le dimensioni ma mantenere tutte le informazioni chiave necessarie.
Il passo successivo nel calcolo del maiale è la normalizzazione, normalizziamo i gradienti per garantire l'invarianza ai cambiamenti di illuminazione, cioè luminosità e contrasto.
In questa immagine, i valori di intensità sono mostrati nel quadrato secondo la rispettiva direzione e hanno tutti una differenza di 50 tra loro
∆ H = 50, ∆ v = 50; │∆│ = √50 2 +50 = 70,72, 70,72 / 100 = 0,707
Dividiamo i vettori per le magnitudini del gradiente che otteniamo 0,707 per tutti, questa è la normalizzazione.
Allo stesso modo, se cambiamo l'intensità o cambiamo il contrasto, otteniamo i valori seguenti.
∆ H = 50, ∆ v = 50; │∆│ = √50 2 +50 = 70,72, 70,72 / 100 = 0,707; ∆ H = 100, ∆ v = 100; │∆│ = √100 2 +100 = 141,42, 141,42 / 100 = 1,41
La normalizzazione non avviene a livello di cella, invece avviene a livello di blocco, quindi qui i blocchi sono fondamentalmente un gruppo di 4 celle, questo tiene conto dei blocchi vicini quindi normalizzarsi tenendo in considerazione segmenti più grandi dell'immagine.
Ora guardiamo il codice
importa numpy come np importa cv2 importa matplotlib.pyplot come plt # Carica l'immagine quindi immagine in scala di grigi = cv2.imread ('elephant.jpg') gray = cv2.cvtColor (image, cv2.COLOR_BGR2GRAY) # Mostra immagine originale cv2.imshow (' Input Image ', image) cv2.waitKey (0) #defining i parametri, la dimensione della cella e la dimensione del blocco # hxw in pixel cell_size = (8, 8) # hxw nelle celle block_size = (2, 2) # numero di bin di orientamento nbins = 9 # Uso del descrittore HOG di OpenCV # winSize è la dimensione dell'immagine ritagliata a un multiplo della dimensione della cella hog = cv2.HOGDescriptor (_winSize = (gray.shape // cell_size * cell_size, gray.shape // cell_size * cell_size), _blockSize = (block_size * cell_size, block_size * cell_size), _blockStride = (cell_size, cell_size), _cellSize = (cell_size, cell_size), _nbins = nbins) # Crea la forma dell'array numpy to create hog_features n_cells = (gray.shape // cell_size, gray.shape // cell_size) # Prima indicizziamo i blocchi per righe. # hog_feats ora contiene le ampiezze del gradiente per ogni direzione, # per ogni cella del suo gruppo per ogni gruppo. L'indicizzazione avviene per righe e poi per colonne. hog_feats = hog.compute (grigio).reshape (n_cells - block_size + 1, n_cells - block_size + 1, block_size, block_size, nbins).transpose ((1, 0, 2, 3, 4)) # Crea il nostro array di gradienti con dimensioni nbin per memorizzare gli orientamenti del gradiente gradients = np.zeros ((n_cells, n_cells, nbins)) # Crea un array di dimensioni cell_count = np.full ((n_cells, n_cells, 1), 0, dtype = int) # Normalizzazione del blocco per off_y nell'intervallo (block_size): per off_x nell'intervallo (block_size): gradienti - block_size + off_y + 1, off_x: n_cells - block_size + off_x + 1] + = \ hog_feats cell_count - block_size + off_y + 1, off_x: n_cells - block_size + off_x + 1] + = 1 # Gradienti medi gradienti / = cell_count # Traccia HOG usando Matplotlib # l'angolo è 360 / nbins * direction color_bins = 5 plt.pcolor (gradienti) plt.gca (). invert_yaxis () plt.gca (). set_aspect ('equal', regolabile = 'box') plt.colorbar () plt.show () cv2.destroyAllWindows ()
L'immagine mostra come l'immagine in ingresso viene rappresentata come rappresentazione HOG.
Classificatori a cascata HAAR
Come discusso in precedenza, possiamo estrarre le caratteristiche da un'immagine e utilizzarle per classificare o rilevare oggetti.
Cosa sono i classificatori a cascata HAAR?
Un metodo di rilevamento degli oggetti che inserisce le caratteristiche Haar in una serie di classificatori (a cascata) per identificare gli oggetti in un'immagine. Sono addestrati per identificare un tipo di oggetto, tuttavia, possiamo usarne diversi in parallelo, ad esempio rilevando occhi e volti insieme.
Spiegazione dei classificatori HAAR:
I classificatori HAAR vengono addestrati utilizzando molte immagini positive (cioè immagini con l'oggetto presente) e
immagini negative (cioè immagini senza l'oggetto presente).
Una volta ottenute quelle immagini, estraiamo le caratteristiche utilizzando finestre scorrevoli di blocchi rettangolari. Queste caratteristiche (caratteristiche HAAR) sono a valore singolo e vengono calcolate sottraendo la somma delle intensità dei pixel sotto i rettangoli bianchi dai rettangoli neri.
Tuttavia, questo è un numero ridicolo di calcoli, anche per una finestra di base di 24 x 24 pixel (180.000 funzioni generate).
Quindi i ricercatori hanno ideato un metodo chiamato immagini integrali che ha calcolato questo con quattro riferimenti di array. Tuttavia, avevano ancora 180.000 funzioni e la maggior parte di esse non aggiungeva alcun valore reale.
Il potenziamento è stato quindi utilizzato per determinare le caratteristiche più informative, con AdaBoost di Freund & Schapire, e ha trovato le caratteristiche più informative nell'immagine. Il potenziamento è il processo mediante il quale utilizziamo classificatori deboli per creare classificatori forti, semplicemente assegnando penalità ponderate più pesanti alle classificazioni errate. Ridurre le 180.000 funzionalità a 6000, che è ancora abbastanza funzionalità.
In quelle 6000 funzionalità, alcune saranno più informative di altre. Quindi, se usassimo le funzionalità più informative per verificare prima se la regione può potenzialmente avere un volto (i falsi positivi non saranno un grosso problema). In questo modo si elimina la necessità di calcolare tutte le 6000 funzioni contemporaneamente. Questo concetto è chiamato Cascade of Classifiers - per il rilevamento del viso, il metodo Viola Jones ha utilizzato 38 fasi.
Rilevamento di viso e occhi
Quindi, dopo aver acquisito alcune conoscenze teoriche sulle cascate HAAR, lo implementeremo finalmente, in modo da rendere le cose abbastanza chiare spezzeremo le lezioni in parti, prima dovremmo rilevare la faccia frontale, dopodiché ci sposteremo per rilevare la faccia frontale con occhi e infine avremmo fatto il rilevamento dal vivo del viso e degli occhi attraverso la webcam.
Quindi, per questo useremo classificatori pre-addestrati che sono stati forniti da OpenCV come file.xml, xml sta per linguaggio di markup estensibile, questo linguaggio viene utilizzato per memorizzare una grande quantità di dati, potresti persino costruire un database su di esso.
Puoi accedere a questi classificatori a questo link .
Riconoscimento facciale
Proviamo per il rilevamento del viso frontale, qui puoi avere l'accesso per la cascata del rilevatore di volti frontali. Basta estrarre il file zip per ottenere il file xml.
import numpy as np import cv2 # Indichiamo la funzione CascadeClassifier di OpenCV dove è memorizzato il nostro # classificatore (formato file XML), ricordati di mantenere il codice e il classificatore nella stessa cartella face_cascade = cv2.CascadeClassifier ('haarcascade_frontalface_default.xml') # Carica la nostra immagine quindi la converte in scala di grigi image = cv2.imread ('Trump.jpg') gray = cv2.cvtColor (image, cv2.COLOR_BGR2GRAY) # Il nostro classificatore restituisce il ROI della faccia rilevata come una tupla # Memorizza la parte superiore sinistra coordinate e le coordinate in basso a destra # restituisce l'elenco degli elenchi, che sono la posizione dei diversi volti rilevati. faces = face_cascade.detectMultiScale (grigio, 1.3, 5) # Quando non viene rilevato alcun volto, face_classifier ritorna e svuota la tupla se faces è (): print ("Nessun volto trovato") # Iteriamo attraverso il nostro array di facce e disegniamo un rettangolo # su ciascuna faccia nelle facce per (x, y, w, h) nelle facce: cv2.rectangle (immagine, (x, y), (x + w, y + h), (127,0,255), 2) cv2.imshow ('Face Detection', immagine) cv2.waitKey (0) cv2.destroyAllWindows ()
Ora combiniamo il rilevamento del viso e degli occhi insieme, puoi avere l'accesso alla cascata del rilevatore di occhi nello stesso file zip.
importa numpy come np importa cv2 face_classifier = cv2.CascadeClassifier ('haarcascade_frontalface_default.xml') eye_classifier = cv2.CascadeClassifier ('haarcascade_eye.xml') img = cv2.imread ('Trump.jpg') gray = cv2.cgt cv2.COLOR_BGR2GRAY) faces = face_classifier.detectMultiScale (gray, 1.3, 5) # Quando non vengono rilevati volti, face_classifier ritorna e svuota la tupla se faces is (): print ("No Face Found") for (x, y, w, h) nelle facce: cv2.rectangle (img, (x, y), (x + w, y + h), (127,0,255), 2) cv2.imshow ('img', img) roi_gray = grigio roi_color = img eyes = eye_classifier.detectMultiScale (roi_gray) cv2.waitKey (0) per (ex, ey, ew, eh) negli occhi: cv2.rectangle (roi_color, (ex, ey), (ex + ew, ey + eh), (255,255,0), 2) cv2.imshow ('img', img) cv2.waitKey (0) cv2.destroyAllWindows () cv2.waitKey (0)
Quindi questo codice è lo stesso tanto quanto che il codice per il rilevamento del volto, ma cascate occhio qui abbiamo aggiunto e il metodo per rilevare loro, come potete vedere abbiamo scelto il grigio scalato versione del viso come il parametro per il detectMultiScale per gli occhi, il che ci porta alla riduzione del calcolo in quanto rileveremo gli occhi solo in quella zona.
Rilevamento di viso e occhi in tempo reale
Quindi fino ad ora abbiamo eseguito il rilevamento del viso e degli occhi, ora implementiamo lo stesso con il flusso video in diretta dalla webcam. In questo faremo lo stesso rilevamento del viso e degli occhi, ma questa volta lo faremo per il live streaming dalla webcam. Nella maggior parte dell'applicazione troverai il tuo viso evidenziato con un riquadro intorno, ma qui abbiamo fatto qualcosa di diverso in modo che tu trovassi il tuo viso ritagliato e gli occhi si identifichino solo in quello.
Quindi qui stiamo importando sia il classificatore del viso che quello degli occhi e abbiamo definito una funzione per eseguire tutta l'elaborazione per il rilevamento del viso e degli occhi. Successivamente, è stato avviato lo streaming della webcam e ha chiamato la funzione di rilevamento del viso per rilevare il viso e gli occhi. Il parametro che stiamo definendo all'interno della funzione Face Detector sono le immagini continue dal live streaming della web cam
importa cv2 importa numpy come np face_classifier = cv2.CascadeClassifier ('haarcascade_frontalface_default.xml') eye_classifier = cv2.CascadeClassifier ('haarcascade_eye.xml') def face_detector (img, size = 0.5): # Converti l'immagine in scala di grigi.cv2.color (img, cv2.COLOR_BGR2GRAY) faces = face_classifier.detectMultiScale (gray, 1.3, 5) if faces is (): return img for (x, y, w, h) in faces: x = x - 50 w = w + 50 y = y - 50 h = h + 50 cv2.rectangle (img, (x, y), (x + w, y + h), (255,0,0), 2) roi_gray = grigio roi_color = img occhi = eye_classifier.detectMultiScale (roi_gray) per (ex, ey, ew, eh) negli occhi: cv2.rectangle (roi_color, (ex, ey), (ex + ew, ey + eh), (0,0,255), 2) roi_color = cv2.flip (roi_color, 1) return roi_color cap = cv2.VideoCapture (0) mentre True: ret, frame = cap.read () cv2.imshow ('Our Face Extractor', face_detector (frame)) se cv2.waitKey (1) == 13: # 13 è il tasto Invio interruzione cap.release () cv2.destroyAllWindows ()
Sintonizzazione dei classificatori a cascata
I parametri definiti all'interno di detectMultiScale diversi dall'immagine di input hanno il seguente significato
ourClassifier. detectMultiScale (immagine in ingresso, Fattore di scala, Min Neighbors)
- Fattore di scala Specifica di quanto riduciamo la dimensione dell'immagine ogni volta che ridimensioniamo. Ad esempio, nel rilevamento del volto usiamo tipicamente 1.3. Ciò significa che riduciamo l'immagine del 30% ogni volta che viene ridimensionata. Valori più piccoli, come 1.05 richiederanno più tempo per il calcolo, ma aumenteranno la velocità di rilevamento.
- Min Neighbors Specifica il numero di vicini che ogni finestra potenziale dovrebbe avere per considerarla un rilevamento positivo. In genere impostato tra 3-6. Agisce come impostazione di sensibilità, valori bassi a volte rilevano più volti su un singolo viso. Valori alti garantiranno meno falsi positivi, ma potresti perdere alcuni volti.
Rilevamento di auto e pedoni nei video
Ora rileveremo i pedoni e le auto nei video utilizzando le cascate HAAR, ma nel caso in cui nessun video venga caricato e il codice venga compilato senza errori, è necessario seguire i seguenti passaggi:
Se nessun video viene caricato dopo aver eseguito il codice, potrebbe essere necessario copiare il nostro opencv_ffmpeg.dl da : opencv \ sources \ 3rdparty \ ffmpeg per incollarlo dove è installato il tuo python, ad esempio C: \ Anaconda2
Una volta copiato, dovrai rinominare il file in base alla versione di OpenCV che stai utilizzando.eg se stai utilizzando OpenCV 2.4.13 quindi rinomina il file come: opencv_ffmpeg2413_64.dll o opencv_ffmpeg2413.dll (se stai utilizzando una macchina X86) opencv_ffmpeg310_64.dll o opencv_ffmpeg310.dll (se stai usando una macchina X86)
Per scoprire dove è installato python.exe, esegui queste due righe di codice, stamperà la posizione in cui è installato python.
import sys print (sys.executable)
Ora, se hai eseguito correttamente questi passaggi, passiamo al codice per il rilevamento dei pedoni, Puoi avere la cascata per il rilevamento dei pedoni e dal file zip allegato qui.
import cv2 import numpy as np # Crea il nostro classificatore del corpo body_classifier = cv2.CascadeClassifier ('haarcascade_fullbody.xml') # Avvia l'acquisizione video per il file video, qui stiamo usando il file video in cui verrebbero rilevati i pedoni cap = cv2.VideoCapture ('walking.avi') # Ripete in loop una volta che il video è stato caricato con successo mentre cap.isOpened (): # Leggendo ogni frame del video ret, frame = cap.read () # qui stiamo ridimensionando il frame, a metà della sua dimensione, stiamo facendo per accelerare la classificazione # poiché le immagini più grandi hanno molte più finestre su cui scorrere, quindi nel complesso stiamo riducendo la risoluzione #del video della metà è ciò che indica 0,5, e stiamo anche usando un metodo di interpolazione più veloce che è #interlinear frame = cv2.resize (frame, None, fx = 0.5, fy = 0.5, interpolation = cv2.INTER_LINEAR) gray = cv2. cvtColor (frame, cv2.COLOR_BGR2GRAY) # Passa frame al nostro classificatore del corpo bodys = body_classifier.detectMultiScale (gray, 1.2, 3) # Estrae i limiti per qualsiasi corpo identificato per (x, y, w, h) nei corpi: cv2. rettangolo (frame, (x, y), (x + w, y + h), (0, 255, 255), 2) cv2.imshow ('Pedestrians', frame) se cv2.waitKey (1) == 13: # 13 è l' interruzione del tasto Invio cap.release () cv2.destroyAllWindows ()
Dopo aver rilevato correttamente il pedone nel video, passiamo al codice per il rilevamento dell'auto, da qui puoi avere la cascata per il rilevamento dei pedoni.
import cv2 import time import numpy as np # Crea il nostro body classifier car_classifier = cv2.CascadeClassifier ('haarcascade_car.xml') # Avvia l'acquisizione video per il file video cap = cv2.VideoCapture ('cars.avi') # Esegui il ciclo una volta che il video è riuscito caricato mentre cap.isOpened (): time.sleep (.05) # Legge il primo frame ret, frame = cap.read () gray = cv2.cvtColor (frame, cv2.COLOR_BGR2GRAY) # Passa il frame al nostro classificatore di auto cars = car_classifier.detectMultiScale (gray, 1.4, 2) # Estrae i rettangoli di delimitazione per qualsiasi corpo identificato per (x, y, w, h) nelle auto: cv2.rectangle (frame, (x, y), (x + w, y + h), (0, 255, 255), 2) cv2.imshow ('Cars', frame) se cv2.waitKey (1) == 13: # 13 è il tasto Invio interruzione cap.release () cv2.destroyAllWindows ()
Hai notato che abbiamo aggiunto time.sleep (.05) , è solo un ritardo nel frame rate in modo da poter confermare che tutte le auto sono identificate correttamente, oppure puoi facilmente rimuoverlo semplicemente aggiungendo un'etichetta di commento ad esso.
Questo articolo fa riferimento al corso Master Computer Vision ™ OpenCV4 in Python con Deep Learning su Udemy, creato da Rajeev Ratan, iscriviti per saperne di più su Computer Vision e Python.