Matteo Dalponte
Anno scolastico: 2014/2015
Sistema di riconoscimento targhe
Sviluppo di un sistema di
riconoscimento targhe e
gestione degli accessi per
una zona a traffico limitato
o un parcheggio protetto
da barriera automatica
Matteo Dalponte
Tesina di maturità
Anno Scolastico 2014-2015
Matteo Dalponte
Tesina di Maturità
A.S: 2014/2015
Indice
La mia passione per l'automazione ..............................................................................3
Il sistema: Caratteristiche principali.............................................................................5
1.1 Funzionamento Generale ........................................................................................................ 5
1.2 ANPR Specifiche tecniche ........................................................................................................ 6
Hardware e il software libero ......................................................................................7
2.1 Caratteristiche Hardware: ....................................................................................................... 7
2.2 Il software progettato: ............................................................................................................ 8
2.3 Cos'è Linux? ........................................................................................................................... 10
2.4 Il Software Libero: ................................................................................................................. 10
Approfondimento .......................................................................................................12
3.1 IP camera e protocollo MJPEG .............................................................................................. 12
3.2 Python ................................................................................................................................... 13
3.3 Gestione dati OCR ................................................................................................................. 14
Il codice sorgente .......................................................................................................16
4.1 Lettura OCR e transizione dati ............................................................................................... 16
4.2 GUI Visualizzazione streaming ............................................................................................... 22
Sitografia .....................................................................................................................29
2
Matteo Dalponte
Tesina di Maturità
A.S: 2014/2015
La mia passione per l'automazione
L'automazione, il controllo remoto, la gestione delle immagini e la comunicazione dei dati
attraverso l'etere sono argomenti che da sempre mi affascinano; così tre anni fa ho deciso
di seguire un corso extrascolastico di programmazione Arduino tenuto nei laboratori di
fisica della Scuola, con l'obiettivo di imparare ad utilizzare la board Arduino.
Il corso, che ho seguito per tutto l'anno, mi ha permesso di entrare nella logica della
programmazione, di imparare le basi del linguaggio C e di confrontarmi con tante altre
persone che condividono la stessa passione.
Alla fine della terza, grazie alle competenze
acquisite durante il corso, ho sviluppato e
venduto due sistemi automatici di cui uno
per la gestione dell'energia prodotta da una
piccola centrale idroelettrica (v. foto); il
sistema costruito è incaricato di misurare i
parametri di corrente, potenza e tensione in
ingresso al pacco batterie mantenute in
carica dal generatore della turbina, visualizzarli
sul un display e fungere da regolatore di carica per le batterie.
Nel caso in cui la tensione superi un certo valore preimpostato, per esempio di notte
quando la l'energia non viene completamente utilizzata, viene attivato un boiler che ha la
duplice funzione di riportare la tensione delle batterie nel range di carica e allo stesso
tempo scaldare acqua sanitaria; in questo modo tutta l'energia prodotta dall'impianto
viene sfruttata a pieno.
Il secondo sistema sviluppato è stato progettato per integrare sul quadro strumenti di una
moto ulteriori informazioni quali il numero di giri del motore e lo stato di carica della
batteria di avviamento.
Per la lettura del numero di giri, senza integrare ulteriore sensoristica, ho scelto di
interfacciare l'apparecchio con il sistema di accensione (che pilota il l'arco elettrico della
candela), naturalmente già presente sul veicolo.
Durante l'estate, poi, è nato un nuovo progetto, il cui obiettivo era quello di controllare un
modellino di macchina da un computer e visualizzarne il video in diretta per il controllo a
distanza. Tale progetto mi ha portato alla scoperta di nuove schede (Raspberry Pi per
esempio), differenti da Arduino, e programmabili con nuovi linguaggi.
Così, da autodidatta, ho imparato le basi della programmazione in Python, il
funzionamento del sistema operativo GNU/Linux e i sistemi di gestione e trasmissione dati
via etere (Mikrotik).
Le potenzialità del controllo a distanza sono state apprezzate da un modellista che ha
intravisto la possibilità di controllare droni a distanza e di visualizzarne il video in diretta ed
in alta definizione.
3
Matteo Dalponte
Tesina di Maturità
A.S: 2014/2015
Così, assieme ad Andrea abbiamo iniziato un'avventura nel modellismo tradizionale,
imparando a guidare quadricotteri e parallelamente creando modelli intelligenti in grado di
"guidarsi da soli".
Il progetto ci ha portato alla scoperta di tecnologie sempre più evolute e per ora siamo
riusciti a creare un modello di esacottero per riprese aeree in grado di pilotarsi
completamente in modo autonomo, seguendo solamente una mappa disegnata dalla
stazione a terra.
Per le prossime migliorie è in progetto lo studio di un sistema più evoluto di gestione del
video per il controllo a distanza e la realizzazione di modelli tridimensionali di edifici e
terreni filmati.
Verso la metà di questo anno scolastico ci è stato proposto di prendere parte al progetto
Tu Sei, in collaborazione con Confindustria, così è nata l'idea di realizzare la tesina
sull'automazione di un cancello tramite un sistema di riconoscimento targhe.
Il progetto in fase di sviluppo è stato presentato alla ditta Algorab di Lavis, ma il lavoro, alla
fine, è stato svolto esclusivamente da me e dal mio compagno di classe Andrea.
Il nostro lavoro, che ha ricevuto un'ottima valutazione dalla ditta Algorab, in data 22
maggio è stato presentato alla commissione di valutazione del progetto Tu Sei, che ha
riconosciuto alla scuola una menzione speciale.
In allegato la fotocopia dell'attestato di riconoscimento della commissione e la valutazione
della ditta.
Esacottero per riprese aeree
(eliche 45 CM)
Sistema di gestione della carica
delle batterie e dell'utilizzo
dell'energia proveniente da un
piccolo impianto idroelettrico fotovoltaico stand alone
4
Matteo Dalponte
Tesina di Maturità
A.S: 2014/2015
Il sistema: Caratteristiche principali
1.1 Funzionamento Generale
Il sistema sviluppato ha come obbiettivo principale la gestione degli accessi di veicoli in
un'area riservata ad alta affluenza.
Il problema è tutt'altro che banale e dipende da numerosi fattori, primi tra tutti il costo del
sistema di gestione e la sicurezza degli accessi.
La soluzione più utilizzata ad oggi si basa su un sistema di lettura di chiavi elettroniche,
soluzione efficace e sicura, ma di costo crescente all'aumentare del numero di utenti.
L'innovazione proposta dal nostro sistema prevede un riconoscimento automatico dei
veicoli autorizzati tramite la lettura della targa.
Il riconoscimento automatico delle targhe (ANPR Automatic number plate recognition) è
una tecnologia che utilizza il riconoscimento ottico dei caratteri sulle immagini per leggere
le targhe dei veicoli.
Il sistema è solitamente utilizzato dalle forze dell'ordine per il controllo della velocità
(Tutor), come metodo di telepedaggio per gli ingressi alle autostrade, la catalogazione dei
movimenti di traffico o individui, il controllo dell'accesso a zone a traffico limitato o
l'accesso a parcheggi con barriera.
Il principio di funzionamento si basa sull’acquisizione tramite telecamera dell'immagine,
l’elaborazione e l’ottimizzazione della stessa , il riconoscimento e la
conversione in stringa del valore della targa tramite un software
OCR (optical character recognition).
Nel nostro caso il sistema
viene posto a controllo di
un ingresso
parcheggio e quindi
un secondo step è necessario al fine di verificare la
corrispondenza della stringa fornita dall'OCR con un database,
Figura1: Funzionamento generale
decidere se al veicolo è consentito l'accesso e, in caso positivo,
comandare il sistema di apertura.
Per fare tutto ciò è stato sviluppato un software, in grado di lavorare su un hardware con
potenza di calcolo medio-bassa, al fine di portare il sistema ad un buon compromesso
prezzo-qualità per fornire la possibilità di installazione anche ad utenze private ad un
prezzo accessibile.
5
Matteo Dalponte
Tesina di Maturità
A.S: 2014/2015
1.2 ANPR Specifiche tecniche
La lettura automatica del numero di targa consiste nel trasformare i pixel dell'immagine
digitale in testo ASCII della targa.
La tecnologia di riconoscimento ottico dei caratteri (OCR) utilizzata per ANPR è molto simile
alla tecnologia che consente di acquisire documenti cartacei e trasformarli in file
elettronici modificabili (software in grado di costruire documenti word da un testo
acquisito a scanner).
Ci sono sette algoritmi primari che il software deve eseguire per arrivare all'identificazione
di una targa:

