PROGETTO DEL CORSO DI VISIONE E PERCEZIONE PARTE 2 RICONOSCIMENTO DI TARGHE AUTOMOBILISTICHE Scopo del progetto Il progetto ha come obiettivo quello di riconoscere il testo di una targa automobilistica a partire dall immagine della targa stessa. Un esempio di immagine di input è il seguente: Il programma mostra in output una stringa rappresentante il testo della targa. Fasi principali dell operazione di riconoscimento Il processo di riconoscimento consta di tre passi fondamentali: binarizzazione e ottimizzazione segmentazione confronto dei caratteri tramite SIFT Il passo di binarizzazione consiste nell assegnare ai pixel con valore inferiore ad una determinata soglia del grigio il valore 0 (nero), mentre agli altri il valore 1 (bianco). L immagine così ottenuta è però affetta da disturbi quali bande nere orizzontali e verticali (in particolare ai margini dell immagine, per via dell ombra proiettata dal vano porta targa), macchie nere ecc. Per ovviare a tale inconveniente l immagine viene sottoposta ad un ulteriore passo di ottimizzazione, nel quale si eliminano le bande nere orizzontali effettuando un controllo sulla dimensione del più lungo segmento nero presente in ciascuna linea orizzontale dell immagine: se tale dimensione risulta essere maggiore di una certa soglia, allora siamo in presenza di una linea nera o di una congiunzione tra due caratteri, che va in ogni caso eliminata dato che comprometterebbe il buon esito della segmentazione. Un successivo passo di dilatazione, seguito da uno di erosione (che essendo effettuati sull immagine a testo nero su sfondo bianco, corrisponderebbero
logicamente a un passo di erosione seguito da uno di dilatazione) permette di eliminare i disturbi minori. L output di questa fase è mostrato nell immagine seguente: Il passo di segmentazione consente di isolare i vari caratteri della targa e di ritagliarli dall immagine. Questo passo viene effettuato determinando area e bounding box di ciascun blob presente nell immagine binarizzata; vengono quindi scartati i blob la cui area sia inferiore al 60% del valore medio delle aree, il che permette di eliminare eventuali stemmi presenti sull immagine o altri elementi puntiformi trascurabili. Un ulteriore controllo sul rapporto tra le dimensioni dei bounding box permette di eliminare anche eventuali bande orizzontali non scartate nel precedente passo di ottimizzazione perché di entità minima, nonché le bande verticali. A questo punto, utilizzando le coordinate dei diversi bounding box precedentemente determinate (variate leggermente in modo da espandere i bounding box così da evitare di perdere i keypoints ai bordi), si procede a ritagliare i caratteri dall immagine originale. A valle di questa fase si ottiene il seguente risultato: Il passo finale di riconoscimento dei caratteri prevede l applicazione dell algoritmo di Lowe per il calcolo delle SIFT a ciascun segmento restituito dal passo di segmentazione; i keypoints determinati vengono quindi confrontati con le entry di un database che mantiene i keypoints relativi alle immagini campione di ciascun carattere. Il carattere nel database i cui keypoints presentano il maggior numero di match con quelli del segmento in analisi viene scelto. Si è deciso di applicare le SIFT sulle immagini originali anziché su quelle binarizzate poiché nel secondo caso, pur trovando un numero considerevolmente maggiore di keypoints, c era un tasso molto alto di falsi match, il che portava a risultati inaccettabili nel riconoscimento.
Pur con questi accorgimenti si è notato che il programma continuava a commettere alcuni errori di riconoscimento quali lo scambio di lettere per cifre e viceversa, nel caso di cifre e lettere simili. Sebbene la regolamentazione italiana in materia di targhe automobilistiche escluda l utilizzo di alcune lettere (I, O, Q, U) proprio per evitare problemi di questo tipo, alcuni errori persistevano (come ad esempio B-8) e si è pertanto deciso di creare due database distinti di cui uno per le cifre ed uno per le lettere, il che ha portato anche un guadagno in efficienza: in questo modo infatti si evitano molti confronti inutili. Per quanto riguarda i parametri con cui viene eseguito l algoritmo per il calcolo delle SIFT, i risultati migliori sono stati ottenuti variando due dei valori di default: il parametro contrast_threshold (default 0.03, impostato a 0.003) e curvature_threshold (default 10, impostato a 100). In questo modo si è ottenuto un numero molto più elevato di keypoints e quindi un maggior numero di match. Si è visto dopo diverse prove che tali valori forniscono risultati ottimali: diminuendo ulteriormente il primo ed aumentando il secondo non si ottengono differenze significative. Permangono in ogni caso alcuni errori più lievi, come ad esempio lo scambio tra la lettera C e la G, come mostrato nell immagine seguente:
Organizzazione del progetto ed elenco delle funzioni Le funzioni sono divise in tre gruppi: Generatore database Riconoscitore targhe SIFT Generatore database Set di funzioni per la generazione dei due database di cifre e lettere function database = add_image_to_database(filename, existing_database) % ADD_IMAGE_TO_DATABASE: aggiunge un'immagine ad un database esistente % passato come argomento insieme al nome del file contenente l'immagine e % restituisce il database aggiornato. % INPUT: % - filename: nome del file contenente l'immagine da inserire nel % database % - existing_database: database esistente % OUTPUT: % - database: database aggiornato con la nuova immagine function construct_database % CONSTRUCT_DATABASE: costruisce i 2 database delle cifre e delle lettere % con i relativi index_name che mantengono per ogni immagine inserita nel % database il carattere rappresentato e servono quindi per capire a quale % cifra o lettera si riferisce l'immagine nel database. Le quattro % variabili create vengono infine salvate in un file in modo da poter % essere caricate dal programma di riconoscimento delle targhe. Riconoscitore targhe Set di funzioni rappresentante il core del progetto function BIN = binarizza(im) % BINARIZZA: presa l'immagine di una targa in scala di grigi la binarizza e % la ripulisce da rumore ed altri disturbi e restituisce la nuova immagine % creata. % INPUT: % - IM: immagine originale in scala di grigi % OUTPUT: % - BIN: immagine binarizzata e ripulita da rumore function [IM_db, pos_db, pos, result] = confronta_cifra(im, database, index_name)
% CONFRONTA_CIFRA: esegue le SIFT sull'immagine in input rappresentante un % carattere e trova le corrispondenze con il database, quindi restituisce % l'immagine nel database con maggior numero di matching, il relativo % carattere ed i vettori dei punti che 'matchano' tra immagine in input ed % immagine scelta dal database. % INPUT: % - IM: immagine (in scala di grigi) rappresentante un carattere % estrapolato dall'immagine della targa di partenza % - database: database contenente le immagini e i keypoints relativi % ai caratteri (in base alla circostanza sarà il database delle % cifre o quello delle lettere) % - index_name: vettore che mantiene per ogni immagine inserita nel % database il carattere rappresentato e serve quindi per capire % a quale cifra o lettera si riferisce l'immagine nel database % OUTPUT: % - IM_db: immagine (in scala di grigi) rappresentante un carattere % scelta tra quelle presenti nel database % - pos_db: vettore di punti di IM_db relativi ai keypoints che % 'matchano' % - pos: vettore di punti di IM relativi ai keypoints che % 'matchano' % - result: carattere rappresentato da IM_db function SEG_IM = segmenta( IM, BIN ) % SEGMENTA: trova tutti i blob dell'immagine binarizzata passata in input % e per ognuno trova Area e BoundingBox; crea quindi un cell array % contenente le immagini (in scala di grigi) rappresentanti i vari % caratteri estrapolati dall'immagine di partenza. % NB: l'insieme di blob trovati viene filtrato prendendo in considerazione % solo quelli con un'area abbastanza grande e con le giuste proporzioni % altezza/larghezza per poter essere una cifra o una lettera. % Inoltre i BoundingBox trovati sono allargati di qualche pixel per % evitare di perdere i keypoints al bordo. % INPUT: % - IM: immagine originale in scala di grigi % - BIN: immagine binarizzata e ripulita da rumore % OUTPUT: % - SEG_IM: cell array contenente le immagini (in scala di grigi) % rappresentanti i vari caratteri estrapolati dall'immagine di % partenza function varargout = main(varargin) % MAIN: questa funzione, oltre a gestire completamente l interfaccia grafica e % gli eventi ad essa associati, si occupa di invocare le altre funzioni % nell ordine opportuno per il corretto funzionamento del programma. SIFT Set di funzioni per il calcolo delle SIFT fornito durante il corso. Questo viene utilizzato dai due gruppi di funzioni precedentemente descritti.
Funzionamento del programma Per lanciare il programma occorre digitare il comando main nella command window di matlab. L interfaccia utente si presenta come nell immagine seguente:
Attraverso il menu File->Apri è possibile aprire immagini contenenti targhe. I formati supportati sono bmp, jpeg e pgm:
Una volta caricata un immagine, il programma effettua il processo di riconoscimento, visualizza in tempo reale i vari passi eseguiti e al termine del processo l output mostrato è il seguente: Nella sezione di segmentazione e riconoscimento cifre vengono visualizzate sulla prima riga i caratteri segmentati, mentre sulla seconda le entry del database che matchano con esse. Sulle immagini dei caratteri vengono anche plottati i keypoints che matchano. Bruno Aleandri 798026 Alessandro Macchioni 797334