Aplicatie Pentru Localizarea Placutelor de Inmatriculare ale Autovehiculelor din Imagini Si Pentu Recunoasterea Caracterelor
Introducere
Societatea zilelor noastre se află într-un proces continuu de dezvoltare, ceea ce
face ca mediul în care trăim să sufere modificări permanente. Dezvoltarea unei societăți poate fi privită ca o expansiune a gradului de confort al cetățenilor, astfel că un nivel de trai mai ridicat face ca rata de achiziție a bunurilor să crească. O categorie de bunuri a căror achiziție este în continua creștere este reprezentată de autovehicule.
Odată cu creșterea numărului de autovehicule pe străzi, fluidizarea traficului și respectarea regulilor de circulație devine foarte dificilă. Pe autostrăzi și în parcări sunt construite cabine pentru plată, unde mașina trebuie să oprească și să își plătească taxa. De asemenea, pe autostrăzi sunt montate sisteme de control al traficului pentru a verifica autoturismele care depășesc viteza legală. Toate aceste procese pot fi îmbunătățite, din moment ce la baza lor se află un autovehicul. Pentru a automatiza aceste procese și a le face mult mai eficiente, este nevoie de un sistem ce poate identifica un autovehicul.
Vehiculele se disting între ele printr-un număr de înmatriculare unic, care este
trecut pe plăcuța de înmatriculare. Un sistem automatizat poate fi implementat pentru
identificarea plăcuței unei mașini și să extragă caractere din regiunea ce conține plăcuța
de înmatriculare. Numărul de înmatriculare poate fi folosit pentru a obține mai multe
informații despre vehicul și despre proprietar, informații utile în procesări viitoare.
Lucrarea de față, intitulată ,,Aplicație pentru localizarea plăcuțelor de înmatriculare ale autovehiculelor din imagini și pentu recunoașterea caracterelor’’, își propune soluționarea problemelor actuale cu care se confruntă sistemele de monitorizare și control. Acest sistem este unul automat, ceea ce înseamnă că intervenția umană este necesară doar pentru proiectare, realizare și depanare.
Principalul scop al lucrării este de a localiza plăcuța de înmatriculare dintr-o imagine și de a recunoaște caracterele din care este format numărul. Este construit un algoritm eficient pentru a detecta plăcuța în condiții diferite de luminozitate. Algoritmul extrage datele plăcuței de înmatriculare din imagine apoi le traduce folosind o tehnică de recunoaștere a caracterelor. Scopul acestui proiect este de a detecta plăcuța de înmatriculare dintr-o imagine dată și de a afișa caracterele recunoscute ale acestuia. Acest proiect poate folosi ca un punct de start pentru viitoare îmbunătățiri în domeniul procesării de imagini, localizare a plăcuțelor de înmatriculare și recunoaștere a caracterelor lor.
Pașii prin care sunt construiți algoritmii de localizare și recunoaștere a plăcuțelor de înmatriculare utilizați în această aplicație nu îmi aparțin, aceștia reprezentând metodele universale prin care sunt construite astfel de aplicații automate. Însă metodele de reprezentare a acestor pași au fost implementate de mine, folosind funcții deja existente din Matlab și documentația pusă la dispoziție de acesta.[10]
Structurarea capitolelor este făcută astfel:
Capitolul 2al proiectului, numit ,,Stadiul actual al cercetărilor în domeniul localizării obiectelor în imagini și recunoașterii caracterelor’’, explică lucruri fundamentale despre procesarea imaginilor, informații despre pixelii unei imagini, formatele RGB și YCbCr, sisteme optice de recunoaștere a caracterelor (OCR) și avantajele/dezavantajele acestora.
Capitolul 3 al proiectului, numit ,,Proiectarea aplicației pentru localizarea și recunoașterea plăcuțelor de înmatriculare’’,arată care sunt pașii unui sistem de localizare și recunoaștere a plăcuțelor de înmatriculare și cum funcționează acesta.
Capitolul 4 al proiectului, numit ,,Implementarea și utilizarea aplicației’’, explică construirea algoritmului de localizare și recunoaștere a plăcuței de înmatriculare în Matlab cât și rezultatele și analiza acestuia.
Capitolul 5 al proiectului, ,,Concluzii’’, expune obiectivele propuse și atinse ale aplicației, viitoare îmbunătățiri ale acesteiași experiența acumulată.
Stadiul actual al cercetărilor în domeniul localizării obiectelor în imagini și recunoașterii caracterelor
2.1 Noțiuni introductive
Imagineaeste o reprezentare vizuală a unui obiect, a unei persoane sau scene produsă de un dispozitiv optic cum ar fi o oglindă, lentilă sau o cameră foto. Această reprezentare este una bidimensională, deși corespunde unei infinități de proiecții din lumea reală, adică lumea tridimensională.
Imaginile sunt folosite pentru a transmite informații într-un format vizibil. Imaginile sunt realizate prin ordonarea într-un spațiu 2D a mii de pixeli. Fiecare pixel conține anumite informații despre imagine, ca de exemplu culoarea, intensitatea luminoasă sau luminanța.
Pixelul este elementul de bază folosit pentru descrierea unei imagini. De cele mai multe ori un pixel este reprezentat în formatul RGB sau YCbCr. În cazul unei imagini RGB toate cele trei componente R,G și B sunt combinate pentru a transmite informații despre culoarea și luminozitatea unui pixel. Fiecare dintre aceste trei componente utilizează un anumit spațiu de memorie pe parcursul procesării de imagine.
În ceea ce privește imaginile YCbCr, fiecare pixel al imaginii este reprezentat ca o combinație de valori pentru Y și Cb/Cr. Y reprezintă luminanța iar Cb/Cr reprezintă componentele cromatice care transmit informații despre culoare.
Componentele YCbCr transmit suficiente date și cu mai puțin spațiu de memorie utilizat în comparație cu RGB, ceea ce se dovedește o caracteristică foarte importantă în prezent deoarece se doresc transmisii foarte rapide ce utilizează puțină memorie. [4]
2.1.1 Formatul RGB
Modelul RGB este un model de culori aditive în care culorile roșu, albastru și verde sunt puse împreună pentru a obține o gamă largă de culori. Fiecare pixel dintr-o imagine RGB este alcătuit din cele trei componente R (red), G (green) și B (blue). Fiecare dintre aceste componente necesită cel puțin 8 biți pentru memorare. În mod obișnuit un singur pixel necesită cel puțin 3×8 biți pentru a fi reținut în unitatea de memorie.
Valorile pentru R, G și B sunt cuprinse în gama 0-255. Valoarea (0,0,0) reprezintă un pixel negru, (255,0,0) reprezintă un pixel roșu sau (0,255,0) este un pixel verde, valoarea (255,255,255) este un pixel alb. Cum fiecare componentă poate lua 256 de valori, aceasta înseamnă că fiecare componentă necesită 8 biți.
O reprezentare a pixelilor în acest format poate fi vazută în Fig. 1.
Fig. 1.Reprezentarea a doi pixeli în format RGB
O alternativă este reprezentarea pe 32 de biți pe pixel, care cuprinde un al patrulea canal, cunoscut sub numele de canalul alpha, acesta furnizează gradul de trasparență pentru fiecare pixel și este foarte folosit la editarea efectelor unei imagini. [4]
2.1.2 Formatul YCbCr
Spre deosebire de formatul RGB, formatul YCbCrreprezintă culoarea prin intensitatea luminoasă și două componente cromatice. În formatul YCbCr 4:2:2, un singur pixel este reprezentat de două componente Y și C. Valorile componentelor Cb și Cr sunt date de diferența dintre B/R (blue/red) și intensitatea luminoasă. Dacă un pixel este reprezentat ca o combinație de Y și Cb, pixelul adiacent va fi reprezentat ca o combinație de Y și Cr, după cum putem vedea în Fig.2. Deși componentele Cr și Cb sunt intercalate, efectul acestora nu este vizibil ochiului uman.
Fig. 2.Reprezentarea a trei pixeli în formatul YCbCr 4:2:2
Valorile pentru Y, Cb și Cr variază între 0-255. Pentru a memora informația despre un singur pixel, cantitatea de memorie este 8 x 2 biți, ceea ce demonstrează un spațiu mai mic de memorare față de RGB. [4]
2.1.3 Tipuri de imagini
Majoritatea formatelor de imagini utilizate pentru reprezentarea imaginilor bitmap conțin un header al fișierului urmat de datele despre pixeli. Acest header conține informații despre imagine, cum ar fi dimensiunile imaginii, numărul de biți pe pixel și câțiva biți pentru identificarea tipului fișierului. Pentru formatele mai complexe, header-ul conține și informații despre tipul de compresie folosit și alți parametrii necesari pentru decodarea imaginii.
Cel mai simplu format de imagine este formatul BIN. Acesta conține doar câteva date despre pixeli fără niciun header. Prin urmare, utilizatorul unui format BIN trebuie să cunoască parametrii relevanți ai imaginii înainte de a folosi imaginea. Formatul PPM și derivatele sale (PBM pentru imagini binare, PGM pentru imagini în nuanțe de gri, PPM pentru imagini color sau PNM pentru oricare dintre ele) sunt larg folosite în procesarea de imagini. Header-ul pentru acestea conține semnătură de 2 biți, sau ,,număr magic”, prin care se identifică formatul imaginii, dimensiunile și valoarea maximă de intensitate.
Microsoft Windows Bitmap (BMP) este un alt format larg răspândit și destul de simplu, ce constă într-un header urmat de datele despre pixeli. Un fișier cu extensia BMP ocupă un spațiu de stocare destul de mare, însă acest tip este încă popular datorită faptului că informațiile sunt stocate în aproape aceeași manieră în care Windows reprezintă intern imaginile. Informația de culoare a fiecărui punct de imagine este stocată în 1, 4, 8, 16 sau 24 biți. Cu cât sunt rezervați mai mulți biți de culoare pentru fiecare punct de imagine, cu atât este mai mare adâncimea culorii și în același timp calitatea imaginii. Totuși, o adâncime de culoare mare duce la ocuparea unui spațiu de stocare mai mare. Din acest motiv, fișierele BMP sunt comprimate uneori cu Run Length Encoding (RLE), însă nu orice program are filtru de import RLE.
Formatul Joint Photographic Expert Group (JPEG), dezvoltat de C-Cube Microsystem este cel mai popular format de fișiere pentru reprezentări fotografice de calitate. Deși acest format are o adâncime mare de culoare (16 milioane de culori), imaginile JPEG ocupă un spațiu mic pe hard-disk. Acesta suportă nivele înalte de comprimare cu pierderi minime de calitate. Pentru comprimare folosește transformarea cosinus discretă iar în spatele acestui sistem se află o transformare Fourier, care schimbă dispersia pixelilor într-o dispersie de frecvență și de amplitudine.
Participațiile de frecvență mici sunt atribuite suprafețelor de imagine mari și uniforme, iar participațiile de frecvență mari sunt primite de detaliile fine ale imaginii. Comprimarea apare când părți din imagine ale căror participații de frecvență sunt mari primesc o pondere mică și amplitudinile lor vor fi zero.
Alte două formate foarte folosite în acțiuni de procesare sunt GIF (Graphics Interchange Format) și TIFF (Tagged Image File Format). GIF folosește o paletă de maxim 256 de culori, algoritmul de compresare LZW și are un header de 13 biți. TIFF este un format mai sofisticat cu mai multe opțiuni și posibilități, inclusiv posibilitatea de a reprezenta truecolor (24 bpp) și de a suporta 5 scheme de compresare.
Portable Network Graphics (PNG) este un format din ce în ce mai popular, care suportă atât imaginile index cât și cele truecolor. În plus, asigură o înlocuire patent-free pentru formatul GIF.
Unele pachete de editare a imaginilor adoptă propriile formate, exemplu fiind XCF (formatul nativ al programului de editare GIMP) sau RAW (care este o familie de formate adoptate în special de producătorii de camere. [4]
2.2 Tehnologia OCR
Recunoașterea optică a caracterelor (Optical Character Recognition), abreviată OCR, reprezintă translatarea mecanică sau electronică a imaginilor tipărite, imprimate sau cu scris de mână în text editabil.
OCR utilizează o formă de inteligență artificială, cunoascută sub numele de recunoașterea modelului, pentru a fi capabilă să identifice fiecare caracter al unui text dintr-o imagine, inclusiv semne de punctuație sau spațiile.
Principalul obiectiv în ceea ce privește dezvoltarea programelor OCR este reprezentat de alegerea algoritmului care oferă rezultatele cele mai promițătoare.
Funcția OCR trebuie să ofere acces rapid la formatul editabil al documentului arhivat, chiar și atunci când acesta conține formatări complexe, grafice, texte scrise cu caractere diferite sau tabele. Obiectivul unui sistem bazat pe OCR este recunoașterea caracterelor alfanumerice reprezentate sub formă de imagini digitale. Acest lucru este posibil prin definirea unor proprietăți/parametrii descriptivi extrași din caracterele imaginii digitale scanate de către sistemul OCR, cât mai apropiați ca valoare de parametrii omologi ai caracterelor-șablon din biblioteca sistemului de recunoaștere. În cazul ideal, este dorit ca proprietățile să fie distincte pentru fiecare caracter al imaginii analizate, pentru a nu exista confuzii în extragerea șablonului corespunzător. În același timp, se dorește robustețea acestora în sensul sensibilității scăzute la intervenția unor factori precum zgomot, variații ale rezoluției etc. [16]
2.2.1 Familiile OCR
Cele două mari familii OCR sunt recunoașterea în timp real și recunoașterea în mod pasiv a caracterelor.
Recunoașterea în timp real a caracterelor lucrează cu un flux de date primit de la un traductor în timpul în care utilizatorul scrie. Dispozitivele cele mai folosite pentru acest tip de recunoaștere sunt tabletele digitale, care au suprafața de scriere sensibilă electromagnetic sau sub presiune. În timpul în care utilizatorul scrie pe suprafața sensibilă, mișcarea vârfului instrumentului de scris este transformată în semnale digitale, memorate și analizate de către dispozitiv.
Recunoașterea în modul pasiv este realizată după ce procesul de scriere a fost finalizat. Diferența majoră dintre aceste două moduri de recunoaștere este aceea că modul în timp real se bazează pe informația contextuală distribuită pe secvențele de timp în care se acționează semnalele, pe când modul pasiv este independent de timpul în care sunt scrise caracterele. Această diferență creează o divergență semnificativă în arhitectura procesului și metodele de procesare a datelor.
Recunoașterea pasivă se împarte la rândului ei în recunoașterea magnetică a caracterelor (MCR) și recunoașterea optică a caracterelor (OCR).
În cazul MCR, caracterele sunt imprimate cu cerneală magnetică iar dispozitivul le recunoaște în conformitate cu unicitatea câmpului magnetic generat de fiecare caracter. MCR este cel mai folosit în contextul bancar pentru controlul autentificărilor.
OCR realizează recunoașterea caracterelor din imaginile achiziționate de către dispozitive optice de captare. Caracterele sunt reprezentate sub formă de imagini formate din pixeli și pot fi imprimate sau scrise de mână. În recunoașterea caracterelor de tipar, imaginile analizate conțin caractere standardizate în fonturi. [1]
În Fig.3 este reprezentată diagrama familiilor OCR și subdiviziunile lor.
Fig. 3.Familiile OCR
2.2.2 Sistemul OCR
Sistemul OCR este format dintr-o serie de procese, care încarcă imaginea, o preprocesează, extrage proprietățile de interes, analizează corespondența rezultatelor cu proprietățile șabloanelor stocate în biblioteca sistemului și reține perechea sistemelor de proprietăți care prezintă cel mai mare grad de corespondență.
Etapa de preprocesare are rolul de a transforma imaginea într-un mediu cât mai benefic extragerii eficiente a proprietăților. Starea imaginii inițiale poate fi perturbată de o serie de factori externi, cum ar fi zgomotul sau efectul de blur. Această etapă implementează limite de prag pentru valorile de culoare ale pixelilor, binarizarea, detecția muchiilor, umplerea ariilor de discontinuitate astfel încât să se obțină o stare care să permită o procesare ulterioară.
Etapa de căutare conține etapa de analiză a corespondenței, aceasta realizează căutarea celei mai mari corespondențe între imaginea obținută din preprocesare și fiecare imagine șablon din biblioteca sistemului OCR. [13]
2.2.3 Tehnici de identificare a caracterelor
Există multiple abordări folosite pentru sistemele de detectare a caracterelor[14]:
Matrix matching;
Fuzzy logic;
Feature extraction;
Structural analysis;
Neural networks.
Matrix matching (Potrivirea matricilor): Convertește fiecare caracter într-un model aflat într-o matrice și îl compară cu un număr de modele cunoscute, ce reprezintă toate caracterele.
În Fig.4 vedem cum arată caracterele în viziunea calculatorului.
a)
b)
c)
Fig. 4. (a) Imaginea unui caracter convertită în matrice de 12×12 pixeli
(b) Matricea pixelilor cu valori de 0 și 1 (c) Modele de caractere[15]
Fuzzy Logic:Este o logică cu valori multiple care permite definirea unor valori intermediare între evaluări convenționale precum da/nu, adevărat/fals, alb/negru etc.
Se încearcă să se atribuie o gândire umană asupra gândirii logice în programarea calculatoarelor. Fuzzy logic se folosește când răspunsurile sunt incerte, când nu există o valoare distinctă de adevărat sau fals.
Feature Extraction (Extragerea trăsăturilor):Această metodă definește fiecare caracter prin prezența sau absența unei trăsături cheie, cum ar fi înălțimea, lățimea, densitatea, numărul de linii, numărul de bucle și alte trăsături specifice caracterelor. Această metodă este perfectă pentru detectarea caracterelor în reviste și imagini de înaltă calitate.
Structural Analysis (Analiză structurală): Metoda identifică caracterele prin examinarea trăsăturilor formei imaginii, a histogramei verticale și orizontale. Metoda poate reconstruii caracterele aflate în calitate proastă.
Neural Networks (Rețele neuronale): Această strategie simulează metoda prin care funcționează sistemul neurologic al omului. Strategia testează pixeli din fiecare imagine și îi potrivește cu un index cunoscut ce reprezintă un pixel al modelului de caracter. Abilitatea de a recunoaște caractere prin abstracție este utilă pentru documentele trimise prin fax și documentele cu text deteriorat. Rețelele neuronale sunt ideale pentru probleme specifice, cum ar fi procesarea datelor de pe piața de stocuri sau găsirea formațiilor în modele grafice.
În Fig.5 avem o rețea neuronală ce simulează recunoașterea textului dintr-un document tipărit.
Fig. 5.Rețea neuronală pentru recunoașterea textului dintr-un document scanat[12]
2.2.4 Avantajele și dezavantajele OCR
Avantajeletehnologiei OCR sunt următoarele[6]:
elimină necesitatea retipăririi unui document;
eficiență;
economie de spațiu și bani;
ajută la editarea documentelor deja imprimate;
este mult mai rapid decât o persoană care să introducă textul;
pot fi identificate atât forme cât și caractere.
Dezavantajeletehnologiei OCR sunt următoarele[6]:
Acuratețea, nici un software OCR nu este precis 100%. Numărul de erori depinde de calitatea și timpul documentului, inclusiv de fontul utilizat. Erorile ce pot apărea pe parcursul OCR sunt: interpretarea greșită a literelor, sărirea peste literele ce nu pot fi citite sau unirea textelor din coloane adiacente;
Limitat pentru anumite forme de documente, OCR este eficient pentru imagini de bună calitate. De asemenea, scrisul de mână și fonturi nelatine creează multe erori pe parcursul procesului OCR. Dacă imaginea are un contrast slab sau prezintă murdărie, sau textul și fundalul sunt similare, atunci OCR nu va da rezultate bune. Documentele care conțin atât imagini cât și text creează dificultăți pentru OCR;
Munca adițională. Deși imaginea este de bună calitate, sunt necesare etape adiționale pentru a corecta textul OCR. O persoană va trebui să verifice textul OCR cu documentul original;
OCR are probleme în a face diferența între diverse caractere, cum ar fi cifra 0 și majuscula O, litera Q poate fi confundată cu litera O.
2.2.5 Aplicații ale tehnologiei OCR
OCR a fost dezvoltat pentru diverse aplicații orientate pe citirea textului digital. Unele dintre utilitățile acestei tehnologii sunt[6]:
Intrări de date pentru documente de afaceri, verificarea pașapoartelor; declarații bancare sau chitanțe;
Recunoașterea automată a numărului de înmatriculare;
Convertirea scrisului de mână în timp real;
Extragerea automată a datelor cheie din documente de asigurare;
Extragerea informațiilor din cărți de vizită și introducerea lor într-o listă de contacte.
2.2.6 ANPR (Automatic Number Plate Recognition)
În ultimii ani, o nouă tehnologie devine tot mai populară în domeniul
identificării automate a autovehiculelor și al aplicațiilor de control al accesului acestora. Această tehnologie are la bază sistemul OCR și se numește Recunoașterea Automată a Numărului de Înmatriculare (Automatic Number Plate Recognition –ANPR). De obicei, această tehnologie este realizată fizic cu ajutorul unei camere cu un software OCR integrat.
Descrierea sumară a procesului de funcționare este:
Camera captează o imagine când identifică un număr de înmatriculare (folosind tehnologia infraroșu);
Camera izolează numărul, ajustează luminozitatea și contrastul și segmentează imaginea în caractere;
Modelul fiecărui caracter este analizat pentru a transforma imaginea în text;
Rezultatul este trimis prinIP (Internet Protocol) printr-o conexiune serială la un sistem de control al accesului sau management al autovehiculelor.
Marele avantaj al folosirii ANPR este acela că se folosește de un element
prezent la toate vehiculele și anume numărul de înmatriculare. Îndepărtează nevoia de a distribui și de a monta tag-uri RFID (Radio-Frequency Identification). Acesta face ca ANPR să fie potrivit în acele situații în care nu se dorește sau nu se pot folosi tag-uri.
Unele din utilizările ANPR sunt:
Controlul accesului vehiculelor cu autorizații de acces limitat: vizitatori, aprovizionare sau staționări în parcări exclusiviste;
Aplicații în care este necesară identificarea unui vehicul, cum ar fi aplicațiile de management al parcărilor în care numărul de înmatriculare este înregistrat pentru a spori securitatea;
Situații în care anumite lungimi de undă pentru RFID nu pot fi folosite din cauza interferențelor sau legislației;
Hoteluri;
Trecerea graniței.
De luat în considerare este faptul că un sistem ANPR se va baza pe
bibliotecile care să ajute la identificarea numerelor de înmatriculare din diverse țări. Fiecare țară utilizează propriile caractere, culori și forme. Din acest motiv, trebuie avut în vedere dacă sistemul OCR suportă caracterele dintr-o anumită țară.
ANPR folosește tehnologia camerelor tradiționale și prin urmare, acestea trebuie instalate și configurate corespunzător. Majoritatea au un punct de focalizare specific dar care poate fi configurat, din acest motiv camerele trebuie montate la o anumită înălțime pentru a asigura un unghi de captare potrivit și să suporte o viteză limită a mașinii. Conexiunea vizuală dintre numărul de înmatriculare și cameră poate influența ANPR prin lumina care bate spre lentilele camerei sau murdăria de pe numărul de înmatriculare. Aceasta este o situație în care tag-urile RFID nu ar prezenta probleme.[7]
Algoritmii necesari construirii unui sistem ANPR
Există șapte algoritmi principali de care are nevoie un software ANPR pentru a identifica plăcuțele de înmatriculare[6]:
Algoritm de localizarea plăcuței – responsabil cu căutarea și izolarea porțiunii din imagine ce corespunde numărului de înmatriculare;
Algoritm de orientareși dimensionare – în cazul în care plăcuța nu este așezată orizontal pe imagine, algoritmul rectifică acest lucru și ajustează dimensiunile;
Algoritm de normalizare – ajustarea luminozității și a contrastului pe plăcuță;
Algoritm de segmentarea caracterelor – găsirea caracterelor individuale pe plăcuță;
Algoritm de recunoaștere a caracterelor (OCR);
Algoritm ce realizează analiza sintactică și geometrică – verificarea caracterelor și a pozițiilor lor pentru regulile specifice fiecărei țări;
Algoritm ce efectuează media obținută din recunoașterea plăcuțelor dintre mai multe imagini, pentru a produce un rezultat încrezător.
Eficiența fiecărui algoritm determină acuratețea acestui sistem.
Dificultăți
Există un număr de dificultăți cu care un software trebuie să se adapteze:
Rezolutie slabă a imaginii, obținută din vina unei camere de calitate slabă sau pentru că plăcuța de înmatriculare este la distanță mare;
Imagini umbrite, efecte de mișcare, blur;
Contrast mic, puțină luminozitate, umbre sau reflecții;
Acoperirea unor porțiuni din numărul de înmatriculare, murdărie;
Font diferit față de cel folosit uzual;
Lipsă de coordonare între țări sau state. Două mașini diferite pot avea același număr de înmatriculare dar un design diferit pentru plăcuță.
Chiar dacă unele dintre aceste probleme pot fi corectate în porțiunea software,
rămâne laaprecierea porțiunii hardware a sistemului pentru a găsii soluții la aceste dificultăți.[6]
Proiectarea aplicației pentru localizarea și recunoașterea plăcuțelor de înmatriculare
Sistemul de localizare și recunoașterea plăcuțelor de înmatriculare se construiește din patru pașiconsecutivi:
Procesarea imaginii inițiale
Localizarea plăcuței de înmatriculare
Segmentarea caracterelor
Recunoașterea caracterelor
3.1 Procesarea imaginii inițiale
Imaginea inițială este procesată pentru a crește calitatea acesteia și pentru a o
pregătii pentru următorii pași ai sistemului. Se efectuează un proces de dilatare asupra imaginii pentru umplerea golurilor,îmbunătățirea luminozității, înlăturarea zgomotului și creșterea contrastului dintre caracterele și imaginea de fundal a plăcuței de înmatriculare. Imaginea este apoi convertită în nuanțe de gri pentru a fi folosită de următoarele procese.
3.2 Localizarea plăcuței de înmatriculare
În stagiul de localizare al plăcuței, pornim de la o imagine în nuanțe de gri și vrem să ajungem la porțiunea din imagine care corespunde plăcuței de înmatriculare. Un calculator vede această imagine ca o matrice de valori între 0 – 255 (reprezentând valorile de gri).
Algoritmul de detectare a plăcuței de înmatriculare este bazat pe urmatoarea idee: o plăcuță de înmatriculare este formată dintr-un șir de caractere. Un caracter este un obiect întunecat aflat pe un fundal luminos. Deci, putem spune că regiunea ce corespunde plăcuței de înmatriculare este dată de un șir de tranziții de la negru la alb și vice versa.
Pentru imaginea în nuanțe de gri, se calculează aceste tranziții dintre pixeli și sunt reprezentate cu ajutorul unor histograme.Pixelii sunt comparați câte doi, consecutivi, iar dacă diferența dintre ei depășește un anumit prag este adăugată la suma de diferențe. Sunt comparați toți pixelii pe linii cât și pe coloane, obținându-se astfel o histogramă orizontală și una verticală.
Pentru a evita pierderi de informații importante în următoarele procese, este necesară netezirea modificărilor drastice de valori din ambele histograme. Acest lucru se realizează prin folosirea unui filtru low-pass digital.
După ce histogramele sunt trecute prin acest filtru, sunt îndepărtate zonele din imagine care nu sunt utile. Acest zone sunt reprezentate de valori mici ale histogramelor, zone ce indică variații mici între pixelii vecini.
Având în vedere că zona cu număr de înmatriculare este formată dintr-un șir de caractere negre aflate pe un fundal alb, diferența pixelilor învecinați este foarte mare, în special la marginile plăcuței și a caracterelor. Astfel, regiunea cea mai probabilă să conțină numărul de înmatriculare are valori mari în histograma verticală și orizontală.
După ce se aplică un threhold dinamic, egal cu valoarea medie dintr-o histogramă și sunt eliminate zonele ce nu sunt necesare, rezultatul este o histogramă ce prezintă zonele cu posibilitate mare de a conține numărul de înmatriculare (Fig.6).
Dintre toate aceste zone, cea cu valorea de histogramă cea mai mare este considerată cel mai bun candidat. Toate regiunile sunt evaluate în funcție de datele de pe rânduri și coloane pentru a găsi regiunea comună unde histograma verticală și orizontală au valoare maximă.(Fig.7).
Fig.6. Posibile zone de interes Fig.7. Cel mai bun candidat
3.3 Segmentarea caracterelor
În acest pas, imaginea ce reprezintă plăcuța de înmatriculare, ce a fost
identificată în pasul anterior, este convertită în imagine binară astfel: se găsesc două vârfuri în histograma imaginii și găsim valoarea minimă dintre ele, această valoare reprezentând threshold-ul (nivelul). Astfel, fiecare pixel care are o valoare mai mică decât nivelul, este transformat în negru, iar ceilalți pixeli în alb. Imaginea este procesată pentru a elimina reziduurile și zonele care nu reprezintă caractere.
După ce se identifică obiectele din imagine, se verifică dacă obiectul detectat reprezintă un caracter sau dacă este un reziduu ce a trecut de faza de procesare. Dacă obiectul se încadrează în mărimile unui caracter în situații normale, acesta este decupat și adăugat în vectorul de imagini.
Acum scopul este recunoașterea și clasificarea imaginilor binare care conțin caractere,dinimaginea procesată. Pentru recunoașterea lor, este necesară segmentarea fiecăruia și adăugarea lor într-un vector de imagini. Segmentarea se face cu ajutorul câmpului BoundingBoxal structurii ce reprezintă obiectele detectate, câmp care este un vector de valori ce semnifică poziția și mărimea obiectului detectat, pe axele Ox și Oy.
Segmentarea este cel mai important aspect din stagiul procesării imaginilor deoarece permite extragerea calităților pentru fiecare caracter individual. Există totuși problema textului scris de mână, unde segmentarea caracterelor devine mult mai dificilă datorită literelor scrise legate.
În Fig.8 vedem cum separă algoritmul caracterele de pe plăcuța de înmatriculare.
Fig.8. Localizarea și separarea caracterelor
Segmentarea caracterelor separă fiecare literă și cifră ce aparține numărului de înmatriculare și vor fi procesate de algoritmul de recunoaștere a caracterelor.
3.4 Recunoașterea caracterelor
Recunoașterea caracterelor se face prin folosirea unui algoritm ce compară imaginile segmentate, cu o bibliotecă de șabloane predefinită și returnează caracterul identificat. Pentru a efectua această comparație logică între imagini, dimensiunile acestora trebuie să fie identice.
Fiecare caracter identificat în procesul de segmentare este recunoascut individual. După ce a fost făcută recunoașterea lor, caracterele sunt introduse unul câte unul într-un șir de caractere ce formează numărul de înmatriculare recunoscut din imagine. [9]
Procesul de segmentare, recunoaștere și creare a șirului de caractere poate fi văzut în Fig.9.
Fig.9. Identificarea caracterelor și construirea șirului
Implementarea și utilizarea aplicației
4.1 Implementarea în Matlab
4.1.1 Introducere
Algoritmul de recunoaștere a numărului de înmatriculare este implementat cu ajutorul software-ului Matlab (MATrix LABoratory). Matlab este un mediu de programare de nivel înalt destinat programării, vizualizării și interpretării numerice. Cu ajutorul Matlab se pot analiza date, dezvolta algoritmi, creea modele sau aplicații. Limbajul, ustensilele și funcțiile matematice încorporate permit explorarea a diverse abordări și soluții mult mai rapide decât cu limbaje de programare tradiționale, cum ar fii C/C++ sau Java.
Principalul avantaj Matlab este că acesta conține o multitudine de biblioteci pentru procesarea imaginilor și procesarea de date. Aceste considerente fac din Matlab o ustensilă foarte utilă pentru implementarea și verificarea oricărui algoritm înainte ca acesta să fie implementat pe echipamente hardware. În plus, Matlab conține câteva elemente precum imhist, imshow, imread, plot, im2bw, care fac acest pachet de programare o alegere mult mai bună față de alte limbaje precum C sau C++.
Tipul de date de bază în Matlab este matricea (sau vectorul). Matlab nu necesită dimensionări iar fiecare dată este considerată o matrice de un anumit tip. Valorile simple sunt considerate de Matlab ca fiind matrici 1×1.
Mediul de dezvoltare al algoritmului Matlab asigură o interfață command-line, o interfață pentru limbajul de programare, seturi de funcții pentru manipulări numerice, reprezentare grafică 2D și 3D și posibilitatea de a construi interfețe grafice cu utilizatorul GUI(Graphic User Interface). Programarea în Matlab interpretează comenzi, ceea ce face ca timpul de programare să fie scurtat prin eliminarea nevoii de compilare. [10]
Considerând aceste avantaje, am implementat un algoritm pentru detectarea plăcuțelor de înmatriculare folosind Matlab. Algoritmul folosește funcții deja existente și nu a fost nevoie de definirea unor noi rutine declarate de utilizator în vederea procesării de imagini. Odată ce algoritmul a fost creat, a fost verificat prin introducerea unor imagini ce conțin plăcuțe de înmatriculare, aliniate orizontal.
4.1.2 Recunoașterea numărului de înmatriculare
Procesul de recunoaștere a numărului de înmatriculare caracteristic fiecărui autovehicul se împarte în două mari etape: identificarea pe imagine a zonei de interes ce conține plăcuța de înmatriculare și identificarea și recunoașterea fiecărui caracter alfanumeric din zona căutată.
În Fig. 10 avem schema bloc pentru recunoașterea numărului de înmatriculare.
Fig. 10.Algoritm de recunoaștere OCR
Dacă este detectat un autoturism, se parcurg pașii de identificare a numărului de înmatriculare. Imaginea inițială este preluată și transmisă către sistemul de calcul. Aceasta este imaginea originală, căreia nu i s-a aplicat nici o modificare.
Pentru a fi posibilă recunoașterea caracterelor, imaginea preluată trebuie transformată în nuanțe de gri și în același timp trebuie redimensionată. Transformarea în nuanțe de gri ușurează procesul de recunoaștere, deoarece conține mai puțină informație decât imaginea color, iar redimensionarea ajută la micșorarea timpului de procesare, algoritmul de recunoastere bazându-se pe parcurgerea imaginii linie cu linie.
Etapele următoare reprezintă acțiunea în sine de recunoaștere a caracterelor numărului de înmatriculare. Acești pași vor fi tratați individual în cele ce urmează.
Aplicația se prezintă sub forma unei interfețe grafice prin care utilizatorul selectează imaginea, aceasta ușurând procesul de recunoaștere prin alegerea directă din interfață a imaginii, fără a mai modifica codul sursă sau apela diverse comenzi. [3]
4.1.3 Identificarea zonei de interes
Pentru a putea identifica zona de interes necesară procesărilor, sunt necesari o serie de pași. (Fig.11)
Fig. 11.Pașii urmați pentru identificarea zonei de interes [5]
Algoritmul de recunoaștere a plăcuței de înmatriculare folosește inițial diverse funcții predefinite și implementează rutine definite de utilizator în legătură cu procesarea imaginii. Imaginea de intrare ce conține numărul de înmatriculare este aliniată orizontal la același unghi cu cel al axei orizontale.
Convertirea din imagine RGB în nuanțe de gri
Algoritmul pentru identificarea poziției numărului de înmatriculare este independent de tipul culorilor din imagine și se bazează în special pe nivelurile de gri ale imaginii penrtu procesarea și extragerea informațiilor necesare. Valorile componentelor de culoare roșu, verde și albastru nu sunt folosite pe parcursul algoritmului de localizare. Prin urmare, dacă imaginea ce va fi procesată este reprezentată în Matlab ca un tablou tridimensional, aceasta este convertită într-o imagine gri bidimensională înainte de a continua orice fel de procesare.[11]
În secvența de cod urmatoare imaginea originală (Fig.12) este convertită în nuanțe de gri (Fig.13).
% I -matricea corespunzătoare imagininii inițiale
r=I(:,:,1); % matricea nuanțelor de roșu
g=I(:,:,2); % matricea nuanțelor de verde
b=I(:,:,3); % matricea nuanțelor de albastru
gray=0.2989*r+0.5870*g+0.1140*b; %transformare în gri
Imaginea RGB convertită în imagine gri:
Fig. 12.Imaginea originalăFig. 13.Imaginea în nuanțe de gri
Dilatarea imaginii
Dilatarea este un proces de simplificare a imaginii originale prin umplerea găurilor din imagini, ascuțirea marginilor obiectelor, unirea liniilor întrerupte și îmbunătățirea luminozității imaginii. De asemenea, zgomotul poate fi înlăturat prin acest procedeu. Prin ascuțirea marginilor, diferența valorii de gri între pixelii învecinați de pe marginile unui obiect poate fi îmbunătățită, ceea ce ajută la detectarea marginilor.
În cazul detectării numărului de înmatriculare, imaginea unei plăcuțe nu va avea aceleași umbre și nuanțe. Din acest motiv imaginea trebuie convertită. Totuși, pe parcursul conversiei anumiți parametrii importanți precum diferența de culoare, margini mai luminoase ale obiectelor sunt pierduți. Procesul de dilatare ajută la anularea acestor pierderi. În secvența de cod următoare, imaginea în nuanțe de gri este dilatată, iar rezultatul îl putem vedea în Fig.14.
[lin col]=size(gray);
dilatare=gray;
for i=1:lin
for j=2:col-1
aux=max(gray(i,j-1),gray(i,j));
dilatare(i,j)=max(aux,gray(i,j+1));
end
end
I=dilatare;
Fig. 14.Imaginea dilatată
Procesarea marginilor orizontale și verticale din imagine
Histograma este un grafic prin care se reprezintă valorile unei variabile într-un anumit domeniu. Histogramele orizontale și verticale folosite în detectarea numărului de înmatriculare reprezintă histogramele datelor de pe coloană, respectiv de pe linii. Graficele reprezintă sume de diferențe de valori de gri dintre pixelii învecinați din imagine.
Prima histogramă care se calculează este cea orizontală. Pentru a se putea determina histograma, algoritmul parcurge toate liniile și coloanele imaginii. Pe fiecare linie algoritmul începe cu al doilea pixel. Se calculează diferența dintre al doilea și primul pixel. Dacă valoarea depășește un anumit prag, este adăugată la suma totală de diferențe. După aceasta, algoritmul se va deplasa la dreapta,pe coloane, pentru a calcula diferența dintre al treilea și al doilea pixel. Algoritmul evaluează diferențele dintre pixelii învecinații până ajunge la ultimul pixel de pe linie. În final, se va obține un vector ce conține datele de pe fiecare linie. Se procedează la fel pentru obținerea histogramei pe verticală, cu diferența că sunt evaluate coloanele. În următoarele secvențe de cod calculăm diferențele dintre pixelii vecini, atât pentru marginile orizontale cât și verticale.
Margini orizontale:
dif=0;
sum=0;
total=0;
dif=uint32(dif);
max_h=0;
maxim=0;
for i = 2:col
sum=0;
for j = 2:lin
if I(j,i) > I(j-1,i)
dif=uint32(I(j,i)-I(j-1,i));
else
dif=uint32(I(j-1,i)-I(j,i));
end
if(dif>20)
sum=sum+dif;
end
end
horz1(i)=sum;
Margini verticale:
dif=0;
sum=0;
total=0;
dif=uint32(dif);
max_v=0;
maxim=0;
for i=2:lin
sum=0;
for j=2:col
if I(i,j)>I(i,j-1)
dif=uint32(I(i,j)-I(i,j-1));
else
dif=uint32(I(i,j-1)-I(i,j));
end
if dif>20
sum=sum+dif;
end
end
vert1(i)=sum;
Trecerea histogramelor printr-un filtru low-pass
Așa cum se va putea vedea din figurile histogramelor (Fig.15/Fig.16), valorile
acestora se modifică drastic între coloane și rânduri consecutive. Prin urmare, pentru a evita pierderi de informații importante în procesele următoare este de preferat ca modifcările drastice de valori din histogramă să fie netezite, aceasta se realizează folosind un filtru low-pass digital. [2]
Astfel, fiecare valoare din histogramă este mediată în funcție de valorile din partea dreaptă și stângă. Acest procedeu se aplică atât histogramei orizontale cât și celei verticale după cum putem vedea în secvențele de cod următoare:
Histograma orizontală:
sum=0;
horz=horz1;
for i= 21:(col-21)
sum=0;
for j=(i-20):(i+20)
sum=sum+horz1(j);
end
horz(i)=sum/41;
end
Histograma verticală:
sum=0;
vert=vert1;
for i=21:(lin-20)
sum=0;
for j=(i-20):(i+20)
sum=sum+vert1(j);
end
vert(i)=sum/41;
end
Filtrarea regiunilor nedorite din imagine
După ce histogramele sunt trecute prin filtrul low-pass digital, se aplică un filtru
pentru a îndepărta zonele nedorite din imagine. În această situție, zonele nedorite sunt cele cu valori mai mici ale histogramelor. O valoare mică din histogramă indică faptul că acea parte din imagine conține variații mici printre pixelii vecini.
Având în vedere că o zonă cu număr de înmatriculare conține un fundal alb cu
caractere alfa-numerice în el, diferența între pixelii învecinați va fi foarte mare, în special la marginile caracterelor și plăcuței de înmatriculare. Aceasta se traduce printr-o valoare mare din histogramă pentru o astfel de imagine.
Prin urmare, o regiune în care este probabil să existe numărul de înmatriculare va avea valori mari în histograma verticală și orizontală. Zonele cu valori mai mici nu mai sunt necesare și sunt îndepărtate din imagine prin aplicarea unui threshold dinamic.
Pentru algoritmul considerat, threshold-ul dinamic este egal cu valoarea medie dintr-o histogramă. Ambele histograme trec prin acest proces de filtrare a zonelor de interes. Rezultatul acestui proces este o histogramă prin care se prezintă zonele cu posibilitate mare de a conține numărul de înmatriculare (Fig.15/Fig.16). Secvențele de cod în care sunt eliminate valorile nenecesare sunt următoarele:
Histograma orizontală:
for i=1:col
if horz(i)<media
horz(i)=0;
for j=1:lin
I(j,i)=0;
end
end
end
Histograma verticală:
for i=1:lin
if vert(i)<media
vert(i)=0;
for j=1:col
I(i,j)=0;
end
end
end
Fig. 15.Prelucrarea histogramelor orizontale
Fig. 16.Prelucrarea histogramelor verticale
Segmentarea
În această etapă se caută zonele din imagine care ar putea conține ceea ce ne
interesează. Coordonatele acestor zone probabile sunt reținute într-un vector și sunt folosite pentru extragerea zonei de interes. Secvența următoare de cod creează regiuni de interes din vectorii histogramelor, iar rezultatul poate fi văzut în Fig. 17.
j=1;
for i=2:col-2
if (horz(i)~=0 && horz(i-1)==0 && horz(i+1)==0)
coloana(j)=i;
coloana(j+1)=i;
j=j+2;
elseif ((horz(i)~=0 && horz(i-1)==0) || (horz(i)~=0 && horz(i+1)==0))
coloana(j)=i;
j=j+1;
end
end
j=1;
for i=2:lin-2
if (vert(i)~=0 && vert(i-1)==0 && vert(i+1)==0)
linie(j)=i;
linie(j+1)=i;
j=j+2;
elseif ((vert(i)~=0 && vert(i-1)==0) || (vert(i)~=0 && vert(i+1)==0))
linie(j)=i;
j=j+1;
end
end
[aux marime_col]=size(coloana);
if mod(marime_col,2)
coloana(marime_col+1)=col;
end
[aux marime_lin]=size(linie);
if mod(marime_lin,2)
linie(marime_lin+1)=lin;
end
Fig. 17.Posibile zone de interes
Extragerea zonei de interes
Rezultatul segmentării constă în afișarea zonei cu probabilitate maximă de a
conține numărul de înmatriculare. Dintre toate zonele, cea cu valoarea de histogramă cea mai mare este considerată cel mai bun candidat.
Toate regiunile sunt evaluate și procesate în funcție de datele de pe rânduri și coloane pentru a găsi o regiune comună care să aibă valorile maxime pentru histogramele orizontale și verticale.
În secvența următoare de cod sunt testate toate regiunile de interes posibile, iar cea care are probabilitate maximă de a reprezenta numărul de înmatriculare este decupată din imagine (Fig.18).
for i=1:2:marime_lin
for j=1:2:marime_col
if (max_h>=coloana(j)&&max_h<=coloana(j+1))&&(max_v>=linie(i)&&max_v<=linie(i+1))
I=imcrop(I,[coloana(j),linie(i),coloana(j+1)-coloana(j),linie(i+1)-linie(i)]);
end
end
end
Fig. 18.Zonă de interes
4.1.4 Recunoașterea caracterelor
După identificarea zonei de interes ce conține numărul de înmatriculare din imaginea prorpiu-zisă, urmează recunoașterea caracterelor din regiunea identificată.
Recunoașterea caracterelor se face prin împărțirea imaginii cu numărul de înmatriculare în imagini ce conțin caractere individuale încadrate perfect în imagine, adică se urmărește ca imaginile obținute să fie imaginile în care sunt încadrate doar caracterele plăcuței, astfel încât să nu existe reziduuri care pot influența algoritmul de detectare al caracterului. Metoda de recunoaștere a caracterelor este aceea de comparare a fiecărei imagini cu șabloane deja existente, stocate într-o bibliotecă. Este de preferat ca șabloanele să fie realizate la o calitate bună, deoarece fiecare imagine segmentată căreia îi corespunde un caracter, va fi redimensionatăla mărimea imaginilor șabloanelor. Având în vedere faptul că imaginea originală nu este preluată la nivel perpendicular, iar unghiul de rotație nu este întotdeauna 0, imaginile caracterelor nu vor fi identice cu cele ale șabloanelor și vor avea o calitate mult mai slabă decât acestea. Acesta este motivul pentru care se optează pentru redimensionarea caracterelor la o dimensiune mai mică.
Odată cu redimensionarea imaginilor ce corespund caracterelor, acestea sunt stocate într-un vector de imagini. Imaginile din vector vor fi comparate logic, pe rând, cu fiecare șablon. După compararea imaginii cu toate șabloanele, algoritmul selecteză șablonul cu cei mai mulți pixeli indentici din bibliotecă. Se introduce primul caracter din numele șablonului în șirul de caractere în care este construit numărul de înmatriculare și se trece la următoarea imagine din vectorul de imagini. Când toate imaginile din vector au fost procesate, se afișează șirul de caractere contruit. Acesta este procesul de identificare a caracterelor din imagini.
Examinarea algoritmului de identificare a caracterelor
Convertirea imaginii din nuanțe de gri în imagine binară
Pentru a putea face o identificare corectă a caracterelor este necesară
convertirea imaginii în formatul binar. Acest lucru se face în următoarea secvență de cod, iar rezultatul poate fi observat în Fig. 19.
I=imadjust(I);
level=graythresh(I);
Bin=im2bw(I,level);
Fig. 19.Imaginea după convertirea în binar
Funcția graythresh returnează valoarea globală medie a nivelului de gri din
imaginea indicată. Aceasta este folosită ca valoare de prag pentru binarizarea imaginii cu ajutorul funcției im2bw, pentru ea se specifică imaginea ce trebuie convertită și pragul de gri.
Binarizarea imaginii înseamnă transformarea tuturor coeficienților de gri în valori de 0 sau 1, în funcție de valoarea de prag: pentru coeficienții de gri între 0 și valoarea de prag specificată, imaginea binară va conține doar valoarea 0, negru, iar pentru coeficienții mai mari decât valoarea de prag până la valoarea maximă de gri 255, imaginea binară va conține valoarea 1.
Imaginea obținută conține elemente parazite din punctul de vedere al identificării caracterelor. Aceste elemente trebuie eliminate și se realizează cu ajutorul funcției bwareaopen, care înlătură din imagine elementele (obiectele) care au mai puțin de numărul de pixeli specificați.
Identificarea obiectului în care se află caracterele
Pentru a scăpa de zonele din imagine care nu conțin caractere din numărul
de înmatriculare și de alte reziduuri, am decis să detectez cel mai mare obiect din imagine (cea mai mare porțiune de alb) și să o salvez într-o nouă imagine:
cc=bwconncomp(Bin,8);
obj=regionprops(cc,'basic');
obj_area=[obj.Area];
[area_max,id]=max(obj_area);
ob=false(size(Bin));
ob(cc.PixelIdxList{id})=true;
Funcția bwconncomp este folosită pentru identificarea componentelor într-o
imagine binară. Aceasta crează o structură, numită de mine ‚cc’ , cu patru câmpuri numite automat Connectivity, ce reprezintă conectivitatea componentelor, ImageSize, mărimea imaginii ( în cazul meu, numită Bin ), NumObjects, numărul de obiecte (componente ) și PixelIdList, un vector cu mărimea egală cu numărul de obiecte și care pentru fiecare obiect reține locația pixelilor într-un vector.
Funcția regionprops oferă un set de proprietăți pentru obiectele dintr-o imagine binară, cum ar fi Area, valoarea suprafeței obiectului (numărul de pixeli), Centroid, ajută la identificarea centrului obiectului și BoundingBox, cel mai mic dreptunghi creat în jurul obiectului, ce are ca parametrii coordonata lui x și y pentru colțul din stânga sus al dreptunghiului, lungimea și înălțimea dreptunghiului.
Prin algoritmul de mai sus am identificat componentele din imagine, le-am salvat într-o structura numită obj, am identificat și am reținut id-ul obiectului cu suprafața cea mai mare, apoi am creat într-o altă imagine porțiunea de alb în care se află caracterele. O problemă pe care am întâmpinat-o a fost faptul că porțiunile de alb din interiorul caracterelor P,B etc., sunt considerate și ele obiecte și nu sunt introduse în noua imagine. Pentru a rezolva această problemă, am creat un algoritm ce detectează obiectele incluse în cel mai mare obiectși le adaugă în noua imagine:
A=obj(id).BoundingBox;
for i=1:cc.NumObjects
B=obj(i).BoundingBox;
if ((i~=id)&&(A(1)+A(3))>=(B(1))&&(A(1))<=(B(1)+B(3))&&(A(2)+A(4))>=(B(2))&&(A(2))<=(B(2)+B(4)))
ob(cc.PixelIdxList{i})=true;
end
end
Bin=imcrop(Bin,A);
[lin, col]=size(Bin);
În vectorul A am reținut valorile parametrilor câmpului BoundingBox pentru obiectul cu suprafața maximă, iar în B valorile parametrilor pentru restul de obiecte.
După ce au fost parcurse toate obiectele și au fost adăugate cele care satisfac condițiile, am tăiat imaginea originală, obținând o imagine de interes mai mică.
Alte preprocesări
3.1 Eliminarea regiunii reprezentative țării
O altă problemă pe care am identificat-o, în unele cazuri, porțiunea de pe
plăcuța de înmatriculare specifică identificării țării de proveniență al autoturismului, este inclusă în noua imagine (obiect). Acest lucru încurcă algoritmul de identificare al caracterelor. Pentru a scăpa de această regiune am parcurs imaginea de la stânga la dreapta, până am identificat o porține de alb mai mare decât jumătate din numărul liniilor. Acest lucru semnifică începerea porțiunii de alb, unde se află caracterele necesare identificării. În secvența următoare de cod, am tăiat imaginea vertical din acel punct, scăpând astfel de o altă regiune nenecesară.
count=0;
for i=2:col
for j=2:lin
if Bin(j,i)==1
count=count+1;
end
end
if count>lin/2
break;
end
count=0;
end
Bin=imcrop(Bin,[i 1 col-i lin]);
[lin, col]=size(Bin);
3.2 Eliminarea marginilor
În unele cazuri, după ce segmentarea a fost făcută și s-a ales zona de interes, există regiuni în imagine care fac parte din plăcuță, dar nu sunt în totalitate albe. Dacă acestea sunt identificate ca obiecte ce nu fac parte din porțiunea de interes (obiect cu suprafață maximă), acestea sunt eliminate în pașii precedenții. Dacă aceste porțiuni nu sunt eliminate, algoritmii de mai jos verifică dacă există aceste porțiuni și segmentează imaginea astfel încât să nu mai fie prezente.
%margine jos
count=0;
for i=lin:-1:2
for j=2:col
if Bin(i,j)==1
count=count+1;
end
end
if count>col/2
break;
end
count=0;
end
Bin=imcrop(Bin,[1 1 col i]);
[lin, col]=size(Bin);
%margine dr
count=0;
for i=col:-1:2
for j=2:lin
if Bin(j,i)==1
count=count+1;
end
end
if count>lin/2
break;
end
count=0;
end
Bin=imcrop(Bin,[1 1 i lin]);
[lin, col]=size(Bin);
3.3 Ștergerea obiectelor mai mici sau mai mari decât caracterele
Pentru a detecta mărimea unui caracter a fost nevoie să inversăm valorile imaginii binare și să creăm obiecte din caracterele și reziduurile încă aflate în imagine. Pentru asta am folosit funcția imcomplement. Aceasta înlocuiește într-o imagine binară valorile de 0 cu 1 și invers. După obținerea obiectelor și verificarea suprafețelor lor, am creat o imagine doar cu obiectele cu o suprafață mai mică de 1400 pixeli și mai mare de 250 pixeli, valori în care se gasesc regiunile reprezentate de caractere în cele mai multe cazuri.
Bin2=imcomplement(Bin);
cc=bwconncomp(Bin2,8);
obj=regionprops(cc,'basic');
areamea=[obj.Area];
ob=true(size(Bin2));
for i=1:length(areamea)
if areamea(i)>250&&areamea(i)<1400
ob(cc.PixelIdxList{i})=false;
end
end
Astfel, în noua imagine rămân doar caracterele necesare segmentării. Chiar dacă după aceste procesări încă se mai găsesc reziduuri, acestea vor fi eliminate în procesul de segmentare.
Segmentarea
După ce imaginea a fost procesată și au rămas doar caracterele ce identifică
plăcuța de înmatriculare, pentru recunoașterea lor, este necesară segmentarea fiecăruia și adăugarea lor într-un vector de imagini.
Folosind iar funcțiile bwconncomp și regionprops, am identificat obiectele din imagine. Verificăm încă o dată dacă obiectul detectat reprezintă un caracter sau dacă este un reziduu. Dacă obiectul din imagine se încadrează în mărimile unui caracter în situații normale, acesta este decupat și adăugat în vectorul de imagini.
După ce toate caracterele sunt detectate și adăugate în vector, îl parcurgem pentru a redimensiona imaginile, să corespundă cu dimensiunile imaginilor aflate deja în biblioteca de șabloane. Acest lucru este necesar pentru a putea efectua o comparație logică între două imagini. Vectorul de imagini rezultat în urma secvenței de cod următoare, poate fi văzut în Fig. 20.
[lin, col]=size(Bin);
Bin=imcomplement(ob);
cc=bwconncomp(Bin,8);
obj=regionprops(cc,'basic');
j=0;
for i=1:cc.NumObjects
D=obj(i).BoundingBox;
if D(4)>35&&D(3)<100
j=j+1;
caractere(j)=i;
end
end
Camere=cell(length(caractere),1);
for i=1:length(caractere)
D=obj(caractere(i)).BoundingBox;
Camere{i}=imcrop(imcomplement(Bin),D);
end
for i=1:length(caractere)
Camere{i}=imresize(Camere{i},[50 20]);
imshow(Camere{i});
pause(1);
end
Fig. 20. Vector de imagini
Recunoașterea caracterelor
Acum că avem vectorul de imagini format din caractere, am creat un algoritm ce construiește șirul de caractere str prin adăugarea fiecărui caracter identificat.
Funcția pathsalvează drumul până la folderul unde se află biblioteca de șabloane.
Funcția dirsalvează în structura fișiereproprietățile imaginilor aflate la locația lui path, în câmpuri cum ar fi name, date, bytes(numele fișierului, data ultimei modificări, mărimea fișierului în octeți) .
Funcția bwareaestimează valoari pentru suprafațele cu pixelii diferiți de 0 dintr-o imagine binară.
Pentru a asocia imaginile din vectorul de imagini cu cele din biblioteca de șabloane, este necesară parcurgerea acestora.
Se selectează prima imagine din vectorul de imagini și se estimează un procent ce reprezintă suprafața pixelilor dată de caracter (procent1). Apoi, se compară logic imaginea cu primul șablon din biblioteca de imagini, obținându-se astfel o nouă imagine. Se estimează un procent de suprafață și pentru aceasta (procent2). Pentru toate imaginile din șablon se repetă procedeul și se memorează șablonul cu procentul cel mai apropiat de procentul imaginii. Primul caracter din numele șablonului este apoi adăugat în șirul de caractere ce reprezintă plăcuța de înmatriculare. Se repetă procedeul până când a fost parcurs tot vectorul de imagini segmentate, obținându-se astfel șirul de caractere necesar. Algoritmul de recunoaștere a caracterelor este reprezentat în secvența de cod următoare:
str='';
path='caracter';
fisiere=dir([path '\*.jpg']);
for k=1:length(Camere)
procent3=0;
bestmatch=1;
procent1=bwarea(Camere{k})/600;
for file=fisiere'
poze=strcat('caracter/',file.name);
LL=imread(poze);
LL=imresize(LL,[50 20]);
LL=Camere{k}&LL;
procent2=bwarea(LL)/600;
if procent2>procent3
procent3=procent2;
bestmatch=file;
end
end
str=strcat(str,bestmatch.name(1));
end
Acum că avem numărul de înmatriculare salvat într-un șir de caractere, îl putem afișa în interfața grafică într-un câmp static de text.
Interfața grafică
Pentru interpretarea mai ușoară a algoritmului de recunoaștere a numărului de
înmatriculare și pentru a observa mai ușor rezultatele fără a fi nevoie de comenzi în codul sursă, se va folosi o interfață grafică (Fig.21).
Fig. 21.Interfața grafică
Pentru această interfață grafică se folosește o listă din care poate fi selectată imaginea dorită, un buton de activare prin care se pornește procesul de identificare al plăcuței și recunoaștere al numărului de înmatriculare. De asemenea, pentru afișarea imaginilor procesate și a obiectelor identificate în imagini se folosesc obiecte de tip axes, iar pentru afișarea mesajelor și a șirului de caractere se folosesc obiecte de tip static text.
4.2 Analiza rezultatelor și performanței aplicației
Metoda tratată de mine în acest proiect este o metodă universală de localizare și recunoaștere a diferitelor plăcuțe de înmatriculare, în condiții diferite de luminozitate și mediu. Aceasta are capacitatea de a recunoaște corect plăcuța de înmatriculare aflată în imagine, într-un timp scurt, chiar dacă aceasta este murdară sau conține puține deteriorări.
Algoritmul de localizare și recunoaștere a fost testat pe multiple numere de înmatriculare, fotografiate în diferite condiții de luminozitate sau background și calități ale imaginii diferite. Câteva dintre aceste rezultate pot fi observate în Fig.22.
b)
c) d)
e) f)
Fig. 22. (a),(c),(e) Imagini ale mașinilor (b),(d),(f) Imagini ale plăcuțelor detectate
Tabelul ce urmează arată rata de succes a localizării și recunoașterii plăcuțelor în diferite condiții:
Tabel 1: Performanța detectării plăcuțelor și recunoașterii caracterelor în diferite condiții de luminozitate
Testele au fost făcute pe un set de 100 de imagini. Setul conține imagini cu condiții diferite de luminozitate, pe timp de zi sau de noapte. În acest set de imagini au fost incluse doar mașini cu gabarit normal, fară autobuze, microbuze sau motociclete. Setul conține și câteva imagini cu plăcuțe de înmatriculare ce aparțin altor țări precum Italia sau Germania. Imaginile au fost făcute de la aceeași distanță, la un unghi relativ egal. Toate autovehiculele din imagini erau staționare în momentul fotografierii. Majoritatea imaginilor din setul testat sunt descrise prin elementele: rezoluție 2570×1920, 24-biți spațiu de culoare și format JPEG.
Proiectul poate fi dezvoltat în continuare prin adăugarea unei baze de date ce conține informații despre proprietarii mașinilor și plăcuțele lor de înmatriculare. În acest mod, poate fi creat un sistem automat de colectare a plății, administrare a traficului, aplicare a legilor, parcare și toate acestea în timp real.
Concluzii
Lucrarea de față, intitulată ,,Aplicație pentru localizarea plăcuțelor de înmatriculare ale autovehiculelor din imagini și pentru recunoașterea caracterelor’’, are ca obiectiv dezvoltarea unei aplicații software prin care să fie posibilă localizarea și recunoașterea numărului de înmatriculare a mașinii.
Tehnologia OCR de recunoaștere a numărului de înmatriculare este una destul de populară în perioada recentă. Popularitatea acesteia a crescut datorită costurilor reduse, fiabilității și rezultatelor bune pe care le oferă.
Totuși, există posibilitatea ca rezultatele oferite de un astfel de proces să nu fie printre cele mai bune. Motivul acestor erori se datorează unei serii de factori precum: lumina mediului în care se preiau imaginile nu este una ideală, plăcuța cu numărul de înmatriculare nu este într-o poziție perfect dreaptă sau murdăria acumulată nu permite identificarea corectă, distanța de la care se face poza și înclinarea camerei nu sunt ideale. Acești factori sunt de natură fizică, dar la sursa de erori se mai adaugă erori de interpretare: litera I poate fi ușor confundată cu cifra 1 iar litera O de asemenea poate fi confundată cu cifra 0. Din acest motiv, pe structura numerelor românești se evită ca grupul de 3 litere să înceapă cu literele I sau O iar litera Q lipsește din orice fel de înregistrare a numerelor de înmatriculare deoarece poate fi foarte ușor confundată cu O sau 0.
Cu toate acestea, rezultatele obținute pe imaginile testate sunt unele pozitive într-o proporție mare.
Principalele obiective pe care mi le-am propus în realizarea acestui proiect au fost:
Identifcarea zonei de interes din imaginea ce conține un autoturism
Pentru a îndeplini acest obiectiv a fost nevoie să obțin cunoștințe de Matlab cu privire la:
Reprezentarea imaginilor digitale;
Citirea, scrierea și afișarea imaginilor;
Procesarea imaginilor color/grayscale/binare;
Recunoașterea obiectelor din imagini;
Procese de segmentare a imaginilor.
Recunoașterea caracterelor numărului de înmatriculare
Pentru acest obiectiv a trebuit să obțin informații cu privire la tehnicile curente de detectare a caracterelor și să folosesc o metodă eficientă.
După îndeplinirea obiectivelor propuse, rezultatul obținut este unul satisfăcător, aplicația putând fi îmbunătățită considerabil. În primul rând, îmbunătățirea algoritmului de detectare a plăcuței este necesară, pentru a evita situații când porțiuni din backgroud sunt identificate ca și plăcuță de înmatriculare. Este necesar și un algoritm de skewpentru a modifica unghiul la care se află plăcuța pe plan, în cazul când aceasta nu este așezată orizontal, acesta fiind util pentru o segmentare corectă a caracterelor. Recunoașterea caracterelor în sistemele automate curente se face folosind rețele neuronale. Această metodă poate fi implementată în aplicația mea, pentru a reduce rata erorilor de recunoaștere a caracterelor. Adăugarea unei baze de date poate fi o opțiune, mai ales dacă aplicația dorește a fi folosită pentru controlul accesului într-o parcare privată sau metode de control al traficului.
Am ales această aplicație pentru că subiectul este unul foarte interesant și actual și pentru că am întâmpinat în viață probleme care puteau fi rezolvate printr-un astfel de sistem. În timp ce stăteam în fața barierei unei parcări private și sistemul dotat cu cartelă nu era funcțional, mi-au trecut prin cap diferite soluții prin care această problemă putea fi evitată. Chiar dacă aplicația creată de mine mai necesită multe îmbunătățiri până să fie implementată într-un astfel de mediu, consider că aplicația este bună și este un punct de start pentru viitoarele implementări.
Pe tot parcursul programării aplicației mi-a făcut plăcere să învăț și să aplic tehnicile și metodele necesare în astfel de sisteme, folosindu-mi propriile idei și cunoștințe în realizarea ei și chiar savurând fiecare moment. Chiar dacă am întâmpinat unele probleme, am reușit să le depășesc căutând informații sau soluții alternative pentru rezolvarea lor.
Am învățat multe lucruri utile din această experiență, atât lucruri teoretice legate de astfel de sisteme cât și de programare într-un astfel de mediu precum Matlab.
ANEXĂ
Codul sursă al aplicației pentru localizarea plăcuțelor de înmatriculare ale autovehiculelor din imagini și pentru recunoașterea caracterelor.
Crearea listei cu imaginiluate din folderul ,,Final’’:
function listbox1_Callback(hObject, eventdata, handles)
% hObject handle to listbox1 (see GCBO)
% eventdata reserved – to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Hints: contents = cellstr(get(hObject,'String')) returns listbox1 contents as cell array
% contents{get(hObject,'Value')} returns selected item from listbox1
arrayfun(@cla,findall(0,'type','axes'));
nume=get(handles.listbox1,'Value');
nume=num2str(nume);
I=imread(strcat('Final/',nume,'.jpg'));
I=imresize(I,[600 800]);
axes(handles.axes1);
imshow(I);
set(handles.text,'string',' ');
% – Executes during object creation, after setting all properties.
function listbox1_CreateFcn(hObject, eventdata, handles)
% hObject handle to listbox1 (see GCBO)
% eventdata reserved – to be defined in a future version of MATLAB
% handles empty – handles not created until after all CreateFcns called
% Hint: listbox controls usually have a white background on Windows.
% See ISPC and COMPUTER.
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
set(hObject,'BackgroundColor','white');
end
Algoritmul executat la apăsarea butonului de start:
% – Executes on button press in buton.
function buton_Callback(hObject, eventdata, handles)
% hObject handle to buton (see GCBO)
% eventdata reserved – to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
nume=get(handles.listbox1,'Value');
nume=num2str(nume);
I=imread(strcat('Final/',nume,'.jpg'));
axes(handles.axes1);
I=imresize(I,[600 800]);
imshow(I);
r=I(:,:,1);
g=I(:,:,2);
b=I(:,:,3);
gray=0.2989*r+0.5870*g+0.1140*b;%grayscale
[lin col]=size(gray);
dilatare=gray;
for i=1:lin
for j=2:col-1
aux=max(gray(i,j-1),gray(i,j));
dilatare(i,j)=max(aux,gray(i,j+1));
end
end
I=dilatare;
%% Margini Orizontale
dif=0;
sum=0;
total=0;
dif=uint32(dif);
max_h=0;
maxim=0;
for i = 2:col
sum=0;
for j = 2:lin
if I(j,i) > I(j-1,i)
dif=uint32(I(j,i)-I(j-1,i));
else
dif=uint32(I(j-1,i)-I(j,i));
end
if(dif>20)
sum=sum+dif;
end
end
horz1(i)=sum;
if(sum>maxim) %varf maxim
max_h=i;
maxim=sum;
end
total=total+sum;
end
media=total/col;
axes(handles.axes2);
plot(horz1);
title('Procesarea marginilor orizontale');
xlabel('Coloana –>');
ylabel('Diferenta –>');
pause(1);
%Low pass filter
sum=0;
horz=horz1;
for i= 21:(col-21)
sum=0;
for j=(i-20):(i+20)
sum=sum+horz1(j);
end
horz(i)=sum/41;
end
axes(handles.axes9);
plot(horz);
title('Netezirea histogramei cu un filtru low-pass');
xlabel('Coloana –>');
ylabel('Diferenta –>');
pause(1);
% Prag
for i=1:col
if horz(i)<media
horz(i)=0;
for j=1:lin
I(j,i)=0;
end
end
end
axes(handles.axes10);
plot(horz);
title('Histograma dupa filtrare');
xlabel('Coloana –>');
ylabel('Diferenta –>');
pause(1);
%% Margini Verticale
dif=0;
sum=0;
total=0;
dif=uint32(dif);
max_v=0;
maxim=0;
for i=2:lin
sum=0;
for j=2:col
if I(i,j)>I(i,j-1)
dif=uint32(I(i,j)-I(i,j-1));
else
dif=uint32(I(i,j-1)-I(i,j));
end
if dif>20
sum=sum+dif;
end
end
vert1(i)=sum;
if (sum>maxim) %varf maxim
max_v=i;
maxim=sum;
end
total=total+sum;
end
media=total/lin;
axes(handles.axes3);
plot(vert1);
title('Procesarea marginilor verticale');
xlabel('Linia –>');
ylabel('Diferenta –>');
pause(1);
%low pass filter
vert=vert1;
for i=21:(lin-20)
sum=0;
for j=(i-20):(i+20)
sum=sum+vert1(j);
end
vert(i)=sum/41;
end
axes(handles.axes11);
plot(vert);
title('Netezirea histogramei cu un filtru low-pass');
xlabel('Linia –>');
ylabel('Diferenta –>')
pause(1);
%prag
for i=1:lin
if vert(i)<media
vert(i)=0;
for j=1:col
I(i,j)=0;
end
end
end
axes(handles.axes12);
plot(vert);
title('Histograma dupa filtrare');
xlabel('Linia –>');
ylabel('Diferenta –>');
pause(1);
%%Intervale
j=1;
for i=2:col-2
if (horz(i)~=0 && horz(i-1)==0 && horz(i+1)==0)
coloana(j)=i;
coloana(j+1)=i;
j=j+2;
elseif ((horz(i)~=0 && horz(i-1)==0) || (horz(i)~=0 && horz(i+1)==0))
coloana(j)=i;
j=j+1;
end
end
j=1;
for i=2:lin-2
if (vert(i)~=0 && vert(i-1)==0 && vert(i+1)==0)
linie(j)=i;
linie(j+1)=i;
j=j+2;
elseif ((vert(i)~=0 && vert(i-1)==0) || (vert(i)~=0 && vert(i+1)==0))
linie(j)=i;
j=j+1;
end
end
[aux marime_col]=size(coloana);
if mod(marime_col,2)
coloana(marime_col+1)=col;
end
[aux marime_lin]=size(linie);
if mod(marime_lin,2)
linie(marime_lin+1)=lin;
end
for i=1:2:marime_lin
for j=1:2:marime_col
if (max_h>=coloana(j)&&max_h<=coloana(j+1))&&(max_v>=linie(i)&&max_v<=linie(i+1))
I=imcrop(I,[coloana(j),linie(i),coloana(j+1)-coloana(j),linie(i+1)-linie(i)]);
end
end
end
axes(handles.axes4);
imshow(I);
pause(1);
% Binarizare
I=imadjust(I);
level=graythresh(I);
Bin=im2bw(I,level);
cc=bwconncomp(Bin,8);
obj=regionprops(cc,'basic');
obj_area=[obj.Area];
[area_max,id]=max(obj_area);
ob=false(size(Bin));
ob(cc.PixelIdxList{id})=true;
%Coliziune
A=obj(id).BoundingBox;
for i=1:cc.NumObjects
B=obj(i).BoundingBox;
if ((i~=id)&&(A(1)+A(3))>=(B(1))&&(A(1))<=(B(1)+B(3))&&(A(2)+A(4))>=(B(2))&&(A(2))<=(B(2)+B(4)))
ob(cc.PixelIdxList{i})=true;
end
end
Bin=imcrop(Bin,A);
[lin, col]=size(Bin);
%sterg ro
count=0;
for i=2:col
for j=2:lin
if Bin(j,i)==1
count=count+1;
end
end
if count>lin/2
break;
end
count=0;
end
Bin=imcrop(Bin,[i 1 col-i lin]);
[lin, col]=size(Bin);
%margine jos
count=0;
for i=lin:-1:2
for j=2:col
if Bin(i,j)==1
count=count+1;
end
end
if count>col/2
break;
end
count=0;
end
Bin=imcrop(Bin,[1 1 col i]);
[lin, col]=size(Bin);
%margine dr
count=0;
for i=col:-1:2
for j=2:lin
if Bin(j,i)==1
count=count+1;
end
end
if count>lin/2
break;
end
count=0;
end
Bin=imcrop(Bin,[1 1 i lin]);
[lin, col]=size(Bin);
%sterg obiecte >< caractere
Bin2=imcomplement(Bin);
cc=bwconncomp(Bin2,8);
obj=regionprops(cc,'basic');
areamea=[obj.Area];
ob=true(size(Bin2));
for i=1:length(areamea)
if areamea(i)>250&&areamea(i)<1400
ob(cc.PixelIdxList{i})=false;
end
end
axes(handles.axes5);
imshow(ob);
pause(1);
%Segmentare
[lin, col]=size(Bin);
Bin=imcomplement(ob);
cc=bwconncomp(Bin,8); %Identificarea obiectelor
obj=regionprops(cc,'basic');
j=0;
for i=1:cc.NumObjects
D=obj(i).BoundingBox;
if D(4)>35&&D(3)<100
j=j+1;
caractere(j)=i;
end
end
Camere=cell(length(caractere),1);
for i=1:length(caractere)
D=obj(caractere(i)).BoundingBox;
Camere{i}=imcrop(imcomplement(Bin),D);
end
axes(handles.axes6);
for i=1:length(caractere)
Camere{i}=imresize(Camere{i},[50 20]);
imshow(Camere{i});
pause(1);
end
str='';
path='caracter';
fisiere=dir([path '\*.jpg']);
for k=1:length(Camere)
procent3=0;
bestmatch=1;
procent1=bwarea(Camere{k})/600;
for file=fisiere'
poze=strcat('caracter/',file.name);
LL=imread(poze);
LL=imresize(LL,[50 20]);
LL=Camere{k}&LL;
procent2=bwarea(LL)/600;
if procent2>procent3
procent3=procent2;
bestmatch=file;
end
end
str=strcat(str,bestmatch.name(1));
end
set(handles.text,'String',str);
Copyright Notice
© Licențiada.org respectă drepturile de proprietate intelectuală și așteaptă ca toți utilizatorii să facă același lucru. Dacă consideri că un conținut de pe site încalcă drepturile tale de autor, te rugăm să trimiți o notificare DMCA.
Acest articol: Aplicatie Pentru Localizarea Placutelor de Inmatriculare ale Autovehiculelor din Imagini Si Pentu Recunoasterea Caracterelor (ID: 149466)
Dacă considerați că acest conținut vă încalcă drepturile de autor, vă rugăm să depuneți o cerere pe pagina noastră Copyright Takedown.