Localizzazione targa - necessità di trovare e isolare la targa sull'immagine acquisita

Orientamento targa e ridimensionamento - viene corretta un'eventuale inclinazione
della targa e ne viene regolata la dimensione

Regolazione luminosità e contrasto

Segmentazione in caratteri - trova i singoli caratteri sulla targa e li divide in singoli
frame

Riconoscimento ottico dei caratteri

Analisi Sintattica / Geometrica - viene verificato se i caratteri rispettano le specifiche
per paese

Eventuale media del riconoscimento su più immagini, per produrre un risultato più
affidabile e sicuro
Il sistema di riconoscimento non è preciso al 100%, infatti presenta alcuni limiti che
possono derivare da uno o più dei seguenti fattori:






Risoluzione del video scadente, solitamente dovuta al tentativo di riconoscimento di
una targa troppo lontana, ma talvolta risultante dall'uso di una telecamera di bassa
qualità
Immagini sfocate, soprattutto se il veicolo è in movimento
Scarsa illuminazione, basso contrasto o sovraesposizione, riflessione o presenza di
ombre
Un oscuramento della targa da parte di un oggetto, molto spesso una barra di traino
o sporcizia
Caratteri differenti (i caratteri delle targhe possono variare da paese a paese)
Tecniche di elusione
E' importante sottolineare che i sistemi di riconoscimento potrebbero portare a violazioni
della normativa sulla privacy, in quanto idonei a tracciare i movimenti dei cittadini.
6
Matteo Dalponte
Tesina di Maturità
A.S: 2014/2015
Hardware e il software libero
Figura 2: Hardware Low-Cost utilizzato
2.1 Caratteristiche Hardware:
Raspberry Pi è un computer delle dimensioni di una carta
di credito e del costo medio di circa 30€.
Il prodotto nasce in un primo momento con lo scopo di
portare nelle scuole elaboratori economici, utili per
l’insegnamento dell’informatica.
Grazie al grande successo riscosso presso gli istituti scolastici più
aperti all’innovazione, la voce dell’esistenza di questo piccolo computer
campione di versatilità si è estesa generando un commercio di centinaia di migliaia di unità
e coinvolgendo i settori più disparati.
Sono stati (e sono tuttora) davvero tanti gli utenti a voler scegliere RaspberryPi, dagli
hacker più esperti
ai giovani che
Figura 3: collegamenti Hardware
desiderano
avvicinarsi al
mondo
dell’informatica, senza
spendere un capitale.
Dal punto di vista tecnico non sono le prestazioni
che fanno gridare al miracolo, ma è la buona
espandibilità dell’hardware e la sua versatilità,
unita alla versatilità dei sistemi operativi Linux che
supporta: sono questi i
fattori
che
hanno
portato ad una larga
diffusione
del
prodotto.
La scheda che abbiamo deciso di adottare per lo sviluppo e la messa in opera del progetto
si chiama Banana Pi ed è un'evoluzione del tradizionale Raspberry, meno conosciuta, un po'
più costosa, ma dalle prestazioni maggiori, fattore quest'ultimo di fondamentale
importanza per il processing video e delle immagini.
E' stato finora descritto l'hardware più importante del progetto, ma sono stati anche
utilizzati: Arduino ed una telecamera (descrizione al punto 3.1)
Inoltre è stata realizzata una scheda relay che consente di interfacciare la sensoristica già
presente sul cancello (fotocellula, barriere a pressione, chiave per apertura) con Arduino.
7
Matteo Dalponte
Tesina di Maturità
A.S: 2014/2015
2.2 Il software progettato:
Oltre all'hardware in questo progetto gioca un ruolo fondamentale il software.
Su Banana Pi è infatti necessario eseguire diversi software che devono essere coordinati e
gestiti in modo simultaneo con differenti velocità di esecuzione.
Tutto ciò viene gestito dal Kernel Linux, approfondito nella sezione 2.3 .
A grandi linee si può dire che il sistema è così strutturato:
I dati provenienti dalla telecamera su interfaccia USB vengono decodificati dal modulo di
gestione delle periferiche video interno al Kernel denominato video fot linux (V4L).
Questi dati decodificati vengono letti dal noto riproduttore video VLC che nel nostro caso,
configurato in modo adeguato, sarà incaricato di creare il flusso streaming MJPEG
(approfondimento sezione 3.1).
Il flusso viene reso accessibile sulla rete locale tramite porta ethernet per la visualizzazione
da remoto e allo stesso tempo verrà mandato al sistema di gestione fotogrammi e
riconoscimento ottico (OCR) per la conversione in stringa del valore della targa.
La stringa viene poi spedita in un "contenitore" (approfondimento sezione 3.3) che fungerà
da tramite tra l'OCR ed il software di gestione database.
Un software scritto in python (codice sorgente sezione 4.1) esegue il confronto tra la targa
letta dall'OCR e il database e, in caso di un riscontro, gestisce l'apertura del cancello ed
inserisce i dati relativi al proprietario della targa in un file di scambio.
Il file di scambio e il file del database vengono resi disponibili sulla rete locale LAN tramite
un server FTP, grazie al quale un qualsiasi computer autenticato nella rete potrà aggiungere
o eliminare le targhe dal database e leggere il file di scambio.
Su un pc della rete locale LAN viene installato un software progettato appositamente per la
gestione del database e per la visualizzazione in tempo reale dello streaming(codice
sorgente sez. 4.2).
Di seguito alcune immagini che mostrano il software di gestione database:
8
Matteo Dalponte
Tesina di Maturità
Funzionamento software schematizzato in uno schema a blocchi
9
A.S: 2014/2015
Matteo Dalponte
Tesina di Maturità
A.S: 2014/2015
2.3 Cos'è Linux?
Linux è un sistema operativo, ovvero quell'insieme di programmi essenziali
per far funzionare il computer . E' una alternativa a Windows e a MacOS,
e può essere installato al loro posto (o insieme, sullo stesso computer).
Più in generale Linux è il primo rappresentante del ("freesoftware", in
inglese), ovvero quel software distribuito con una licenza che ne
permette non solo l'utilizzo da parte di chiunque ed in qualsiasi
circostanza, ma anche la modifica, la copia e l'analisi.
Linux è un sistema operativo sviluppato da Linus Torvalds; in gergo
Figura 4: Stemma S.O. GNU/Linux
tecnico è più corretto denominare Linux come kernel, cioè cuore del sistema; attorno ad
esso girano applicazioni di varia natura che sfruttano le sue potenzialità. L'idea originaria di
Linus Torvalds fu quella di migliorare un kernel già esistente, Minix, creato per scopi
didattici da Andrew S.Tanenbaum. La particolarità di Linux è che il progetto di sviluppo
attorno al kernel è stato realizzato sia da esperti che da semplici appassionati ed hacker di
tutto il mondo, grazie al coordinamento ed alla diffusione dei dati tramite Internet.
Questa collaborazione ha portato alla nascita di un sistema operativo realmente in grado di
essere antagonista a Windows.
Il nome più corretto per indicarlo è in realtà GNU/Linux, in quanto le applicazioni
fondamentali (compilatori, editor, librerie, etc.) sono state sviluppate dalla Free Software
Foundation di Richard Stallman alla cui base c'è il progetto GNU (Gnu's not Unix), ovvero la
realizzazione di un sistema operativo libero di cui possiamo elencare le principali
caratteristiche relative alla licenza di distribuzione GPL (General Public License):

