Rilevamento di zone leggibili dalla macchina nelle immagini del passaporto
Il post sul blog di oggi non sarebbe possibile senza il membro dei guru di PyImageSearch, Hans Boone. Hans sta lavorando a un progetto di visione artificiale per rilevare automaticamente le zone leggibili dalla macchina (MRZ) nelle immagini del passaporto, proprio come la regione rilevata nell’immagine sopra.
La regione MRZ nei passaporti o carte di viaggio rientrano in due classi: Tipo 1 e Tipo 3. Gli MRZ di tipo 1 sono tre righe, ciascuna delle quali contiene 30 caratteri. Il tipo 3 MRZ ha solo due righe, ma ogni riga contiene 44 caratteri. In entrambi i casi, l’MRZ codifica le informazioni identificative di un determinato cittadino, incluso il tipo di passaporto, l’ID del passaporto, il paese di emissione, il nome, la nazionalità, la data di scadenza, ecc.
All’interno del corso PyImageSearch Guru, Hans mi ha mostrato i suoi progressi sul progetto e mi sono subito interessato. Ho sempre voluto applicare algoritmi di visione artificiale alle immagini del passaporto (principalmente solo per divertimento), ma mancava il set di dati per farlo. Date le informazioni di identificazione personale che un passaporto contiene, ovviamente non potevo scrivere un post sul blog sull’argomento e condividere le immagini che ho usato per sviluppare l’algoritmo.
Fortunatamente, Hans ha accettato di condividere alcune delle immagini del passaporto campione/campione a cui ha accesso-e ho colto al volo l’opportunità di giocare con queste immagini.
Ora, prima di arrivare lontano, è importante notare che questi passaporti non sono “reali” nel senso che possono essere collegati a un vero essere umano. Ma sono passaporti autentici che sono stati generati utilizzando nomi falsi, indirizzi, ecc. per gli sviluppatori con cui lavorare.
Potresti pensare che per rilevare la regione MRZ di un passaporto sia necessario un po ‘ di apprendimento automatico, magari usando il framework SVM + HOG lineare per costruire un “rilevatore MRZ” — ma sarebbe eccessivo.
Invece, possiamo eseguire il rilevamento MRZ utilizzando solo tecniche di elaborazione delle immagini di base come soglia, operazioni morfologiche e proprietà del contorno. Nel resto di questo post sul blog, illustrerò in dettaglio la mia opinione su come applicare questi metodi per rilevare la regione MRZ di un passaporto.
Stai cercando il codice sorgente di questo post?
Vai a destra alla sezione Download
Rilevamento di zone leggibili dalla macchina nelle immagini del passaporto
Andiamo avanti e iniziamo questo progetto. Aprire un nuovo file, denominarlo detect_mrz.py
e inserire il seguente codice:
# import the necessary packagesfrom imutils import pathsimport numpy as npimport argparseimport imutilsimport cv2# construct the argument parse and parse the argumentsap = argparse.ArgumentParser()ap.add_argument("-i", "--images", required=True, help="path to images directory")args = vars(ap.parse_args())# initialize a rectangular and square structuring kernelrectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (13, 5))sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (21, 21))
Linee 2-6 importare i nostri pacchetti necessari. Presumo che tu abbia già installato OpenCV. Avrai anche bisogno di imutils, la mia collezione di funzioni di convenienza per semplificare le operazioni di elaborazione delle immagini di base con OpenCV. È possibile installare imutils
utilizzando pip
:
$ pip install --upgrade imutils
Da lì, le linee 9-11 gestiscono l’analisi del nostro argomento della riga di comando. Abbiamo solo bisogno di un singolo interruttore qui, --images
, che è il percorso della directory contenente le immagini del passaporto che stiamo per elaborare.
Infine, le linee 14 e 15 inizializzano due kernel che utilizzeremo in seguito quando applicheremo operazioni morfologiche, in particolare l’operazione di chiusura. Per il momento, è sufficiente notare che il primo kernel è rettangolare con una larghezza di circa 3 volte maggiore dell’altezza. Il secondo kernel è quadrato. Questi kernel ci permetteranno di colmare le lacune tra i caratteri MRZ e le aperture tra le linee MRZ.
Ora che i nostri argomenti della riga di comando sono analizzati, possiamo iniziare a eseguire il loop su ciascuna delle immagini nel nostro set di dati ed elaborarle:
# loop over the input image pathsfor imagePath in paths.list_images(args):# load the image, resize it, and convert it to grayscaleimage = cv2.imread(imagePath)image = imutils.resize(image, height=600)gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# smooth the image using a 3x3 Gaussian, then apply the blackhat# morphological operator to find dark regions on a light backgroundgray = cv2.GaussianBlur(gray, (3, 3), 0)blackhat = cv2.morphologyEx(gray, cv2.MORPH_BLACKHAT, rectKernel)
Le linee 20 e 21 caricano la nostra immagine originale dal disco e la ridimensionano per avere un’altezza massima di 600 pixel. Puoi vedere un esempio di un’immagine originale qui sotto:
La sfocatura gaussiana viene applicata sulla linea 26 per ridurre il rumore ad alta frequenza. Applichiamo quindi un’operazione morfologica blackhat all’immagine sfocata in scala di grigi sulla riga 27.
Un operatore blackhat viene utilizzato per rivelare regioni scure (cioè, testo MRZ) su sfondi chiari (cioè, lo sfondo del passaporto stesso). Poiché il testo del passaporto è sempre nero su uno sfondo chiaro (almeno in termini di questo set di dati), è appropriata un’operazione blackhat. Di seguito puoi vedere l’output dell’applicazione dell’operatore blackhat:
Il passo successivo nel rilevamento MRZ consiste nel calcolare la rappresentazione della grandezza del gradiente dell’immagine blackhat utilizzando l’operatore Scharr:
# compute the Scharr gradient of the blackhat image and scale the# result into the range gradX = cv2.Sobel(blackhat, ddepth=cv2.CV_32F, dx=1, dy=0, ksize=-1)gradX = np.absolute(gradX)(minVal, maxVal) = (np.min(gradX), np.max(gradX))gradX = (255 * ((gradX - minVal) / (maxVal - minVal))).astype("uint8")
Qui calcoliamo il gradiente Scharr lungo l’asse x dell’immagine blackhat, rivelando regioni dell’immagine che non sono solo scure su uno sfondo chiaro, ma contengono anche cambiamenti verticali nel gradiente, come la regione del testo MRZ. Prendiamo quindi questa immagine sfumata e la ridimensioniamo nell’intervallo usando il ridimensionamento min / max:
Anche se non è del tutto ovvio il motivo per cui applichiamo questo passaggio, dirò che è estremamente utile per ridurre i rilevamenti MRZ falsi positivi. Senza di esso, possiamo accidentalmente contrassegnare le regioni abbellite o progettate del passaporto come MRZ. Lascerò questo come un esercizio a voi per verificare che il calcolo del gradiente dell’immagine blackhat può migliorare la precisione di rilevamento MRZ.
Il passo successivo è cercare di rilevare le linee effettive del MRZ:
# apply a closing operation using the rectangular kernel to close# gaps in between letters -- then apply Otsu's thresholding methodgradX = cv2.morphologyEx(gradX, cv2.MORPH_CLOSE, rectKernel)thresh = cv2.threshold(gradX, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
Per prima cosa, applichiamo un’operazione di chiusura usando il nostro kernel rettangolare. Questa operazione di chiusura ha lo scopo di colmare le lacune tra i caratteri MRZ. Quindi applichiamo la soglia usando il metodo di Otsu per soglia automaticamente l’immagine:
Come possiamo vedere dalla figura sopra, ciascuna delle linee MRZ è presente nella nostra mappa di soglia.
Il passo successivo è quello di chiudere gli spazi tra le linee reali, dandoci una grande regione rettangolare che corrisponde al MRZ:
# perform another closing operation, this time using the square# kernel to close gaps between lines of the MRZ, then perform a# series of erosions to break apart connected componentsthresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, sqKernel)thresh = cv2.erode(thresh, None, iterations=4)
Qui eseguiamo un’altra operazione di chiusura, questa volta usando il nostro kernel quadrato. Questo kernel viene utilizzato per colmare le lacune tra le singole linee del MRZ, dandoci una grande regione che corrisponde al MRZ. Una serie di erosioni vengono quindi eseguite per rompere i componenti collegati che potrebbero essere stati uniti durante l’operazione di chiusura. Queste erosioni sono anche utili per rimuovere piccole macchie che sono irrilevanti per l’MRZ.
Per alcune scansioni del passaporto, il confine del passaporto potrebbe essere stato attaccato alla regione MRZ durante le operazioni di chiusura. Per ovviare a ciò, impostiamo il 5% dei bordi sinistro e destro dell’immagine su zero (cioè nero):
# during thresholding, it's possible that border pixels were# included in the thresholding, so let's set 5% of the left and# right borders to zerop = int(image.shape * 0.05)thresh = 0thresh - p:] = 0
Puoi vedere l’output della nostra rimozione dei bordi qui sotto.
Rispetto alla figura 5 sopra, ora è possibile vedere che il bordo è stato rimosso.
L’ultimo passo è trovare i contorni nella nostra immagine con soglia e utilizzare le proprietà del contorno per identificare l’MRZ:
# find contours in the thresholded image and sort them by their# sizecnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)cnts = imutils.grab_contours(cnts)cnts = sorted(cnts, key=cv2.contourArea, reverse=True)# loop over the contoursfor c in cnts:# compute the bounding box of the contour and use the contour to# compute the aspect ratio and coverage ratio of the bounding box# width to the width of the image(x, y, w, h) = cv2.boundingRect(c)ar = w / float(h)crWidth = w / float(gray.shape)# check to see if the aspect ratio and coverage width are within# acceptable criteriaif ar > 5 and crWidth > 0.75:# pad the bounding box since we applied erosions and now need# to re-grow itpX = int((x + w) * 0.03)pY = int((y + h) * 0.03)(x, y) = (x - pX, y - pY)(w, h) = (w + (pX * 2), h + (pY * 2))# extract the ROI from the image and draw a bounding box# surrounding the MRZroi = image.copy()cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)break# show the output imagescv2.imshow("Image", image)cv2.imshow("ROI", roi)cv2.waitKey(0)
Sulla riga 56-58 calcoliamo i contorni (cioè i contorni) della nostra immagine con soglia. Prendiamo quindi questi contorni e li ordiniamo in base alle loro dimensioni in ordine decrescente sulla riga 59 (implicando che i contorni più grandi sono i primi nell’elenco).
Sulla linea 62 iniziamo a scorrere la nostra lista ordinata di contorni. Per ciascuno di questi contorni, calcoleremo il riquadro di delimitazione (riga 66) e lo useremo per calcolare due proprietà: il rapporto di aspetto e il rapporto di copertura. Le proporzioni sono semplicemente la larghezza del riquadro di delimitazione divisa per l’altezza. Il rapporto di copertura è la larghezza del riquadro di delimitazione divisa per la larghezza dell’immagine reale.
Usando queste due proprietà possiamo fare un controllo sulla linea 72 per vedere se stiamo esaminando la regione MRZ. L’MRZ è rettangolare, con una larghezza che è molto più grande dell’altezza. L’MRZ dovrebbe anche coprire almeno il 75% dell’immagine di input.
A condizione che questi due casi rimangano, le linee 75-84 usano le coordinate (x, y) del riquadro di delimitazione per estrarre l’MRZ e disegnare il riquadro di delimitazione sulla nostra immagine di input.
Infine, le righe 87-89 mostrano i nostri risultati.
Risultati
Per vedere il nostro rilevatore MRZ in azione, basta eseguire il seguente comando:
$ python detect_mrz.py --images examples
Di seguito è riportato un esempio di rilevamento MRZ riuscito, con l’MRZ delineato in verde:
Ecco un altro esempio di rilevamento della Zona leggibile dalla macchina in un’immagine passport utilizzando Python e OpenCV:
Non importa se la regione MRZ è in alto o in basso nell’immagine. Applicando operazioni morfologiche, estraendo i contorni e calcolando le proprietà dei contorni, siamo in grado di estrarre l’MRZ senza problemi.
Lo stesso vale per l’immagine seguente:
Proviamo un’altra immagine:
Fino ad ora abbiamo visto solo MRZ di tipo 1 che contengono tre righe. Tuttavia, il nostro metodo funziona altrettanto bene con MRZ di tipo 3 che contengono solo due righe:
Ecco un altro esempio di rilevamento di un MRZ di tipo 3:
E poi? Raccomando PyImageSearch University.
30+ classi totali * video 39h 44m * Ultimo aggiornamento: 12/2021
★★★★★ 4.84 (128 Valutazioni) * 3.000 + Studenti iscritti
Credo fermamente che se tu avessi l’insegnante giusto potresti padroneggiare la visione artificiale e l’apprendimento profondo.
Pensi che l’apprendimento della visione artificiale e dell’apprendimento profondo debba richiedere molto tempo, essere travolgente e complicato? O deve coinvolgere matematica ed equazioni complesse? O richiede una laurea in informatica?
Non è così.
Tutto ciò che serve per padroneggiare la visione artificiale e l’apprendimento profondo è che qualcuno ti spieghi le cose in termini semplici e intuitivi. Ed è esattamente quello che faccio. La mia missione è cambiare l’educazione e come vengono insegnati argomenti complessi di Intelligenza Artificiale.
Se sei serio sull’apprendimento della visione artificiale, la tua prossima tappa dovrebbe essere PyImageSearch University, il più completo computer vision, deep learning e corso OpenCV online oggi. Qui imparerai come applicare con successo e sicurezza la visione artificiale al tuo lavoro, alla tua ricerca e ai tuoi progetti. Unisciti a me in computer vision mastery.
All’interno di PyImageSearch University troverai:
- &controllo; 30+ corsi essenziali di computer vision, approfondimento, e OpenCV argomenti
- &controllo; 30+ Certificati di Completamento
- &controllo; 39h 44m di video on-demand
- &controllo; Marca nuovi corsi rilasciato ogni mese, per garantire il grado di tenere il passo con state-of-the-art tecniche
- &di controllo; Pre-configurato Jupyter Notebook in Google Colab
- &controllo; Eseguire tutti gli esempi di codice nel tuo web browser funziona su Windows, macOS e Linux (non dev ambiente di configurazione richiesto!)
- &controllo; Accesso ai repository di codice centralizzati per tutti gli oltre 500 tutorial su PyImageSearch
- & verifica; Download semplici con un solo clic per codice, set di dati, modelli pre-addestrati, ecc.
- & verifica; Accesso su cellulare, laptop, desktop, ecc.
Clicca qui per iscriverti a PyImageSearch University
Sommario
In questo post del blog abbiamo imparato come rilevare le zone leggibili dalla macchina (MRZ) nelle scansioni dei passaporti usando solo tecniche di elaborazione delle immagini di base, vale a dire:
- Soglia.
- Gradienti.
- Operazioni morfologiche (in particolare, chiusure ed erosioni).
- Proprietà del contorno.
Queste operazioni, anche se semplici, ci hanno permesso di rilevare le regioni MRZ nelle immagini senza dover fare affidamento su metodi di estrazione di funzionalità e apprendimento automatico più avanzati come Linear SVM + HOG per il rilevamento di oggetti.
Ricorda, di fronte a un impegnativo problema di visione artificiale, considera sempre il problema e le tue ipotesi! Come dimostra questo post del blog, potresti essere sorpreso di ciò che le funzioni di elaborazione delle immagini di base utilizzate in tandem possono realizzare.
Ancora una volta, un grande grazie a PyImageSearch Guru membro, Hans Boone, che ci ha fornito con queste immagini di esempio passaporto! Grazie Hans!