Rilevamento di zone leggibili dalla macchina nelle immagini del passaporto

mrz_output_04

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 imutilsutilizzando 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:

Figura 1: La nostra immagine originale del passaporto che stiamo cercando di rilevare l'MRZ in.
Figura 1: La nostra immagine originale del passaporto che stiamo cercando di rilevare l’MRZ in.

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:

Figura 2: L'applicazione dell'operatore morfologico blackhat rivela il testo MRZ nero sullo sfondo del passaporto chiaro.
Figura 2: L’applicazione dell’operatore morfologico blackhat rivela il testo MRZ nero sullo sfondo del passaporto chiaro.

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:

Figura 3: L'applicazione dell'operatore Scharr alla nostra immagine blackhat rivela le regioni che contengono forti cambiamenti verticali nel gradiente.
Figura 3: L’applicazione dell’operatore Scharr alla nostra immagine blackhat rivela regioni che contengono forti cambiamenti verticali nel gradiente.

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:

Figura 4: Applicazione di un'operazione di chiusura utilizzando un kernel rettangolare (che è più largo di quanto non sia alto) per chiudere gli spazi tra i caratteri MRZ
Figura 4: Applicare un’operazione di chiusura usando un kernel rettangolare (che è più largo di quanto non sia alto) per chiudere gli spazi tra i caratteri MRZ

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.

 Figura 5: Viene eseguita una seconda operazione di chiusura, questa volta utilizzando un kernel quadrato per chiudere gli spazi tra le singole linee MRZ.
Figura 5: Viene eseguita una seconda operazione di chiusura, questa volta utilizzando un kernel quadrato per chiudere gli spazi tra le singole linee 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.

 Figura 6: Impostazione del 5% dei pixel del bordo sinistro e destro a zero, assicurando che la regione MRZ non sia collegata al margine scansionato del passaporto.
Figura 6: Impostazione del 5% dei pixel del bordo sinistro e destro a zero, assicurando che la regione MRZ non sia collegata al margine scansionato del passaporto.

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:

Figura 7: A sinistra, abbiamo la nostra immagine di input. E sulla destra, abbiamo la regione MRZ che è stata rilevata con successo.
Figura 7: A sinistra, abbiamo la nostra immagine di input. E sulla destra, abbiamo la regione MRZ che è stata rilevata con successo.

Ecco un altro esempio di rilevamento della Zona leggibile dalla macchina in un’immagine passport utilizzando Python e OpenCV:

Figura 8: Applicazione del rilevamento MRZ a un passaporto scansionato.
Figura 8: Applicazione del rilevamento MRZ a un passaporto scansionato.

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:

Figura 9: Rilevamento di zone leggibili dalla macchina nelle immagini mediante computer vision.
Figura 9: Rilevamento di zone leggibili dalla macchina nelle immagini mediante visione artificiale.

Proviamo un’altra immagine:

 Figura 10: Ancora una volta, siamo in grado di rilevare l'MRZ nella scansione del passaporto utilizzando tecniche di elaborazione delle immagini di base.
Figura 10: Ancora una volta, siamo in grado di rilevare l’MRZ nella scansione del passaporto utilizzando tecniche di elaborazione delle immagini di base.

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:

Figura 11: Rilevamento dell'MRZ in un'immagine del passaporto di tipo 3 utilizzando Python e OpenCV.
Figura 11: Rilevamento dell’MRZ in un’immagine del passaporto di tipo 3 utilizzando Python e OpenCV.

Ecco un altro esempio di rilevamento di un MRZ di tipo 3:

Figura 12: Applicazione della visione artificiale e dell'elaborazione delle immagini per rilevare le zone leggibili dalla macchina nelle immagini.
Figura 12: Applicazione della visione artificiale e dell’elaborazione delle immagini per rilevare le zone leggibili dalla macchina nelle immagini.

E poi? Raccomando PyImageSearch University.

Informazioni sul corso:
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!

Leave a Reply

Il tuo indirizzo email non sarà pubblicato.