codice sorgente aperto e disponibile per la lettura e la modifica;

libera distribuzione, da parte di chiunque, sia del software che del relativo codice
sorgente;

applicazioni e prodotti derivati coperti sempre da licenza GPL (copyleft);

libero utilizzo anche per fini di natura commerciale.
2.4 Il Software Libero:
L'idea di software libero nasce agli inizi degli anni
Ottanta, quando lo sviluppo del software
cominciò a passare dalle università alle aziende
(software proprietario), ponendo un pesante
freno alla collaborazione che caratterizzava il
lavoro di gran parte dei programmatori e dei
sistemisti dell'epoca, soprattutto con i patti di
10
Figura 5: Stemma Free Software Foundation
Matteo Dalponte
Tesina di Maturità
A.S: 2014/2015
non divulgazione che le aziende facevano firmare ai programmatori assunti.
In realtà il software "commerciale" esisteva già, ma i costi elevati dell'hardware facevano
sì che il business delle aziende non fosse concentrato sul software, che era considerato una
parte naturale del prodotto, ed i cui file sorgente erano in genere di dominio pubblico.
Con il passare del tempo il software diventò sempre più complesso e difficile da realizzare e
le aziende iniziarono a non distribuire i file sorgente obbligando i propri dipendenti a non
rivelare nulla per non avvantaggiare la concorrenza; inoltre con il crollo dei costi
dell'hardware, lo sviluppo commerciale del software divenne un business notevole, ed il
codice sorgente era divenuto un investimento prezioso che poteva, da un lato far acquisire
una fetta di tale mercato in rapida crescita e dall'altro legare i propri utenti al proprio
software mantenendo il segreto sui metodi utilizzati per lo sviluppo di sistemi e
applicazioni.
In questo modo le aziende cominciarono ad utilizzare la legge sul diritto d'autore per
impedire ai concorrenti di leggere e modificare i loro prodotti, assicurandosi il controllo dei
propri clienti che, senza poter vedere e modificare il codice sorgente del software, non
potevano più adattarlo alle loro esigenze, ed erano così costretti ad acquistare servizi di
supporto dalle aziende fornitrici.
Nel 1983 Richard Stallman fondò il progetto GNU con l'intenzione di creare un sistema
operativo completamente libero. Grazie alla collaborazione di molti sviluppatori volontari,
all'uso di Internet per il coordinamento del progetto ed al kernel Linux di Linus Torvalds,
nel 1991 nacque GNU/Linux, un clone di Unix liberamente utilizzabile, modificabile e
ridistribuibile.
Il movimento per il software libero si batte, quindi, per dare agli utenti di sistemi
informatici la libertà che deriva dal software libero. Il software libero dà, a chi lo usa, il
controllo delle proprie elaborazioni informatiche, mentre il software non libero pone chi lo
usa sotto il dominio dello sviluppatore.
Secondo la Free Software Foundation, un software si può definire libero solo se garantisce
quattro "libertà fondamentali":

Libertà 1: Libertà di eseguire il programma per qualsiasi scopo.

Libertà 2: Libertà di studiare il programma e modificarlo.

Libertà 3: Libertà di ridistribuire copie del programma in modo da aiutare il
prossimo.

Libertà 4: Libertà di migliorare il programma e di distribuirne pubblicamente i
miglioramenti, in modo tale che tutta la comunità ne tragga beneficio.
11
Matteo Dalponte
Tesina di Maturità
A.S: 2014/2015
Approfondimento
3.1 IP camera e protocollo MJPEG
Il Sistema hardware è costituito da una telecamera USB che, interfacciata con VLC come
descritto nella sezione 2.2, è in grado di creare un flusso
video digitale formato M-JPEG collocato in rete su
protocollo HTTP e fisicamente trasportato tramite
cavo di rete ethernet; sfruttando questa
configurazione il sistema, a differenza della
tecnologia analogica su cavo coassiale, non risente
della perdita di qualità dell'immagine.
La scelta del tipo di formato è stata vincolata dalla
libreria incaricata di migliorare i singoli fotogrammi
delle immagini contenenti la targa.
Infatti per la sua struttura "grezza" il formato MJPEG non
Figura 6: Speciale IP camera con visore 360°
richiede processori di alto livello per comporre il flusso(nel
Banana Pi) e poi per scomporlo nuovamente in singoli fotogrammi per l'analisi(nel PC di
controllo), ma la velocità di trasmissione tra i due hardware richiesta dalla rete è
considerevole.
Il software basato sul protocollo MJPEG acquisisce dal sensore ottico singole foto
(solitamente ad una velocità di 30 al secondo), le codifica nel formato JPEG per ridurne la
qualità e la dimensione e poi le manda in sequenza al client, che visualizza il flusso video
come una sequenza di foto.
Per fare un confronto con la recentissima tecnologia H264 o MPEG2 (utilizzata per esempio
nella trasmissione della tv digitale) possiamo dire che le ultime due hanno una
compressione intraframe; ciò significa che se il fotogramma precedente conteneva la
stessa immagine del successivo frame non viene inviata al client nessuna nuova immagine
e quindi verrà mostrata l'ultima ricevuta; nel caso in cui il frame successivo cambi alcune
sue parti rispetto al precedente, il protocollo h264 prevede l'invio solo delle parti
modificate.
In questo caso, a parità di qualità di immagine, la rete viene utilizzata anche 10 volte
meno, ma sia il processore di codifica che quello di decodifica vengono utilizzati
maggiormente.
12
Matteo Dalponte
Tesina di Maturità
A.S: 2014/2015
Figura 7: Stemma del linguaggio di programmazione Python
3.2 Python
L'intero software a bordo di Banana Pi per la gestione dei caratteri
digitalizzati provenienti dall'OCR, per il confronto con il database e
per la gestione della comunicazione seriale con Arduino è
interamente scritto in python.
Analogamente è gestito con python anche il software di controllo in
grado di gestire sul Pc il database delle targhe consentite e di riprodurre il
video streaming.
Perché proprio Python e non C, Java, Visual Basik o Perl?
Python è innanzitutto un linguaggio di script pseudocompilato.
Questo significa che, similmente a Perl ed a Tcl/Tk, ogni programma sorgente deve essere
pseudocompilato da un interprete. L'interprete è un normale programma che va installato
sulla propria macchina e si occupa di interpretare il codice sorgente e di eseguirlo.
Quindi, diversamente da C++, non abbiamo una fase di compilazione che trasforma il
codice sorgente in file eseguibile, ma esiste solo il sorgente che viene eseguito
dall'interprete.
Il fatto di essere pseudocompilato rende Python un linguaggio portabile. Una volta scritto
un sorgente, esso può essere interpretato ed eseguito sulla gran parte delle piattaforme
attualmente utilizzate come Apple (Mac) o PC (Microsoft Windows e GNU/Linux),
disponendo semplicemente di una versione corretta dell'interprete.
Python non è attualmente il linguaggio di programmazione più famoso (v. Figura 8), ma
viene spesso utilizzato per creare codici sorgente destinati ad hardware tipo Raspberry Pi.
Inoltre la documentazione e le librerie a disposizione sulla rete sono numerose.
Figura 8: Statistica relativa ai linguaggi di programmazione più utilizzati (fonte: TIOBE Software)
13
Matteo Dalponte
Tesina di Maturità
A.S: 2014/2015
3.3 Gestione dati OCR
Verrà ora proposta la soluzione ad uno dei problemi riscontrati durante lo sviluppo del
progetto, tutto il restante codice sorgente è, con i relativi commenti, disponibile a seguire.
Il software optical character recognition (OCR), dopo aver effettuato la lettura
dell'immagine, deve comunicare al software di gestione database la stringa contenente il
valore della targa.
Il software ocr ed il software di gestione database e accessi sono scritti in linguaggi
differenti, quindi è necessario trovare un sistema comune per comunicare i dati.
La soluzione è l'utilizzo delle code beanstalkd. Il sistema prevede un contenitore centrale
(software beanstalkd) in cui vengono inseriti dei dati dall'alto e prelevati dal basso.
In questo modo il software che legge i dati
potrà leggerli quando vorrà scaricandoli dal
"contenitore" e non dovrà essere sempre in
ascolto.
Per la gestione di questo contenitore sono presenti diverse
librerie per tutti i linguaggi di programmazione: in questo
modo un software scritto ad esempio in C potrà caricare i dati,
mentre uno scritto in Python potrà scaricarli e, data la presenza Figura 9: Sistema di gestione code
delle code beanstalkd, il software più veloce non verrà rallentato da quello più lento.
Sarà poi necessario trasportare i dati in un formato standard facile da dividere e da
interpretare per i diversi linguaggi di programmazione.
Per la soluzione a questo secondo problema risulta particolarmente adatto il sistema JSON
(JavaScript Object Notation), un formato studiato per lo scambio dei dati in applicazioni
client-server.
Python gestisce il sistema json come una serie di librerie e dizionari.
Per capire meglio la struttura di un elemento json è necessario avere chiari i seguenti
concetti:
le liste in Python sono collezioni ordinate di oggetti, simili agli array di altri linguaggi di
programmazione come Java. In altre parole permettono di memorizzare una sequenza di
oggetti ed accedere ad essi mediante un indice.
es:
>>> lista=[1, 'html'] # lista con un intero e una stringa
(>>> significa comando eseguito direttamente nella shell,
si utilizza # in Python per aggiungere commenti )
Per recuperare un valore da una lista è sufficiente richiamare la posizione
es:
>>> lista[1]
# indicizzazione
'html'
14
Matteo Dalponte
Tesina di Maturità
A.S: 2014/2015
Un dizionario invece rappresenta una collezione “non ordinata” di oggetti. Gli oggetti
sono identificati univocamente da una chiave (generalmente una stringa) invece che
mediante un indice numerico, come avviene nelle liste.
Ogni elemento del dizionario è rappresentato da una coppia (chiave : valore), la chiave
serve per accedere all’elemento e recuperare il valore.
es:
>>> diz={'html':1, 'HTML':2, 'HTml':3}
Per recuperare un valore da un dizionario è sufficiente richiamare la posizione
es:
>>> diz['HTML']
#ottieni valore richiamando la chiave
2
Analizzando bene il json in uscita all'OCR possiamo vedere come i dati effettivamente
siano divisi in liste e dizionari.
{
"uuid": "e11ecc-6aaf-47-929-9e67",
"camera_id": 1,
"site_id": "watchtower-hq",
"img_width": 640,
"img_height": 480,
"epoch_time": 1402161050,
"processing_time_ms": 138.669163,
"results": [
{
"plate": "S11FRE",
"confidence": 77.130661,
"matches_template": 0,
"region": "",
"region_confidence": 0,
"coordinates": [
{
"x": 218,
"y": 342
},
{
"x": 407,
"y": 325
},
{
"x": 407,
"y": 413
},
{
"x": 218,
15
Matteo Dalponte
Tesina di Maturità
A.S: 2014/2015
"y": 431
}
],
"candidates": [
{
"plate": "S11FRE",
"confidence": 77.130661,
"matches_template": 0
},
{
"plate": "S11ERE",
"confidence": 75.496307,
"matches_template": 0
}
]
}
]
}
Per esempio se noi dovessimo recuperare il numero di targa dovremmo entrare nel primo
dizionario e richiamare i dati tramite la chiave "results", poi recuperare i dati contenuti
nella posizione 0 della lista, entrare nel nuovo dizionario e richiamare i dati tramite la
chiave "plate"
es:
>>> json["results"][0]["plate"]
'S11FRE'
# JSON è la variabile che contiene il JSON
Il codice sorgente
A titolo di chiarimento verranno di seguito analizzati in dettaglio due dei quattro codici
sorgente da noi realizzati per il funzionamento del sistema
4.1 Lettura OCR e transizione dati
Il seguente codice, scritto in Python, viene eseguito su Banana Pi e ha la funzione di leggere
i dati provenienti dall'ocr, confrontarli con il database, inviare il segnale di apertura ad
Arduino e scrivere un file di transizione informazioni.
16
Matteo Dalponte
Tesina di Maturità
1.
import serial
2.
import beanstalkc
3.
import json
4.
import os
A.S: 2014/2015
5.
6.
immx=0
7.
immy=0
8.
buffer=0
9.
valstanga = 0
10.
11.
open_alprd = "/home/bananapi/openalpr/src/build/alprd --config /etc/openalpr"
12.
os.system("pkill alprd")
13.
os.system(open_alprd)
14.
15.
16.
17.
18.
19.
20.
21.
try:
ser = serial.Serial('/dev/ttyUSB0', 9600, timeout=1)
except:
try:
ser = serial.Serial('/dev/ttyUSB1', 9600, timeout=1)
except:
try:
22.
23.
ser = serial.Serial('/dev/ttyACM0', 9600, timeout=1)
except:
24.
pass
25.
26.
beanstalk = beanstalkc.Connection(host='localhost', port=11300)
27.
beanstalk.watch('alprd')
28.
29.
while True:
30.
31.
f = open('/home/bananapi/Desktop/Database.conf','r')
32.
s=str(f.readlines())
33.
dati=eval(s)
34.
35.
job = beanstalk.reserve()
36.
jobb = job.body
37.
job.delete()
38.
d = json.loads(jobb)
39.
40.
time = str(d["processing_time_ms"])
41.
targa = str(d["results"][0]["plate"])
42.
x1 = str(d['results'][0]['coordinates'][0]['x'])
43.
y1 = str(d['results'][0]['coordinates'][0]['y'])
44.
x2 = str(d['results'][0]['coordinates'][1]['x'])
45.
y2 = str(d['results'][0]['coordinates'][1]['y'])
46.
x3 = str(d['results'][0]['coordinates'][2]['x'])
47.
y3 = str(d['results'][0]['coordinates'][2]['y'])
48.
x4 = str(d['results'][0]['coordinates'][3]['x'])
49.
y4 = str(d['results'][0]['coordinates'][3]['y'])
50.
immx = str(d['img_width'])
51.
immy = str(d['img_height'])
17
Matteo Dalponte
Tesina di Maturità
A.S: 2014/2015
52.
53.
54.
for num in range(0,40):
55.
try:
56.
try:
57.
number_lines = len(dati)
58.
for i in range(0, number_lines):
59.
diz1 = eval(dati[i])
60.
targa_diz = diz1['targa']
61.
if (str(d['results'][0]['candidates'][num]['plate']) ==
targa_diz):
62.
try:
63.
ser.write("1")
64.
except:
65.
pass
66.
valstanga = 1
67.
nome = diz1['nome']
68.
print "
Consento l'accesso!
69.
70.
except:
71.
pass
72.
73.
except:
74.
pass
75.
76.
trasm = dict()
77.
trasm["targa"]=nome
78.
trasm["tempo"]=time
79.
trasm["valstanga"]=valstanga
80.
trasm["x1"]=x1
81.
trasm["y1"]=y1
82.
trasm["x2"]=x2
83.
trasm["y2"]=y2
84.
trasm["x3"]=x3
85.
trasm["y3"]=y3
86.
trasm["x4"]=x4
87.
trasm["y4"]=y4
88.
trasm["immx"]=immx
89.
trasm["immy"]=immy
90.
91.
f1 = open('/home/bananapi/Desktop/trasmissione.conf','w')
92.
f1.write (str(trasm))
Commenti al codice:
1.
import serial
2.
import beanstalkc
3.
import json
4.
import os
18
", time," mS ", nome
Matteo Dalponte
Tesina di Maturità
A.S: 2014/2015
Questa parte di codice è incaricata di importare le librerie necessarie alla corretta
esecuzione del programma.
Serial è la libreria che gestisce la comunicazione USB con Arduino, beanstalkc è necessario
al fine di leggere il "contenitore" di cui si è parlato nella sezione 3.3, json è la libreria che
decodifica i dati provenienti da beanstalkc ed infine os gestisce il controllo del terminale
della macchina (è possibile eseguire comandi su shell o terminale).
1.
open_alprd = "/home/bananapi/openalpr/src/build/alprd --config /etc/openalpr"
2.
os.system("pkill alprd")
3.
os.system(open_alprd)
Ora viene assegnata alla variabile open_alprd una stringa (le stringhe in python vengono
contrassegnate con le virgolette) contenente il percorso dove è collocato il software OCR.
Con la seconda riga viene spedito il comando pkill alprd sul terminale delle macchina.
Questo comando interrompe eventuali processi del software ocr che erano già stati aperti
in precedenza (è necessario al fine di evitare che due processi di riconoscimento caratteri
siano eseguiti nello stesso momento).
La terza riga esegue il comando contenuto nella variabile open_alpr sul terminale della
macchina.
1. try:
2.
ser = serial.Serial('/dev/ttyUSB0', 9600, timeout=1)
3. except:
4.
5.
6.
7.
8.
9.
10.
try:
ser = serial.Serial('/dev/ttyUSB1', 9600, timeout=1)
except:
try:
ser = serial.Serial('/dev/ttyACM0', 9600, timeout=1)
except:
pass
Viene ora aperta la comunicazione con Arduino.
E' importante inserire l'istruzione di connessione in una struttura try-except perché nel
caso in cui il tentativo di connessione fallisca (per esempio USB arduino non collegata) il
software non deve interrompersi per colpa dell'errore, ma deve procedere con tutti gli altri
comandi ignorando il problema.
E' inoltre importante fare dei tentativi di connessione su varie porte Usb visto che diversi
tipi di arduino possono utilizzare diversi tipi di driver.
Così se il primo ciclo try restituisce errore (o perché la USB non è collegata o perché i driver
sono errati) si passa al secondo try che tenta la connessione con altri driver.
I tentativi continuano fino all'ultimo except dove viene data l'istruzione di saltare il
passaggio di connessione e procedere con il restante codice.
La struttura della connessione è la seguente :
19
Matteo Dalponte
Tesina di Maturità
A.S: 2014/2015
Quando si eseguono operazioni di lettura o scrittura relative alla connessione seriale si
utilizza la variabile "ser" (es: ser.read() significa "leggi i dati provenienti dalla
comunicazione").
'dev/ttyUSB' è il driver di Arduino (è come la COM in windows);
9600 è il bitrate in bit/sec;
timeout=1 è il tempo (s) dopo il quale, in caso di non risposta, si interrompono i tentativi.
1.
beanstalk = beanstalkc.Connection(host='localhost', port=11300)
2.
beanstalk.watch('alprd')
Apre il collegamento con il server "contenitore" dei dati provenienti dall'ocr.
Il server si trova sulla stessa macchina (localhost) e risponde alla porta 11300.
1.
while True:
Tutte le istruzioni precedenti a questo comando vengono eseguite solamente all'avvio,
mentre quelle a seguire saranno eseguite a ciclo continuo.
1.
f = open('/home/bananapi/Desktop/Database.conf','r')
2.
s=str(f.readlines())
3.
dati=eval(s)
Viene
aperto
il
file
contenete
il
database,
situato
nel
direttorio
/home/bananapi/Desktop/Database.conf' in sola lettura (in questo caso non è necessaria la
scrittura se si devono fare solamente confronti tra le targhe lette ed il database).
Il file Database.conf viene poi letto e convertito in una lista (v. struttura lista sezione 3.3)
dove l'indice della lista è il numero della riga e l'oggetto è il contenuto in stringa della riga.
La struttura del database è:
{'targa':'RK755AJ', 'nome':'Matteo Dalponte', 'password':'17846', }
{'targa':'AA555AA', 'nome':'Mario Rossi', 'password':'95761', }
{'targa':'AB344CA', 'nome':'Ciao ', 'password':'98264', }
Dove tramite l'indice della lista si ricava la riga desiderata e poi, tramite la chiave del
dizionario, si ricava a piacere il numero di targa, il nome o la password.
1.
job = beanstalk.reserve()
2.
jobb = job.body
3.
job.delete()
4.
d = json.loads(jobb)
5.
6.
time = str(d["processing_time_ms"])
7.
targa = str(d["results"][0]["plate"])
8.
x1 = str(d['results'][0]['coordinates'][0]['x'])
20
Matteo Dalponte
Tesina di Maturità
9.
y1 = str(d['results'][0]['coordinates'][0]['y'])
10.
x2 = str(d['results'][0]['coordinates'][1]['x'])
11.
y2 = str(d['results'][0]['coordinates'][1]['y'])
12.
x3 = str(d['results'][0]['coordinates'][2]['x'])
13.
y3 = str(d['results'][0]['coordinates'][2]['y'])
14.
x4 = str(d['results'][0]['coordinates'][3]['x'])
15.
y4 = str(d['results'][0]['coordinates'][3]['y'])
16.
immx = str(d['img_width'])
17.
immy = str(d['img_height'])
A.S: 2014/2015
A questo punto viene letto il "contenitore" con i dati inseriti dall'OCR e questi vengono
tradotti in codice JSON (v. sezione 3.3 per spiegazione)
La variabile d conterrà ora tutti i dati riportati nelle pagine 12 e 13, con l'unica differenza
che sotto la chiave candidates avremo 40 tentativi di riconoscimento con diverse
affidabilità (confidence).
Vengono poi estrapolati da JSON (contenuto nella variabile d) i dati del tempo di processing
dell'immagine della targa (time), il numero di targa con maggior probabilità (targa), gli
angoli della targa (necessari poi per contornare la targa nel video streaming), la risoluzione
sull'asse delle x della telecamera (immx) e quella sull'asse delle y (immy).
1.
for num in range(0,40):
2.
3.
try:
try:
4.
number_lines = len(dati)
5.
for i in range(0, number_lines):
6.
diz1 = eval(dati[i])
7.
targa_diz = diz1['targa']
8.
if (str(d['results'][0]['candidates'][num]['plate']) ==
targa_diz):
9.
try:
10.
ser.write("1")
11.
except:
12.
pass
13.
valstanga = 1
14.
nome = diz1['nome']
15.
print "
Consento l'accesso!
", time," mS ",
nome
16.
17.
18.
except:
19.
pass
20.
21.
22.
except:
pass
Ora tutti i 40 tentativi di riconoscimento prodotti dall' OCR vengono confrontati con tutte
le targhe contenute nel database (struttura Database a pag. 17).
21
Matteo Dalponte
Tesina di Maturità
A.S: 2014/2015
Nel caso in cui vi sia corrispondenza vene inviato il comando di apertura ad Arduino
(ser.write("1")), viene portata ad un valore alto una variabile (ci servirà poi per colorare di
rosso o di verde il contorno della targa sul video in streaming) e ricavato dal database il
nome del proprietario del veicolo consentito.
1.
trasm = dict()
2.
trasm["targa"]=nome
3.
trasm["tempo"]=time
4.
trasm["valstanga"]=valstanga
5.
trasm["x1"]=x1
6.
trasm["y1"]=y1
7.
trasm["x2"]=x2
8.
trasm["y2"]=y2
9.
trasm["x3"]=x3
10.
trasm["y3"]=y3
11.
trasm["x4"]=x4
12.
trasm["y4"]=y4
13.
trasm["immx"]=immx
14.
trasm["immy"]=immy
15.
16.
f1 = open('/home/bananapi/Desktop/trasmissione.conf','w')
17.
f1.write (str(trasm))
Viene ora creato un dizionario (trasm) che conterrà tutti i dati significativi della lettura della
targa ( posizione nel video, nome del proprietario del veicolo, targa consentita o meno e
risoluzione della videocamera).
Infine viene scritto il tutto su un file denominato trasmissione.
Tale file verrà poi letto in FTP dal PC di controllo collegato tramite cavo ethernet.
4.2 GUI Visualizzazione streaming
Figura 10: interfaccia grafica GUI per la visualizzazione dello streaming
22
Matteo Dalponte
Tesina di Maturità
A.S: 2014/2015
Il seguente codice viene eseguito sulla macchina (PC remoto) ed è una GUI (graphical user
interface) necessaria per visualizzare lo streaming proveniente dall'IP camera.
Il software ha inoltre il compito di delimitare la targa, in verde se è presente una
corrispondenza della targa con il database, in rosso se non è presente alcuna
corrispondenza (v figura 10).
Il codice è scritto in python ed è stato compilato in modo tale da creare un file eseguibile
(EXE) per macchina windows; in questo modo non è necessario che il computer che lo
esegue sia dotato di interprete python e di tutte le librerie di funzionamento.
La libreria principale per il funzionamento di tale codice è OpenCV, libreria orientata alla
computer vision.
E' importante spendere alcune parole per descrivere le notevoli potenzialità di tale libreria,
pensata inizialmente da Intel per testare le CPU in applicazioni intensive, come ad esempio
la gestione di immagini 3D, e poi rilasciata come libreria open source per la computer
vision.
OpenCV contiene moduli di elaborazione di immagini e video I / O, e più di 350 algoritmi di
gestione dati quali: filtri di immagine, calibrazione della telecamera, riconoscimento di
oggetti, analisi strutturale e molti altri.
1.
import cv2
2.
import urllib
3.
import numpy as np
4.
import ctypes
5.
from ftplib import FTP
6.
import time
7.
8.
x1=0
9.
x2=0
10.
x3=0
11.
x4=0
12.
y1=0
13.
y2=8
14.
y3=0
15.
y4=0
16.
immx=0
17.
immy=0
18.
immx1=500
19.
immy1=500
20.
tempopresente=0
21.
tempopassato=0
22.
valstanga=0
23.
24.
25.
26.
stream=urllib.urlopen('http://192.168.0.44:8080/video')
27.
ftp = FTP('192.168.0.44', 'bananapi', 'bananapi', timeout=2)
23
Matteo Dalponte
Tesina di Maturità
A.S: 2014/2015
28.
29.
30.
bytes=''
31.
while True:
32.
tempopresente=time.time()
33.
if (tempopresente-tempopassato)>0.2:
34.
tempopassato=tempopresente
35.
36.
try:
37.
temp=open('temp.conf','w')
38.
ftp.retrbinary('RETR /home/bananapi/Desktop/trasmissione.conf',
temp.writelines)
39.
temp.close()
40.
f = open('temp.conf','r')
41.
trasm=eval(f.read())
42.
43.
user32 = ctypes.windll.user32
44.
Yval=int(user32.GetSystemMetrics(1)*0.66)
45.
46.
rapp_trasf=((user32.GetSystemMetrics(1)*0.66)/
(eval(trasm['immy'])))
47.
Xval=int((eval(trasm['immx']))*rapp_trasf)
48.
49.
targa=trasm['targa']
50.
x1=int((eval(trasm['x1']))*rapp_trasf)
51.
y1=int((eval(trasm['y1']))*rapp_trasf)
52.
x2=int((eval(trasm['x2']))*rapp_trasf)
53.
y2=int((eval(trasm['y2']))*rapp_trasf)
54.
x3=int((eval(trasm['x3']))*rapp_trasf)
55.
y3=int((eval(trasm['y3']))*rapp_trasf)
56.
x4=int((eval(trasm['x4']))*rapp_trasf)
57.
y4=int((eval(trasm['y4']))*rapp_trasf)
58.
immx=int((eval(trasm['immx']))*rapp_trasf)
59.
immy=int((eval(trasm['immy']))*rapp_trasf)
60.
valstanga=(trasm['valstanga'])
61.
62.
63.
except:
pass
64.
65.
66.
bytes+=stream.read(1024)
67.
a = bytes.find('\xff\xd8')
68.
b = bytes.find('\xff\xd9')
69.
if a!=-1 and b!=-1:
70.
jpg = bytes[a:b+2]
71.
bytes= bytes[b+2:]
72.
i = cv2.imdecode(np.fromstring(jpg, dtype=np.uint8),cv2.CV_LOAD_IMAGE_COLOR)
73.
74.
ridimensiona=cv2.resize(i, (Xval,Yval), fx=5, fy=5)
75.
76.
pts = np.array([[x1,y1],[x2,y2],[x3,y3],[x4,y4]], np.int32)
77.
24
Matteo Dalponte
78.
A.S: 2014/2015
if valstanga==0:
79.
80.
Tesina di Maturità
cv2.polylines(ridimensiona,[pts],True,(0,0,255),2)
else:
81.
cv2.polylines(ridimensiona,[pts],True,(0,255,0),2)
82.
83.
cv2.putText(ridimensiona,targa, (x1,y1-5), cv2.FONT_HERSHEY_PLAIN,
1.2,(255,255,255),2)
84.
cv2.putText(ridimensiona,"Q=Uscita", (0,20), cv2.FONT_HERSHEY_PLAIN,
1.2,(255,255,255),2)
85.
86.
87.
cv2.imshow("Riconoscimento targhe",ridimensiona)
88.
89.
90.
if cv2.waitKey(1) & 0xFF == ord('q'):
91.
break
92.
93.
94.
cv2.destroyAllWindows()
Commento al codice:
1.
import cv2
2.
import urllib
3.
import numpy as np
4.
import ctypes
5.
from ftplib import FTP
6.
import time
Vengono importate le librerie; open cv (cv2 ) e numpy per la gestione dei fotogrammi,
urllib per l'apertura dello streaming, ctypes per ottenere informazioni utili dal sistema
operativo quali per esempio la risoluzione dello schermo, ftplib per la lettura in remoto del
file di trasmissione (v sez. 4.1 pag 14) e time per la gestione del tempo.
1.
stream=urllib.urlopen('http://192.168.0.44:8080/video')
2.
ftp = FTP('192.168.0.44', 'bananapi', 'bananapi', timeout=2)
Apre il link al quale risponde il server MJPEG e inserisce nella variabile streaming tutti tutte
le istruzioni per la lettura del link.
Apre poi una connessione ftp criptata verso Banana Pi; a questo tentativo di connessione
risponderà il server e la comunicazione servirà per scambiare dati tra il server (Banana Pi) e
il PC di controllo.
1.
while True:
25
Matteo Dalponte
Tesina di Maturità
2.
tempopresente=time.time()
3.
if (tempopresente-tempopassato)>0.2:
4.
A.S: 2014/2015
tempopassato=tempopresente
Nel ciclo infinito while True andiamo ora ad assegnare alla variabile tempopresente il
valore in secondi del tempo trascorso dall'accensione della macchina al momento in cui si
richiama la funzione time.time().
Ogni 0,2 secondi viene rieseguito il ciclo IF
Questo accorgimento è un sistema rudimentale, ma in questo caso efficace al fine di non
rallentare due processi che richiedono diverse velocità alla macchina.
Infatti la lettura tramite FTP del file trasmissione.conf è nettamente più lenta della lettura
e visualizzazione del flusso video MJPEG quindi, se la lettura FTP venisse fatta ad ogni ciclo
macchina la visualizzazione dello streaming risulterebbe a scatti e in ritardo rispetto alla
realtà.
Con questo accorgimento le lettura FTP viene eseguita solamente ogni 200 millisecondi,
mentre la gestione video viene fatta a ciclo continuo senza interruzioni.
1.
try:
2.
temp=open('temp.conf','w')
3.
ftp.retrbinary('RETR /home/bananapi/Desktop/trasmissione.conf',
temp.writelines)
4.
temp.close()
5.
f = open('temp.conf','r')
6.
trasm=eval(f.read())
Con le righe 2,3,4 viene trasferito il file trasmissione.conf, situato su Banana Pi, alla
macchina dove viene eseguito il seguente codice.
Il file appena creato viene letto, vengono estratti i dati, viene convertito il contenuto in
dizionario (da file di testo si ricavano solo stringhe) e assegnato alla variabile trasm.
Il seguente file è temporaneo visto che al ciclo successivo viene riscritto e riletto.
7.
user32 = ctypes.windll.user32
8.
Yval=int(user32.GetSystemMetrics(1)*0.66)
9.
rapp_trasf=((user32.GetSystemMetrics(1)*0.66)/(eval(trasm['immy'])))
10.
Xval=int((eval(trasm['immx']))*rapp_trasf)
11.
12.
targa=trasm['targa']
13.
x1=int((eval(trasm['x1']))*rapp_trasf)
14.
y1=int((eval(trasm['y1']))*rapp_trasf)
15.
x2=int((eval(trasm['x2']))*rapp_trasf)
16.
y2=int((eval(trasm['y2']))*rapp_trasf)
17.
x3=int((eval(trasm['x3']))*rapp_trasf)
18.
y3=int((eval(trasm['y3']))*rapp_trasf)
19.
x4=int((eval(trasm['x4']))*rapp_trasf)
26
Matteo Dalponte
Tesina di Maturità
20.
y4=int((eval(trasm['y4']))*rapp_trasf)
21.
immx=int((eval(trasm['immx']))*rapp_trasf)
22.
immy=int((eval(trasm['immy']))*rapp_trasf)
23.
valstanga=(trasm['valstanga'])
A.S: 2014/2015
24.
25.
except:
26.
pass
L'interfaccia grafica (GUI) e quindi anche il video streaming visualizzato devono avere delle
dimensioni tali da non essere troppo grandi per lo schermo del PC e allo stesso tempo
mantenere le stesse proporzioni del video inviato dalla telecamera per evitare di
deformare l'immagine.
Si è deciso di occupare 2/3 dello schermo in altezza per cui, una volta applicata questa
misura, la lunghezza della finestra dovrà variare in base al rapporto del video sorgente.
27.
Yval=int(user32.GetSystemMetrics(1)*0.66)
Con il seguente comando inseriamo nella variabile Yval il valore della dimensione in pixel
dello schermo in altezza moltiplicandolo per 2/3 (0,66)
28.
rapp_trasf=((user32.GetSystemMetrics(1)*0.66)/(eval(trasm['immy'])))
Il valore di Yval viene ora diviso per l'altezza in pixel dell''immagine della telecamera che
avevamo ricavato dall'ocr su Banana Pi e poi inserito nel file trasmissione.conf.
In questo modo il rapporto tra le grandezze dello schermo e della telecamera costituisce un
rapporto di trasformazione che utilizzeremo per adattare la posizione del contorno targa
nel piano di visualizzazione.
1.
bytes+=stream.read(1024)
2.
a = bytes.find('\xff\xd8')
3.
b = bytes.find('\xff\xd9')
4.
if a!=-1 and b!=-1:
5.
jpg = bytes[a:b+2]
6.
bytes= bytes[b+2:]
7.
i = cv2.imdecode(np.fromstring(jpg, dtype=np.uint8),cv2.CV_LOAD_IMAGE_COLOR)
8.
9.
ridimensiona=cv2.resize(i, (Xval,Yval), fx=5, fy=5)
10.
11.
pts = np.array([[x1,y1],[x2,y2],[x3,y3],[x4,y4]], np.int32)
12.
13.
if valstanga==0:
14.
15.
16.
cv2.polylines(ridimensiona,[pts],True,(0,0,255),2)
else:
cv2.polylines(ridimensiona,[pts],True,(0,255,0),2)
17.
27
Matteo Dalponte
18.
Tesina di Maturità
A.S: 2014/2015
cv2.putText(ridimensiona,targa, (x1,y1-5), cv2.FONT_HERSHEY_PLAIN,
1.2,(255,255,255),2)
19.
cv2.putText(ridimensiona,"Q=Uscita", (0,20), cv2.FONT_HERSHEY_PLAIN,
1.2,(255,255,255),2)
20.
21.
22.
cv2.imshow("Riconoscimento targhe",ridimensiona)
23.
24.
25.
26.
if cv2.waitKey(1) & 0xFF == ord('q'):
break
27.
28.
29.
cv2.destroyAllWindows()
Vengono inseriti tutti i bit provenienti dalla lettura della pagina di streaming nella variabile
bytes, vengono selezionati solamente i bit che contengono il fotogramma del video e
vengono ricombinati per crearne un'immagine dalla funzione cv2.imdecode.
L'immagine viene poi ridimensionata con i criteri scelti e descritti nella pagina precedente
e viene creato un poligono che avrà come estremi i punti di limite della targa riportati
dall'OCR nel JSON (v sez. 3.3 pag. 13).
Questo poligono verrà colorato in rosso o in verde in base al valore della variabile valstanga
e, assieme al numero di targa o proprietario del veicolo, verrà poi stampato a monitor
sopra l'immagine proveniente dall'IP camera.
28
Matteo Dalponte
Tesina di Maturità
A.S: 2014/2015
Sitografia
http://www.anpr.net/
http://www.police.uk/information-and-advice/automatic-number-plate-recognition/
http://en.wikipedia.org/wiki/Automatic_number_plate_recognition
http://www.raspberrypi.org
http://www.linux.it/linux
http://it.wikipedia.org/wiki/Software_libero
http://www.softwarelibero.it/
https://gnu.org/
http://it.wikipedia.org/wiki/MPEG-4
http://en.wikipedia.org/wiki/Motion_JPEG
https://github.com/openalpr/openalpr/wiki/OpenALPR-Design
http://www.python.it/doc/intro/
http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html
http://www.html.it/pag/15614/dizionari/
http://www.html.it/pag/15613/liste/
https://github.com/openalpr/openalpr/wiki/OpenALPR-Daemon-%28alprd%29
http://opencv.org/
29