Detectia Si Recunoasterea Fetelor In Imagini de Slaba Calitate

Detecția și recunoașterea fețelor în imagini de slabă calitate

Lucrare de dizertație

CUPRINS

Lista acronimelor

INTRODUCERE

1. DETECȚIA FEȚELOR

1.1. Abordări și soluții în domeniul detecției automate a fețelor

1.2. Metoda Viola-Jones

2. RECUNOAȘTEREA FEȚELOR

2.1. Analiza pe Componente Principale (PCA)

2.2. Rețele neuronale artificiale

2.2.1. Definiție. Proprietăți

2.2.2. Neuronul artificial

2.2.3. Arhitecturi ale RNA

2.2.4. Tipuri și algoritmi de instruire

2.2.5. Aplicații ale rețelelor neuronale artificiale

3. ZGOMOTUL ÎN IMAGINI

4. DESCRIEREA EXPERIMENTULUI

4.1. Arhitectura și implementarea unui sistem de detecție și recunoaștere automată a feței

4.2. Detecția fețelor utilizând algoritmul Viola-Jones

4.3. Recunoașterea fețelor

CONCLUZII

ANEXA 1 53

ANEXA 2 65

BIBLIOGRAFIE 87

Lista acronimelor

NN – Neural Network – rețea neuronală

RNA – rețea neuronală artificială

PCA – Principal Component Analysis – Analiza pe componente principale

INTRODUCERE

Această lucrare abordează o serie de aspecte necesare pentru a construi un sistem capabil de a detecta și recunoaște chipuri umane în imagini de slabă calitate. În ultimii ani, acest subiect a devenit unul de mare interes, mai ales în domeniul securității informației.

În această lucrare se prezintă un sistem cadru general și componentele sale care detectează cu precizie chipuri umane, apoi efectuază o operație de recunoaștere facială.

Primul pas în crearea sistemului este alcătuirea unei baze de date de 1000 portrete. Următorul aspect, foarte important, este alegerea și implementarea unui algoritm de detecție eficient, care să aibă rezultate foarte bune atât în cazul imaginilor de bună, dar mai ales în cazul celor de slabă calitate. Algoritmul ales pentru detecția fețelor este Viola-Jones. Pentru partea de recunoaștere am ales să analizez prin comparație algoritmul PCA și rețelele neuronale.

Contribuțiile personale din domeniul detecției și recunoașterii chipului uman :

Studiul celor mai importante metode de detecție facială

Studiu comparativ al celor mai importante tehnici de recunoaștere facială

Descrierea experimentelor efectuate.

Lucrarea este structurată în patru capitole. Capitolul 1 prezintă principiile detecției fețelor, capitolul 2 trece în revistă noțiunea de recunoaștere facială și prezintă toate etapele necesare implementării. În capitolul 3 este tratată problematica zgomotului în imagini, iar în capitolul 4 este prezentat întreg procesul exprimental. In final, sunt prezentate concluziile și direcțiile de cercetare viitoare.

1. DETECȚIA FEȚELOR

În zilele noastre, practic oricine a avut ocazia să utilizeze o cameră foto digitală obișnuită (sau chiar camera foto a unui telefon mobil ieftin) și a putut observa pe ecranul acesteia cum, la încadrarea subiecților umani, apare (câte) un dreptunghi / pătrat colorat care încadrează figurile respective. Această funcție de localizare automată a fețelor permite o mai bună încadrare, precum și stabilirea automată a parametrilor de focalizare și expunere corectă a fețelor respective, prin comparație cu restul scenei. Probabil însă că puțini sunt aceia care s-au întrebat cum anume reușește camera foto să distingă faptul că într-o anumită regiune a imaginii există o figură umană, iar în altele nu, respectiv că o anumită configurație de pixeli reprezintă o față, în timp ce alte configurații nu. Și asta practic în timp real. Cum camerele foto sau telefoanele mobile, cel puțin cele de clasă medie, ieftine, nu sunt dotate cu cipuri cu putere foarte mare de procesare, înseamnă că algoritmul respectiv și implementarea sa trebuie să fie extrem de eficiente. În plus, software-ul de detecție a fețelor integrat în camerele foto obișnuite a evoluat, ajungând astăzi nu numai să localizeze figurile umane, dar chiar să și identifice apariția zâmbetului pe acestea și să comande declanșarea automată în momentul respectiv [3].

De asemenea, detecția automată a fețelor reprezintă astăzi o componentă fundamentală ca prim pas în aplicațiile din ce în ce mai variate și răspândite de recunoaștere a fețelor, precum și în cele vizând noi modalități evoluate de interacțiune om-calculator. Ea joacă totodată un rol extrem de important și în ceea ce înseamnă etichetarea automată a volumului uriaș de date de tip imagine disponibile pe Internet, într-o nouă paradigmă a acestuia, prin asocierea unor metadate descriptive utile pentru clasificarea lor, stabilirea de legături categoriale și/sau semantice între ele și alte date disponibile și, în cele din urmă, pentru căutarea și regăsirea acestora grupate pe criterii variate.

Totuși, trebuie precizat faptul că problema detectării figurilor umane în imagini nu este tocmai una trivială, datorită varietății uriașe în care acestea pot apărea în percepția senzorului 2-D, atât din cauza trăsăturilor și particularităților fizionomice, culorii, dimensiunilor, poziției, acoperirii parțiale, fundalului complex, dar mai cu seamă din cauza zonelor de lumină și umbră determinate de poziția și distribuția sursei / surselor de lumină [A].

Abordări și soluții în domeniul detecției automate a fețelor

De-a lungul timpului au existat numeroase tipuri de abordări, ca metode, tehnici și algoritmi, pentru găsirea unor soluții optime, fiabile, performante și eficiente, de tratare a problemei detectării figurilor umane în imagini (digitale). Primul sistem de detectare a fețelor a fost dezvoltat în anii '70. La începutul anilor '90, dezvoltarea tehnicilor de recunoaștere a fețelor a făcut necesară și dezvoltarea unor algoritmi mai performanți pentru detectarea acestora, ca prim pas în recunoașterea automată. Detectarea fețelor poate fi privită ca un caz particular al detectării claselor de obiecte, presupunând localizarea acestora în imagini (digitale) indiferent de orientare / poziționare, condiții de iluminare, scalare, particularități și expresie facială. Domeniului i s-a acordat o atenție deosebită în ultimii 15 ani, în principal datorită creșterii numărului de aplicații comerciale și din domeniul legal care necesită autentificarea personală (de exemplu, controlul accesului – care presupune și recunoașterea feței, supravegherea spațiilor publice, interacțiunea om-calculator etc.) pe de o parte și, pe de altă parte, dezvoltarea unui număr mare de dispozitive de captură de imagini ieftine [5].

Deși pentru vederea umană pare o sarcină banală, detectarea automată a fețelor este o problemă dificilă, practic imposibil de definit / precizat și tratat complet și riguros, varietatea modurilor posibile în care pot apărea figurile umane în imagini fiind practic infinită. Și asta nu atât din cauza trăsăturilor și particularităților fizionomice și a dimensiunilor variate ale acestora în diferite imagini, cât mai ales din cauza varietății în percepția lor în 2-D, datorate poziției (orientării / înclinării, scalării) efective în imagine și în special efectelor jocului luminii și al umbrelor asupra reliefului acestora, precum și din cauza contextului înconjurător variat și imprevizibil. Abordările și soluțiile încercate de-a lungul timpului au trebuit să-și propună să facă față tuturor situațiilor care pot fi întâlnite, indiferent de particularitățile subiectului și în orice context de poziționare, dimensiune, scalare, încadrare, fundal, sau iluminare s-ar afla acesta. O altă necesitate pentru majoritatea, datorită specificului aplicațiilor, a fost să producă rezultate în timp real. Unele au reușit mai bine, altele mai puțin bine. Performanța sistemelor de detecție a fețelor este dată de două componente: rata / procentul fals-pozitivelor (confuziilor – raportări false ca fețe ale unor regiuni din imagini care nu conțin în realitate o față), precum și rata / procentul fals-negativelor (rateurilor – regiuni ale imaginilor care în realitate conțineau o față, dar care nu au fost raportate ca atare). Pentru un sistem cât mai general, fiabil și robust, acestea trebuie să fie ambele cât mai mici, ideal tinzând spre zero fiecare.

O observație care trebuie făcută, este aceea că detecția fețelor, indiferent de metoda utilizată, nu este și nu poate fi o știință exactă. Așa cum chiar oamenii pot fi păcăliți de imagini 2-D care par a conține o figură umană deși în realitate nu există niciuna acolo, la fel și algoritmii de detecție a fețelor pot fi induși în eroare în anumite situații. Acest fenomen poartă denumirea de „pareidolia” în limba engleză și se referă la recunoașterea aparentă a ceva semnificativ (de obicei o figură sau siluetă umană) în ceva care nu-l conține în mod natural. Există numeroase exemple în acest sens, poate cel mai spectaculos fiind „figura” de pe Marte – o fotografie luată în regiunea Cydonia de pe Marte ce pare a conține o figură umană sculptată în stâncile de pe solul marțian respective, sau nenumăratele aparente figuri formate de configurațiile noroase sau ale frunzelor copacilor în jocul de lumină și umbră. Așa cum am mai spus, software-ul de detecție a fețelor poate fi de asemenea păcălit de astfel de situații, deci se poate vorbi despre o rată de fals-pozitive (detecții de fețe unde nu sunt) și una de fals-negative (nedetectarea unei fețe acolo unde de fapt exista una) ale acestora.

Putem enumera următorii factori principali care pot induce probleme în detectarea automată a fețelor (în imagini bidimensionale):

poziția și orientarea acestora în imagine (frontal, profil, sub un unghi etc.) – anumite caracteristici faciale (ochi, nas) putând fi parțial sau total ascunse;

prezența / absența unor componente structurale – unele caracteristici faciale precum barbă, mustață, ochelari putând fi, sau nu, prezente și existând o mare variabilitate a acestora din punct de vedere al formei, culorii sau dimensiunilor;

expresia facială – geometria feței fiind afectată de aceasta;

-obturarea – fețele putând fi parțial mascate (acoperite) de alte obiecte (inclusiv alte fețe);

-condțiile în care a fost realizată fotografia – iluminarea (spectrul, poziția și/sau distribuția sursei / surselor de lumină, intensitatea) și caracteristicile aparatului foto (lentilele, senzorul) afectând foarte puternic felul în care o figură apare în imagine.

În general, metodele utilizate, indiferent de tipul acestora, sunt laborioase, presupun numeroase iterații, analize pe diferite criterii, scalări, filtrări, comparații și, evident au solicitat eforturi și timp pentru a fi puse la punct. Unele se bazează pe antrenări anterioare ale unor clasificatoare (în general cu două clase: față și non-față) de diferite tipuri, utilizând rețele neuronale, support vector machines (SVM), modele ascunse (hidden) Markov etc., în timp ce altele încearcă să se bazeze pe cunoștințe și observații a priori codate programatic și utilizate astfel la detecție, iar altele încearcă o mixare între aceste două tipuri de abordări în diferite etape de analiză. În general, toate metodele recurg la multiple operații de scalare și/sau normalizare fie a imaginii, fie a unei subferestre de analiză, prin glisare peste aceasta, ori a modelelor / șabloanelor sau caracteristicilor a căror prezență este verificată în imaginea țintă.

Metoda Viola-Jones

În anul 2001, Paul Viola și Michael Jones au prezentat un cadru nou, inovativ, pentru detectarea obiectelor arbitrare în imagini, pe care l-au rafinat pentru detecția fețelor. Algoritmul este cunoscut drept metoda Viola-Jones și este unul dintre cei mai robuști, performanți, eficienți și utilizați, reprezentând practic un punct de cotitură în dezvoltarea aplicațiilor practice de timp real utilizând detecția fețelor, cum este cazul celor incluse în camerele foto digitale de astăzi [7].

Metoda Viola-Jones oferă o viteză remarcabilă și o rată foarte înaltă de acuratețe – cercetătorii raportând o rată de fals-negative (nedetecție) de sub 1% și una de fals-pozitive de sub 40%, chiar când sunt utilizate doar cele mai simple filtre. Metoda completă utilizează după cum vom arăta mai jos, până la 38 de filtre sau clasificatoare.

Princ care l-au rafinat pentru detecția fețelor. Algoritmul este cunoscut drept metoda Viola-Jones și este unul dintre cei mai robuști, performanți, eficienți și utilizați, reprezentând practic un punct de cotitură în dezvoltarea aplicațiilor practice de timp real utilizând detecția fețelor, cum este cazul celor incluse în camerele foto digitale de astăzi [7].

Metoda Viola-Jones oferă o viteză remarcabilă și o rată foarte înaltă de acuratețe – cercetătorii raportând o rată de fals-negative (nedetecție) de sub 1% și una de fals-pozitive de sub 40%, chiar când sunt utilizate doar cele mai simple filtre. Metoda completă utilizează după cum vom arăta mai jos, până la 38 de filtre sau clasificatoare.

Principala inovație adusă de Viola și Jones a fost aceea de a nu încerca să analizeze direct imaginea în sine, ci anumite „caracteristici” (features) dreptunghiulare în aceasta. Aceste caracteristici, inspirate, printr-o analogie cu analiza formelor de undă complexe din sistemul orto- normal de funcții Haar de bază, sunt cunoscute sub denumirea de „caracteristici de tip Haar” (Haar-like features), după matematicianul ungur Alfred Haar care a trăit și creat la începutul secolului 20. Trebuie făcută totuși – pentru evitarea posibilelor confuzii – precizarea că nu este vorba aici de wavelet-uri Haar. În primul rând, dacă imaginea de analizat este una color, aceasta este transformată într-una în nivele de gri, în care apar doar nivelele de strălucire / luminanță, informația de culoare fiind neglijată. Este de subliniat aici faptul că independența de culoare conferă metodei o mare generalitate. În practică, se poate utiliza pentru fiecare pixel (x, y) al imaginii o relație de forma:

i(x, y) = 0,299 R(x, y) + 0,587 G(x, y) + 0,114 B(x, y) (1.1)

unde valorile R, G, B reprezintă respectiv componentele de roșu, verde și albastru ale valorii respectivului pixel (x, y) în spațiul RGB utilizat frecvent în reprezentarea digitală a imaginilor color, pe 3 sau 4 octeți (24 sau 32 de biți). Valorile sunt cuprinse între 0 și 255 (cât poate fi reprezentat pe un octet).

Viola și Jones au definit mai multe tipuri de astfel de caracteristici, reprezentate prin câte două, trei, sau patru blocuri dreptunghiulare adiacente, cu tentă întunecată și respectiv deschisă. În figura 1.1 sunt reprezentate câteva dintre acestea. Trebuie precizat faptul că într-o anumită caracteristică, toate blocurile dreptunghiulare componente au fiecare aceeași formă și aceleași dimensiuni. Aceste caracteristici pot fi evaluate la orice scală sau poziție în imagine, cele reprezentate în figura de mai sus având dimensiuni arbitrare, doar cu titlu de exemplu. Fiecărei astfel de caracteristici îi este asociată o valoare care este calculată ca diferența între suma pixelilor din regiunea de imagine delimitată de dreptunghiurile deschise, minus suma pixelilor din dreptunghiurile închise care compun caracteristica respectivă. Valoarea caracteristicii este apoi utilizată de un filtru pentru a determina dacă acea caracteristică este prezentă sau nu în imaginea originală [9].

Figura 1.1.: Câteva tipuri de caracteristici definite de Viola și Jones [3]

Pare că mecanismul descris mai sus ar fi destul de costisitor din punct de vedere computațional, adică destul de lent. O a doua inovație spectaculoasă și importantă adusă de metoda Viola-Jones constă într-o optimizare computațională ingenioasă, pentru îmbunătățirea vitezei de însumare a intensităților pixelilor din blocurile dreptunghiulare componente ale caracteristicilor definite.

Astfel, pentru fiecare imagine originală de analizat se generează inițial o așa numită „imagine integrală”, mapată 1 la 1 peste imaginea originală, în care fiecare punct capătă valoarea sumei tuturor pixelilor din imaginea originală situați la stânga și deasupra coordonatelor punctului respectiv, inclusiv.

Valorile tuturor punctelor ii(x, y) din imaginea integrală pot fi calculate cu o singură trecere prin imaginea inițială, pornind din colțul din stânga-sus (x = 0 și y = 0), pixel cu pixel, linie după linie, de sus în jos.

Fie, pentru oricare linie y din imaginea originală:

s(x, y) = s(x-1, y) + i(x, y), cu convenția: s(-1, y) = 0, (1.2)

suma cumulativă a valorilor tuturor pixelilor i(x, y) din linia y până în poziția x inclusiv.

Valoarea oricărui punct (x, y) din imaginea integrală poate fi calculată ca:

ii(x, y) = ii(x, y-1) + s(x, y), cu convenția: ii(x, -1) = 0. (1.3)

Termenul „integrală” are aceiași semnificație ca în definirea matematică a unei integrale, respectiv aria de sub o curbă, obținută prin sumarea unor arii dreptunghiulare elementare. Odată calculată imaginea integrală pentru fiecare punct corespunzător din imaginea originală, suma intensităților pixelilor din oricare dreptunghi arbitrar din aceasta din urmă poate fi calculate cu ușurință. Astfel, pentru calcularea sumei tuturor pixelilor din dreptunghiul abcd din imaginea originală (figura 1.2), pot fi utilizate numai valorile punctelor a, b, c și d corespondente din imaginea integrală, efectuându-se numai trei operații simple (două scăderi și o adunare) între acestea, astfel:

Sabcd = iia – iib – iid + iic. (1.4)

Figura 1.2. Calculul sumei intensităților pixelilor dintr-o regiune dreptunghiulară a imaginii originale utilizându-se valorile punctelor din imaginea integral [3]

În acest mod pot fi calculate extrem de eficient din punct de vedere computațional valorile asociate caracteristicilor definite, la orice scală și în orice poziție în imaginea originală. Dar ce și cum se poate obține pe baza acestora? Prin comparație cu analiza directă a intensității pixelilor, caracteristicile oferă o vedere mai grosieră, în rezoluție scăzută, a imaginii, fiind potrivite pentru caracterizarea unor particularități locale în imagine prin detectarea limitelor între regiuni luminoase și întunecoase, dungi / bare și alte structuri simple.

Ce au realizat mai departe Viola și Jones a fost să implementeze un sistem de antrenare. Au utilizat ca input pentru rutina de detecție a fețelor un set de imagini de 24 x 24 de pixeli conținând fețe și un alt set de astfel de imagini de 24 x 24 pixeli care nu conțineau fețe și au antrenat rutina să recunoască fețele și să elimine non-fețele. Au fost utilizate aproape 5.000 (circa 4.900) de astfel de exemple conținând fețe și 10.000 de exemple de non-fețe, colectate arbitrar de pe Internet.

În ce a constat însă de fapt antrenarea? Utilizând imagini 24 x 24, există circa 45.000 de moduri diferite de a plasa una dintre cele patru tipuri de caracteristici prezentate în figura 1.1 pe o astfel de imagine (sau peste 160.000 în cazul tuturor tipurilor de caracteristici definite de Viola și Jones). De exemplu, pentru primul tip de caracteristică, pot fi considerate dreptunghiuri de 1 x 2 pixeli, până la 1 x 24, apoi 2 x 2 până la 2 x 24 și așa mai departe. Aceste caracteristici de diverse dimensiuni pot fi plasate în poziții diferite pe imagine astfel încât să fie testate toate caracteristicile posibile, de toate dimensiunile posibile, în fiecare poziție posibilă.

Se poate observa imediat că numărul caracteristicilor posibile, de circa 45.000 (sau 160.000), este de departe mai mare ca numărul de pixeli dintr-o imagine 24 x 24, respectiv 576, deci este evident că trebuie redus cumva numărul celor care sunt utilizate. Să ne amintim că pentru fiecare caracteristică se calculează diferența între sumele pixelilor din regiunile deschise și respective închise ale acesteia. Se poate stabili un prag pentru aceste diferențe (care poate fi ajustat în timpul antrenării) pe baza căruia o caracteristică să fie considerată ca detectată sau nu. Utilizându-se acesta, se aplică fiecare dintre cele 45.000 (respectiv 160.000) de caracteristici posibile la setul de învățare [3].

S-a dovedit însă, că anumite caracteristici nu sunt utile în determinarea faptului că o imagine reprezintă o figură sau nu, respectiv că nu există nicio corelație în modul în care o caracteristică identifică o față și respectiv nu o identifică și reciproc. La aceste caracteristici s-a renunțat. Pe de altă parte, alte caracteristici s-au dovedit a avea o rată de succes mare în eliminarea subferestrelor de tip non-față și aici intervine practic învățarea.

Viola și Jones au făcut o serie de experimente cu caracteristicile rămase pentru a determina cea mai bună metodă de utilizare a acestora pentru clasificarea unei imagini ca față sau non-față. În cele din urmă au decis să utilizeze o variantă a unui sistem de învățare automată (machine learning) denumit AdaBoost (de la Adaptive Boosting), pentru a construi un clasificator. AdaBoost este o tehnică de Inteligență Artificială (I.A.) similară rețelelor neuronale, un meta-algoritm adaptiv formulat inițial de Zoav Freund și Robert Schapire, dezvoltat pentru a combina caracteristici slabe într-un clasificator mai puternic. Fiecărei caracteristici dintr-un clasificator îi este atașată o pondere (ajustată în timpul învățării) care definește precizia clasificatorului. Ponderi mici înseamnă caracteristici slabe, în timp ce ponderi mari sunt asociate cu caracteristici puternice.

Dacă suma ponderilor caracteristicilor care au răspuns pozitiv pe o anumită imagine depășește un anumit prag (ajustabil de asemenea în timpul învățării), se decide că imaginea respectivă este o față. Un alt element important care trebuie subliniat este acela că Viola și Jones au utilizat AdaBoost nu numai pentru antrenarea clasificatorului, dar și pentru selectarea unui număr considerabil mai mic dintre toate caracteristicile inițial definite, care să fie utilizate în cele din urmă.

Viola și Jones au constatat în cursul învățărilor că există două caracteristici care, combinate și ajustate corespunzător de AdaBoost într-un singur clasificator, pot recunoaște 100% fețele, cu o rată a fals-pozitivelor de 40% (respectiv, 60% dintre non-fețe sunt rejectate de acest clasificator).

În figura 1.3 este prezentat sugestiv acest tip simplu de clasificator în acțiune. El utilizează două caracteristici pentru a testa imaginea: o caracteristică orizontală, care măsoară diferența între regiunea mai întunecată a ochilor și cea mai luminată a pomeților obrajilor și caracteristica cu trei dreptunghiuri verticale, care testează regiunile mai întunecate ale ochilor cu regiunea mai luminoasă a șeii nazale.

Figura 1.3. Primul clasificator la lucru pe o imagine 24 x 24 [3]

Astfel, cu toate că inițial s-au străduit să implementeze un clasificator puternic prin combinarea a circa 200 de clasificatoare slabe, acest succes timpuriu i-a determinat ca în cele din urmă să construiască mai degrabă o cascadă de clasificatoare cu două clase fiecare, sub forma unui arbore de decizie degenerat, în locul unui singur clasificator uriaș. Această cascadă de filtre, denumită „cascadă atențională” (Figura 1.4), reprezintă cea de-a treia inovație semnificativă introdusă de metoda Viola-Jones.

Fiecare subfereastră a imaginii originale este testată cu primul clasificator. Dacă trece de acesta, este testată cu al doilea. Dacă trece și de acesta, este testată cu al treilea și așa mai departe. Dacă nu trece de un anumit nivel, subfereastra este rejectată ca posibilă față la nivelul respectiv. Numai dacă trece de toate filtrele din cascadă, atunci este clasificată ca fiind o față.

Ce este interesant, este că cel de-al doilea clasificator și următorii nu (mai) sunt antrenați pe întregul set de învățare, ci numai pe acele imagini care nu au fost rejectate de clasificatorii anteriori din lanț. În același timp, subferestrele fals-pozitive scăpate de primele niveluri sunt oferite ca exemple de învățare de non-fețe nivelurilor următoare.

Al doilea clasificator și următorii sunt mai complecși și au mai multe caracteristici decât primul și prin urmare sunt și mai mari consumatori de timp computațional. Este cu atât mai remarcabil faptul că există un astfel de clasificator simplu care să elimine atât de multe subferestre fără a necesita efectuarea calculelor necesare clasificatorilor mai complecși. Pe de altă parte, este mult mai probabil ca imagini aleatoare să nu conțină efectiv o față, sau ca regiunile conținând fețe în acestea să fie relativ puține, iar faptul că majoritatea subferestrelor pot fi eliminate ca posibili candidați cu efort computațional extrem de redus este un lucru benefic.

Figura 1.4. Cascada de clasificatori Viola-Jones [3]

În cele din urmă, Viola și Jones au utilizat 38 de niveluri pentru cascada de clasificatori utilizându-se în primele 5 dintre acestea, respectiv, câte 2, 10, 25, 25 și 50 de caracteristici, iar în total, pentru toate nivelurile, numărul acestora fiind de 6060. Numărul de caracteristici pentru fiecare nivel a fost stabilit empiric, prin încercare și eroare, pentru primele niveluri. Criteriul a fost minimizarea fals-pozitivelor până sub un anumit prag pentru fiecare nivel, concomitent cu menținerea unei rate înalte a recunoașterilor corecte (rată foarte scăzută a fals-negativelor). Au fost adăugate caracteristici fiecărui nivel, în etape, până când criteriile de performanță propuse la nivelul respectiv au fost atinse [9].

Clasificatoarele de pe primele niveluri sunt mai simple și asigură eliminarea foarte rapidă a unui număr mare de subferestre de tip non-față. Astfel, primul clasificator din cascadă utilizează cele două caracteristici descrise mai sus și elimină peste 50% dintre non-fețe, iar următorul, utilizând alte 10 caracteristici, elimină peste 80% dintre non-fețe.

Pentru antrenare s-au utilizat 4.916 exemple de fețe descărcate aleator de pe Internet. decupate și aliniate grosier (manual) și scalate la 24 x 24 de pixeli. În procesul de învățare au fost utilizate ca exemple de fețe și imaginile în oglindă ale acestora față de axa centrală verticală, deci un total de 9.832 de imagini. Exemplele de non-fețe au fost selectate ca subferestre din alte peste 9.500 de imagini aleatoare, de asemenea descărcate de pe internet și verificate manual că nu conțin fețe. Numărul acestor subferestre este de circa 350.000.000, dar numai câte maximum 10.000 au fost utilizate pentru antrenarea fiecărui clasificator din cascadă. Mai trebuie precizat că este vorba de o învățare adaptivă. Dacă pentru primul nivel s-au utilizat subferestre din cele peste 9.500 de imagini non-fețe, pentru nivelurile următoare s-au utilizat subferestrele de tip non-față obținute din fals- pozitivele date de nivelurile anterioare.

Întregul proces de învățare a durat mai multe săptămâni. Nu mai vorbim despre durata experimentărilor pentru alegerea caracteristicilor, a tipului de clasificator, pentru ajustarea ponderilor. Se poate concluziona că este vorba despre o metodă care a presupus o primă etapă extrem de laborioasă, din categoria celor în care învățarea este lentă, dar detecția este foarte rapidă [10].

În final, când se analizează o imagine curentă, detectorul de fețe scanează imaginea completă prin subferestre la mai multe scale și cu mai multe poziționări pentru fiecare scală. Cercetătorii au stabilit că utilizarea unui factor de 1,25 de la o scalare a subferestrei la alta a produs cele mai bune rezultate. Totodată s-a mai constatat că nu este necesar să se testeze neapărat fiecare locație în parte. Chiar dacă se sar câțiva pixeli de fiecare dată la translatarea / glisarea subferestrei de analizat, rezultatele bune nu sunt afectate. Toate aceste observații empirice au permis o mai mare optimizare și o îmbunătățire suplimentară a vitezei de calcul [11].

Ulterior, pentru a face mai bine față situațiilor în care figurile nu apar frontal în imagini, atât Jones și Viola cât și alți cercetători, cum ar fi Lenhart și Maydt au continuat să aducă îmbunătățiri prin extinderea setului de caracteristici utilizate, introducând filtre diagonale sau caracteristici rotite cu 45 de grade, dar au mai existat și alte nenumărate contribuții care au adus completări și îmbunătățiri punctuale metodei [8].

2. RECUNOAȘTEREA FEȚELOR

Fața joacă un rol esențial în relațiile sociale, în comunicarea identității și a emoțiilor. Capacitatea umană de a recunoaște fețele este remarcabilă: putem recunoaște mii de figuri învățate de-a lungul vieții și identifica fețele familiare dintr-o singură privire chiar după ani de zile. Această capacitate este destul de robustă, în ciuda schimbărilor mari în stimulul vizual datorate condițiilor de vizualizare, expresiei, îmbătrânirii și altor factori perturbatori precum prezența ochelarilor, a bărbii sau schimbări ale coafurii [B].

Deși atractivă deoarece nu presupune contact direct între subiect și senzor (se spune că este o tehnică neinvazivă), recunoașterea feței este o sarcină dificilă datorită surselor numeroase de variabilitate în condiții reale. Acestea includ printre altele: orientarea feței în raport cu aparatul de fotografiat sau camera de filmat, nivelul de iluminare, expresia feței, timpul scurs între momentele prelevării unor imagini distincte, precum și aspectele demografice (rasa, vârsta, sexul). Asigurarea invarianței în raport cu transformări elementare precum translația, rotația sau schimbarea rezoluției reprezintă de asemenea o cerință obligatory [12].

Schema-bloc a unui sistem generic de recunoaștere a fețelor se prezintă în figura 2.1, în care se distinge prezența unui modul de extragere a “semnăturii” specifice fiecărei fețe și a unui modul de clasificare, a căror proiectare este de regulă corelată. Există 2 abordări majore pentru a obține informația caracteristică unei fețe, cu avantaje și dezavantaje specifice, ce pot fi folosite pentru extragerea “semnăturilor” de interes atât pentru aplicații de recunoaștere cât și pentru cele de verificare, diferențe apărând datorită tipului de clasificator utilizat:

Figura. 2.1. Schema-bloc a unui sistem de recunoaștere/verificare a fețelor [12]

a) algoritmi bazați pe analiza statistică a imaginilor disponibile, al căror scop constă în identificarea unei baze reprezentative în raport cu care să poată fi exprimată orice imagine sub forma unei combinații liniare de vectori ai bazei. Din această categorie fac parte metode precum Analiza pe Componente Principale (PCA), Analiza Discriminatorie Liniară (LDA) și Analiza pe Componente Independente (ICA).

b) algoritmi bazați pe măsurarea unor trăsături geometrice referitoare la distanțe între puncte semnificative de pe suprafața feței. Ca exemple putem enumera metodele Elastic Bunch Graph Matching și Local Feature Analysis .

2.1. Analiza pe Componente Principale (PCA)

De regulă, bazele de date folosite în experimentele de recunoaștere a fețelor conțin imagini de dimensiune foarte mare. O astfel de “risipă” de resurse, valabilă de altfel și în cazul semnalelor vocale sau al altor imagini naturale, conduce la o robustețe semnificativă, care permite receptarea corectă a informației transmise, chiar în condițiile în care aceasta este afectată de zgomot, este distorsionată sau incompletă. Pe de altă parte, dimensiunile mari complică semnificativ implementarea practică a diverselor tehnici de procesare, cresc volumul de calcul și, în plus, necesită existența unui număr sporit de imagini în baza de date cu care se operează (dacă imaginile originale sunt văzute ca puncte într-un spațiu multidimensional, cu cât dimensiunea spațiului este mai mare, cu atât mai multe puncte sunt necesare pentru a asigura o “acoperire” mai bună a întregului spațiu, în vederea asigurării unei aproximări adecvate a densității reale de repartiție a tuturor punctelor reprezentând imagini valide de fețe umane). În acest context, se dovedesc utile tehnicile de compresie, folosite pentru a reduce dimensiunea datelor originale, în condițiile unor pierderi de informație (inevitabile) cât mai mici [12].

Tehnicile de compresie uzuale aparțin de regulă uneia din următoarele 3 categorii:

a) codare (liniar) predictivă;

b) calcul de transformate liniare;

c) cuantizare vectorială.

În cele ce urmează voi prezenta una dintre cele mai cunoscute metode de compresie aparținând celei de a doua clase, denumită Analiza pe Componente Principale (Principal Component Analysis – PCA) sau transformata Karhunen-Loeve. Astfel, să considerăm că avem la dispoziție N vectori xn aparținând unui spațiu vectorial de dimensiune D cărora li se asociază, prin intermediul unei transformate liniare descrise de matricea [W]MxN, un set de vectori de dimensiune mai mică M < D, conform relației:

yn = Wxn , n = 1…N (2.1.1)

În spațiul original, vectorul xn poate fi scris sub forma unei combinații liniare a elementelor unei baze ortonormate {ui, i = 1…D} sub forma:

xn = (2.1.2)

în care coeficienții wi,n se calculează cu relația:

wi n = xn , n = 1…N (2.1.3)

Să presupunem că dorim să reținem din descompunerea (2.1.2) numai un set redus de M termeni, iar restul coeficienților wi,n să fie înlocuiți cu valori constante:

n = (2.1.4)

Ideea fundamentală a metodei PCA este de a găsi baza particulară care asigură

minimizarea erorii pătratice medii dintre seturile de vectori xn și n:

(2.1.5)

Un rezultat fundamental cunoscut sub denumirea de transformata Karhunen-Loeve (KLT) demonstrează că această bază este formată din vectorii proprii ai matricii de autocovarianță a vectorilor xn:

(2.1.6)

unde desemnează valoarea estimată (pe baza setului finit de N exemple) a valorii medii a procesului aleator reprezentat de vectorii xn. În plus, valorile constantelor ci sunt date de relația:

(2.1.7)

Utilizarea acestor rezultate pentru compresia de date presupune parcurgerea succesivă a câtorva pași: a) calculul valorii medii a vectorilor supuși analizei; b) determinarea valorilor λi și vectorilor proprii ui ai matricii de autocovarianță S; c) aplicarea relației (2.1.5) pentru un număr M < D de vectori proprii corespunzători celor mai mari valori proprii ale matricii de autocovarianță S (așa-numitele componente principale) [13].

În multe aplicații practice se dovedește că cea mai mare parte a energiei semnalelor originale se regăsește acumulată numai într-un număr redus de component principale, iar modalitatea particulară de selecție a acestora este justificată (conform unui calcul elementar) de expresia erorii pătratice medii:

(2.1.8)

Din punct de vedere practic apar dificultăți datorate complexității calculului și memoriei necesare estimării matricii de autocovarianță S și a valorilor/vectorilor proprii ale acesteia. Una dintre soluțiile adoptate este de a înlocui baza ortonormată corespunzătoare transformatei KLT cu cea definită de Transformata Cosinus Discretă (DCT). Pe de altă parte au fost prezentate în literatură o serie de rețele neurale, cele mai multe liniare, capabile să implementeze metoda PCA într-o manieră recursivă, eliminând astfel și dezavantajul variantei standard de a necesita reluarea întregii proceduri de calcul la fiecare apariție a unui vector nou în baza de date [13].

Metoda PCA descrisă anterior a fost aplicată cu succes la recunoașterea fețelor, sub denumirea generică Eigenfaces. ”Materia primă” o constituie ansamblul imaginilor disponibile în baza de date, formate din matrici cu valori reale (eventual – binare). Fiecare astfel de matrice, presupusă de dimensiune (MxN), este mai întâi transformată într-un vector de aceeași lungime, prin concatenarea coloanelor corespunzătoare. Algoritmul de procesare presupune parcurgerea următorilor pași:

a) Se calculează valoarea medie a imaginilor care formează setul de antrenare

(presupus a avea K fotografii):

(2.1.9)

și se „centrează” imaginile originale (se aduc la valoare medie nulă):

(2.1.10)

b) Se calculează așa-numita scatter matrix, care reprezintă aproximarea matricii de covarianță a imaginilor din baza de date (aproximarea este cu atât mai bună cu cât avem mai multe imagini la dispoziție):

(2.1.11)

unde matricea A are pe coloane câte o fotografie centrată:

(2.1.12)

Matricea S este simetrică și are dimensiuni (M*N)x(M*N).

c) Se calculează valorile și vectorii proprii ai matricii S (vectorii proprii ai matricii S în cazul lucrului cu imagini reprezentând fețe poartă denumirea Eigenfaces).

Observații:

a) se poate utiliza un artificiu care reduce volumul de calcul: se calculează valorile și vectorii proprii ai matricii AT A și apoi se folosește relația dintre aceștia din urmă și vectorii proprii ai matricii S.

b) valorile proprii ale matricii S sunt întotdeauna pozitive deoarece S este reală și simetrică.

d) Se ordonează valorile proprii ale matricii S în sens descrescător. Se trasează un grafic care exprimă pierderea de informație în raport cu factorul de compresie.

Astfel, dacă notăm cu λi , i = valorile proprii sortate ale matricii S, graficul anterior se referă la raportul (pe abscisă avem j =:

(2.1.13)

Graficul anterior permite estimarea numărului de valori și vectori proprii considerați semnificativi (adică aceia care păstrează cea mai mare parte din energia imaginilor originale).

e) Se proiecteză imaginile (centrate) originale pe spațiul descris de vectorii proprii reprezentativi (tipic aceștia sunt în număr de 5-10% din numărul total). Proiecția constă de fapt în efectuarea produsului scalar dintre fiecare imagine originală și o matrice având drept coloane numai vectorii proprii semnificativi. Pentru fiecare imagine (centrată) centrat se obține proiecția pe baza relației [13]:

(2.1.14)

(2.1.15)

unde Nmax este numărul maxim de vectori proprii reținuți, Ej sunt vectorii proprii semnificativi, iar vectorii Wj au dimensiunea (Nmax × 1) și pot fi priviți ca „semnăturile” asociate imaginilor originale.

f) Clasificarea imaginilor test presupune mai întâi determinarea „semnăturii” fiecărei imagini în raport cu subpațiul determinat anterior (și care depinde exclusiv de imaginile din setul de antrenare) și găsirea acelei imagini din baza de date de antrenare a cărei semnătură este cea mai apropiată de semnătura imaginii de test.

Aprecierea similitudinii dintre astfel de perechi de imagini se realizează folosind o metrică convenabil aleasă. Opțiunea uzuală este distanța Euclideană (L2), însă se pot utiliza și alte măsuri precum funcția de autocorelație, cosinusul unghiului dintre 2 vectori sau distanța Mahalanobis.

Principalul avantaj al metodei PCA constă în simplitatea sa. Există posibilitatea de a calcula vectorii proprii principali nu numai în variantă off-line prin procedura algebrică descrisă anterior ci și on-line, folosind anumite rețele neurale artificiale pentru a ajusta în mod iterativ valorile acestora, pe măsură ce se aplică date noi la intrare. În cazul aplicării metodei PCA la recunoașterea fețelor, trebuie menționate și o serie de dezavantaje, care limitează performanțele sistemelor bazate pe acest instrument de analiză:

– principalul dezavantaj constă în faptul că ignorarea componentelor care contribuie puțin la energia imaginilor originale nu conduce automat și la îmbunătățirea separării (discriminării) dintre diversele subclase de imagini aparținând unor persoane diferite (altfel spus, minimizarea erorii de reprezentare nu înseamnă neapărat îmbunătățirea performanțelor de clasificare).

– un alt dezavantaj al tehnicii PCA îl reprezintă caracterul global al acesteia, în sensul că matricea de convarianță (deci și valorile și vectorii proprii) este dedusă luând în considerare toate imaginile disponibile, care pot să conțină o foarte mare variabilitate din punct de vedere al nivelului de iluminare, orientării, fundalului.

Acest dezavantaj poate fi compensat pațial utilizând arhitecturi modulare, în care tehnica PCA se aplică pe subseturi de imagini care au caracteristici comune (de exemplu, se calculează seturi de vectori proprii distincți pentru clasa imaginilor reprezentând vederi frontale, respectiv vederi înclinate la ±30°, ±40°). De asemenea, se pot utiliza arhitecturi în care fiecare modul este “specializat” să recunoască numai imaginile reprezentând o aceeași persoană.

– în cazul particular al analizei imaginilor reprezentând fețe, metoda PCA s-a dovedit extrem de sensibilă în raport cu normalizarea poziției acestora: translații pe orizontală/verticală cu numai câțiva pixeli, mici rotații sau variații de scală pot altera semnificativ „semnăturile” extrase și, în consecință, pot degrada performanțele de recunoaștere/autentificare. Ca urmare, este necesară o etapă (manuală sau automată) de normalizare a aspectului imaginilor, care să preceadă aplicarea propriu-zisă a PCA. Alternativ, au fost propuse variante ale metodei standard, care încearcă să compenseze acest dezavantaj prin filtrarea adecvată a imaginilor originale. În particular, uneori se preferă ignorarea proiecției de-a lungul primului vector propriu semnificativ, deoarece de regulă acesta este sensibil la nivelul global de iluminare al imaginilor.

2.2. Rețele neuronale artificiale

Rețelele neuronale artificiale (RNA), denumite uneori procesoare paralel distribuite, eurocomputere sau modele conexioniste, reprezintă o încercare de a simula, cel puțin parțial, structura și funcțiile creierului specifice organismelor vii.

2.2.1. Definiție. Proprietăți

Ca o definiție generală, se poate spune că RNA reprezintă un sistem de procesare al semnalelor, compus dintr-un număr mare de procesoare elementare interconectate, denumite neuroni artificiali sau noduri, și care cooperează pentru rezolvarea unor sarcini specifice. Modalitatea de adaptare la condițiile specific mediului constă în modificarea ponderilor asociate conexiunilor dintre neuroni și eventual a structurii RNA.

Astfel, de modele conexioniste oferă anumite avantaje, caracteristice sistemelor neuronale reale (biologice) și care nu sunt întâlnite în cazul sistemelor de calcul tradiționale, secvențiale [6]:

proprietate deosebit de importantă a RNA este aceea de a învăța și de a se adapta;

Posibilitatea de a opera cu date imprecise;

Capacitatea de generalizare, în sensul în care RNA va opera corect și cu date de intrare care nu au fost prezentate în timpul procesului de antrenament;

Datorită gradului ridicat de paralelism , funcționarea defectuoasă sau chiar pierderea unui număr de neuroni nu afectează semnificativ performanța sistemului global. RNA reprezintă deci sisteme tolerante la erori;

Capacitatea de a aproxima orice funcție continuă neliniară cu gradul de acuratețe dorit. Astfel, RNA pot fi folosite cu succes în modelarea sistemelor neliniare;

Datorită numărului mare de intrări și ieșiri, RNA modelează cu ușurință sisteme multivariabilă;

Implementările hardware ale RNA, de exemplu prin intermediul circuitelor integrate pe scară largă (VLSI), fac posibilă utilizarea RNA pentru cazul aplicațiilor în timp real.

2.2.2. Neuronul artificial

Neuronul artificial denumit uneori procesor elementar sau, mai simplu nod, încearcă să imite structura și funcționarea neuronului biologic. Există numeroase modele prezentate în literatură, dar cel mai răspândit are la bază modelul elaborate de McCulloch-Pitts în 1943. Astfel, se poate considera că neuronul artificial este format dintr-un număr de intrări, fiecare dintre acestea fiind caracterizată de propria pondere sinaptică. De exemplu, semnalul xj prezent la intrarea sinapsei “j” este conectat la neuronul “k” prin multiplicare cu ponderea wkj (fig. 2.2.1).

Figura 2.2.1 Modelul neuronului artificial [6]

O altă componentă a modelului neuronului artificial prezentat în fig. 2.2.1 o reprezintă sumatorul destinat însumării intrărilor ponderate.

Rezultatul obținut în urma însumării:

(2.2.1)

este denumit intrare netă.

Pentru limitarea amplitudinii semnalului de ieșire al neuronului, acesta este prevăzut cu o funcție de activare ϕ (⋅) :

(2.2.2)

în care θk reprezintă valoarea pragului de activare (treshold) al neuronului. Uneori intrarea netă este majorată prin termenul bk denumit factor al deplasării scării (bias); deplasarea scării reprezintă deci negativul pragului de activare.

Valoarea:

(2.2.3)

poartă denumirea de potențial de activare.

În ceea ce privește tipul funcției de activare, aceasta este de regulă o funcție neliniară; în cele ce urmează se va face o prezentare a celor mai răspândite tipuri de funcții de activare (fig. 2.2.2):

Funcția prag:

(2.2.4)

Funcția prag simetrică sau funcția signum:

(2.2.5)

Funcția sigmoid:

(2.2.6)

Funcția tangentă hiperbolică:

(2.2.7)

Funcțiile sigmoid și tangentă hiperbolică reprezintă unele dintre funcțiile de activare cel mai des folosite la implementarea RNA, unul dintre motive reprezentându-l calculul simplu al derivatelor acestora.

Funcția liniară:

(2.2.8)

Funcția liniară cu saturație:

(2.2.9)

Funcția liniară cu saturație, simetrică:

(2.2.10)

Funcția gaussiană:

(2.2.11)

Figura 2.2.2. Funcții de activare tipice

Analizând comparativ modelele neuronului real (biologic) și neuronului artificial se pot face următoarele observații:

-Din punct de vedere al implementării este practic imposibil și chiar ineficient ca modelul artificial al neuronului să copieze exact comportamentul și structura celui biologic.

-RNA sunt proiectate pentru rezolvarea unor probleme specifice și deci arhitectura și trăsăturile RNA depind de problema pe care trebuie să o rezolve.

-Un neuron real produce la ieșire o secvență de impulsuri și nu o anumită valoare cum este cazul celui artificial. Reprezentarea ratei de activare printr-un singur număr (yk) ignoră informația care ar putea fi conținută de exemplu în faza impulsurilor.

-Unele celule nervoase biologice efectuează o însumare neliniară a intrărilor. Pot exista chiar operații logice (ȘI, SAU, NU) efectuate la nivelul dendritelor.

-Ieșirile neuronilor nu se modifică în mod sincron și nu toți au același tip de întârziere.

– Cantitatea de substanță transmițătoare (mediator chimic) eliberată la nivelul sinapsei poate să varieze într-un mod imprevizibil. Fenomenul este aproximat grosier prin intermediul funcției de activare [6].

2.2.3. Arhitecturi ale RNA

Se pot distinge două mari categorii în modul de structurare al unei RNA:

1. RNA feedforward (cu propagare înainte) .Sunt caracterizate de prezența unui strat de neuroni de intrare, un număr destraturi ascunse (posibil și fără) și un strat de neuroni de ieșire.

În fig. 2.2.3. este prezentată arhitectura unei RNA feedforward cu un singurstrat ascuns. Definitoriu pentru acest tip de RNA este faptul că un neuron primește semnale doar de la neuroni aflați în stratul/straturi precedent/precedente. Se spune despre o RNA că este total conectată dacă fiecare nod din fiecare strat este conectat la fiecare neuron din stratul precedent (fig. 2.2.4.).

Dacă anumite conexiuni sinaptice lipsesc se spune că RNA este partial conectată (fig. 2.4.2). RNA total conectate au un caracter general, în sensul în care pot fi folosite într-o gamă largă de probleme, dar rezultatele nu sunt întotdeauna cele mai bune [11]. RNA parțial conectate introduc anumite restrângeri, care reprezintă tocmai cunoștințe apriorice despre problema de rezolvat și care reduc gradul de generalitate al unei RNA. Prin restrângerea câmpului de recepție al neuronilor se efectuează o extragere a trăsăturilor locale, iar în straturile ce urmează acestea sunt combinate pentru a se forma trăsături de ordin superior. Astfel, RNA parțial conectate pot da rezultate mai bune decât RNA total conectate în rezolvarea anumitor problem specifice, cu condiția exploatării cunoștințelor apriorice despre problema data [6].

Figura 2.2.3. RNA feedforward total conectată [6]

Figura 2.2.4. RNA feedforward parțial conectată [6]

2. RNA recurente (feedback, cu propagare înapoi).

RNA recurente se individualizează prin existența unui semnal de reacție, din partea neuronilor de ordin superior, pentru cei de ordin inferior sau chiar pentru propriile lor intrări (fig. 2.4.4.).

Figura 2.2.4. RNA recurentă [6]

2.2.4. Tipuri și algoritmi de instruire

RNA achiziționează cunoștințele prin instruire (învățare). Învățarea presupune adaptarea parametrilor liberi ai RNA (ponderi, praguri, rată de învățare, uneori chiar forma funcției de activare sau structura rețelei) ca urmare a stimulilor mediului în care se găsește rețeaua.

Vectorii de instruire sunt prezentați RNA în mod secvențial, iar ponderile sinaptice, care memorează practic cunoștințele rețelei, sunt adaptate pentru a extrage informația pe care acești vectori o conțin [6].

Tipul de învățăre este determinat de maniera în care sunt ajustați parametrii liberi ai RNA. Deși în literatura RNA există o mare diversitate de opinii în ceea ce privește modul de clasificare al algoritmilor și tipurilor de învățăre, fig. 2.2.5. încearcă să sintetizeze principalele direcții.

Figura 2.2.5. Tipuri și algoritmi de instruire [6]

Învățarea de tip supervizat

Este caracterizată de prezența unui supervizor care cunoaște cu exactitate modul de asociere al intrărilor RNA cu ieșirile acesteia, conform fig. 2.2.6.

Figura 2.2.6. Arhitectura unui sistem cu învățare supervizată [6]

Parametrii RNA sunt modificați sub influența combinată a vectorilor de antrenament și a semnalului de eroare (diferența dintre răspunsul dorit și cel actual). Scopul final al algoritmului de antrenament este ca RNA să emuleze, optim în sens statistic, supervizorul.

Învățarea de tip nesupervizat (cu autoorganizare)

Este caracterizată de absența unui semnal sau supervizor care să aprecieze corectitudinea asociațiilor intrare-ieșire (fig. 2.2.7.). RNA va descoperii singură legitățile conținute în datele de intrare printr-o reprezentare internă adecvată a trăsăturilor vectorului de intrare [6].

Figura 2.2.7. Sistem cu învățare de tip nesupervizat [6]

Învățarea prin întărire

Urmărește maximizarea unei mărimi scalare (indice de performanță sau semnal de întărire) în urma unei acțiuni efectuate de către sistemul supus învățării. Dacă modificările aduse conduc spre o stare mai bună decât cea precedentă, tendința sistemului de a produce acea acțiune particulară este întărită.

Algoritmi de învățare bazați pe corecția erorii

Fie x(n) vectorul de intrare aplicat unei RNA. Dacă se notează ieșirea neuronului “k” prin yk(n), semnalul de eroare poate fi definit ca fiind diferența dintre ieșirea dorită pentru neuronul “k” și ceea ce furnizează în etapa actuală de către același neuron:

ek (n) = dk (n) – yk (n) (2.2.12)

Scopul final al algoritmilor bazați pe corecția erorii este de a minimiza așa-numita funcție de cost. Unul dintre criteriile frecvent utilizate în alegerea funcției de cost este cel al erorii pătratice medii – care urmărește minimizarea valorii medii pătratice pentru suma erorilor pătratice aferente stratului de ieșire al RNA [6]:

(2.2.13)

în care E[.] semnifică media în sens statistic.

Una dintre metodele de minimizarea a funcției de cost J în raport cu parametrii RNA este metoda gradientului descendent. De cele mai multe ori proprietățile statistice ale procesului nu sunt cunoscute. În acest caz se oferă o soluție aproximativă pentru problema de optimizare, prin utilizarea drept funcție de cost a valorii instantanee a sumei erorilor pătratice:

(2.2.14)

O metodă în acest sens o oferă Widrow și Hoff (regula delta):

(2.2.15)

în care η reprezintă rata de învățăre a RNA.

Algoritmi de învățare de tip Boltzmann

Sunt inspirați din teoria informației și din termodinamică, neuronii constituind

o structură recurentă caracterizată de așa-numita funcție energie:

(2.2.16)

unde si reprezintă starea neuronului “i”, adică +1 (neuron activ) sau -1 (neuron inactiv).

Mașina Boltzmann operează prin alegerea aleatoare a unui neuron și schimbarea stării acestuia. Astfel, schimbarea ponderilor se va face ținând cont de corelațiile dintre starea neuronului “i” și cea a neuronului “j”.

Algoritmi de învățare de tip hebbian

Conform postulatului lui Hebb, modificarea ponderii sinaptice wkj este dependentă de activitatea pre- și postsinaptică:

(2.2.17)

O formă particulară a ecuației de mai sus este:

(2.2.18)

cu η o constantă pozitivă reprezentând rata de învățare. Dezavantajul acestei reguli îl reprezintă faptul că ea conduce la o creștere exponențială a wkj. Una din metodele propuse ulterior presupune introducerea unui termen de “uitare” (forgetting factor):

(2.2.19)

Algoritmul de învățare de tip competitiv

Este caracterizat de competiția între neuronii de ieșire ai RNA, câștigatorul acesteia urmând să fie activat. Spre deosebire de RNA care se bazează pe algoritmi de învățare de tip hebbian și la care există posibilitatea ca mai mulți neuroni să fie active simultan, la RNA bazate pe algoritmi de învățare de tip competitiv doar un singur neuron este activ la un moment dat.

Practic, fiecare neuron al unei astfel de RNA va deveni specializat, în urma procesului de învățare, în recunoașterea unei anumite trăsături prezentă în datele de intrare. Acest lucru este posibil având în vedere modalitatea de adaptare a ponderilor:

(2.2.20)

Prin aceasta, ponderea wj a neuronului “j”, câștigator al competiției, se apropie și mai mult de tiparul x prezentat la intrare.

2.2.5. Aplicații ale rețelelor neuronale artificiale

De regulă RNA sunt folosite în acele aplicații în care:

• modelul matematic al procesului este necunoscut, nu se poate determina sau este prea complex;

• se operează cu date incomplete, contaminate cu zgomot;

• este necesară optimizarea simultană a mai multor constrângeri impuse unui proces.

Nu se utilizează în aplicațiile care dispun de un proces determinist, cunoscut, cu reguli clare.

Problema XOR

Cu RNA–MLP problema este separabilă, așa cum se constată din analiza celor două arhitecturi prezentate mai jos (fig. 2.2.8).

Figura 2.2.8. Rezolvarea problemei XOR cu ajutorul unei RNA-MLP.

Problema parității

Reprezintă o generalizare a problemei XOR pentru “N” intrări. Este necesară o singură unitate pentru stratul de ieșire care să fie activă dacă există un număr impar de intrări pe “1” și inactivă altfel. Arhitectura care rezolvă problema parității pentru cazul N = 4 e prezentată în continuare (fig. 2.2.9.).

Figura 2.2.9. Rezolvarea problemei parității cu ajutorul unei RNA-MLP.

Problema codării

Presupune găsirea unui număr de neuroni ascunși care să codifice în mod eficient un număr mare de tipare de dimensiune largă. Se consideră un număr de intrări “N” egal cu numărul de ieșiri și un număr “M” de neuroni ascunși, M<N (fig. 2.2.10.).

Se definește astfel o problemă de autoasociere, în care tiparul aplicat la intrare și cel de la ieșire sunt identice: RNA va efectua practic o operație de codare la nivelul stratului de intrare și cel ascuns și o operație de decodare la nivelul straturilor ascuns – ieșire.

RNA de tip autoasociativ sunt folosite în compresia imaginilor sau pentru extragerea trăsăturilor prin metoda analizei componentelor principale (PCA, “Principal Component Analysis”).

Figura 2.2.10. RNA folosită în problema codării/compresiei datelor.

3. ZGOMOTUL ÎN IMAGINI

Zgomotul este un semnal aleator, care afectează informația utilă conținută într-o imagine. El poate apare de-a lungul unui lanț de transmisiune, sau prin codarea și decodarea imaginii, și reprezintă un element perturbator nedorit. De obicei se încearcă eliminarea lui prin diverse metode de filtrare [14].

Zgomotul se poate suprapune informației utile în două moduri:

aditiv (fig. 3.1.) . În acest caz, zgomotul se numește zgomot aditiv și matematic se poate scrie:

g(x; y) = f(x; y) + n(x; y) (3.1)

unde f(x; y) este imaginea inițială, neafectată de zgomot, n(x; y) este zgomotul, iar g(x; y) este imaginea afectată de zgomot.

multiplicativ. În acest caz zgomotul se numește zgomot multiplicativ, iar fenomenul de suprapunere al acestuia peste informația utilă se scrie matematic astfel:

g(x; y) = f(x; y) _ n(x; y) (3.2)

unde f(x; y), n(x; y) și g(x; y) au aceleași semnificații ca mai sus.

Dacă logaritmăm relația, zgmotul multiplicativ poate fi tratat la fel ca zgomotul aditiv:

log(g(x; y)) = log(f(x; y) * n(x; y)) = log(f(x; y)) + log(n(x; y)) (3.3)

Figura 3.1. Modelul aditiv de degradare.

Zgomotul cu distribuție gaussiană

Zgomotul gaussian este caracterizat de o funcție de densitate de probabilitate de forma [1N]:

(3.4)

Figura 3.2. Funcția densitate de probabilitate pentru o distribuție gaussiană.

Valoarea medie a unei variabile aleatoare , cu o distribuție dată de funcția ca în relația (3.4), este , iar varianța ei este . O distribuție gaussiană se mai numește și normală. O distribuție normală de medie și varianța se notează cu N(;). O exemplificare a zgomotului Gaussian se poate observa in figura 3.3.

Figura 3.3. Zgomotul Gaussian: (a) imaginea originală; (b) imaginea afectată de zgomot gaussian și varianța

Zgomotul de tip “sare și piper"

După cum îi spune numele, acest tip de zgomot va afecta valorile pixelilor în două moduri: “sare" – adică noua valoare a pixelului va fi 255 (pixelul va fi alb), sau “piper" – adică noua valoare a pixelului va fi 0 (pixelul va fi negru). Zgomotul de tip “sare și piper" (figura 3.4) este perfect decorelat, deoarece între valorile 0 și 255, și între coordonatele pixelilor afectați de zgomot nu există corelație.

O exemplificare a zgomotului “sare și piper” se poate observa in figura 3.4.

Figura 3.4. Zgomotul “sare și piper": (a) imaginea originală; (b) imaginea cu 5% pixeli afectați de zgomot.

Subeșantionarea

Sub-eșantionarea (numită și decimare) se referă la scăderea numărului de pixeli dintr-o imagine. Conceptul de baza al decimării este reducerea dimensiunii semnalului de intrare video (semnal bi-dimensional, pe orizontală și pe verticală) și a numărului de cadre, înainte de începerea codării. La destinatar, imaginile decodate sunt interpolate pentru afișare (fig. 3.5) [18], [19], [20].

Figura 3.5. Subeșantionarea: (a) imaginea originală; (b) imaginea cu 30% pixeli afectați de zgomot (pas = 3).

Iluminare

O imagine căreia i s-a aplicat un proces de iluminare este exemplificată in figura 3.6. În acest caz intensitatea pixelilor a fost mărită cu un pas bine stabilit.

Figura 3.6. Iluminarea: (a) imaginea originală; (b) imaginea cu pixeli afectați de iluminare (pas = 1.2).

Întunecare

O imagine căreia i s-a aplicat un proces de întunecare este exemplificată in figura 3.7. În acest caz intensitatea pixelilor a fost scăzuttă cu un pas bine stabilit.

Figura 3.7: Subeșantionarea: (a) imaginea originală; (b) imaginea cu pixeli afectați de întunecare (pas = 5).

4. DESCRIEREA EXPERIMENTULUI

4.1. Arhitectura și implementarea unui sistem de detecție și recunoaștere automată a feței

Un sistem automat de detecție și recunoaștere facială presupune parcurgerea următoarelor etape (fig. 4.1.):

Figura 4.1. Arhitectura unui sistem de detecție și recunoaștere automată a feței.

a) Achiziția imaginii – folosește la prelevarea imaginilor în care se presupune că există fețe umane;

b) Detecția feței – presupune localizarea spațială a unei imagini faciale conținută în scenă. Acuratețea ei influențează calitatea procesului de clasificare (recunoaștere). Această operație a fost implementată cu algoritmul Viola-Jones.

c) Recunoașterea facială – prin această etapă se extrage informația relevantă, ce caracterizează o anumită persoană. Totodată această etapă asigură și o reducere a dimensionalității datelor de intrare. Există numeroase metode de extragere a trăsăturilor, atât convenționale cât și neuronale. În această etapă au fost implementate algoritmul PCA și o rețea neuronală.

4.2. Detecția fețelor utilizând algoritmul Viola-Jones

Primul pas în implementarea algoritmului Viola-Jones a fost crearea unei baze de date cu chipuri umane. Baza de date conținea inițial 445 imagini distribuite unui număr de 25 de utilizatori. Din motive de performanță am mărit ulterior numărul de utilizatori la 51, însumând un număr de 1000 imagini. Baza de date a fost creată cu ajutorul resurselor [15], [16], [17]

Mai jos, în figura 4.2. sunt afișate cele 21 de portrete aferente primului utilizator :

Figura 4.2. Imaginile aferente primului utilizator

Se poate observa că imaginile sunt variate (luminozitate ridicată/scăzută, umbre pe față, ochi închiși). În urma aplicării algoritmului, am obținut pentru primul utilizator 18 imagini în care am delimitat fața (figura 4.3):

Figura 4.3. Fețele detectate pentru primul utilizator

Dintr-un număr total de 1000 imagini, s-au obținut 736 de fețe, distribuite între cei 51 de utilizatori.

În figura 4.4. este prezentată o interfață grafică utilizată pentru detecția fețelor. Fiecare față detectată este încadrată într-un cadran roșu. În partea dreaptă sunt extrase primele 12 fețe detectate.

Figura 4.4. Interfața grafică creată pentru testarea detecției feței

4.3. Recunoașterea fețelor

În partea de recunoaștere, am implementat algoritmul PCA și o rețea neuronală.

Ca parametri de intrare am folosit imaginile obținute în urma aplicării algoritmului Viola-Jones.

Primele teste le-am efectuat pe un număr de 25 de utilizatori. Rezultatele sunt exemplificate în tabelul 4.1.

Tabel 4.1 – Precizie recunoaștere – 25 utilizatori

Datorită faptului că am obținut un procent de 100% al preciziei de recunoaștere, m-am decis să măresc numărul de utilizatori, obținând următoarele rezultate (tabelul 4.2.):

Tabel 4.2 – Precizie recunoaștere – 51 utilizatori

Se poate observa că precizia de detecție este mai mare în cazul rețelelor neuronale decât în cazul algoritmului PCA. Mai mult decât atât, precizia este aproape dublă în cazul rețelelor neuronale.

În cazul rețelelor neuronale, se poate observa că, pe măsură ce se face antrenarea cu mai multe poze crește preciyia de recunoaștere. De asemenea, precizia crește pe măsură ce crește numărul de iterații.

În continuare, am alterat imaginile prin diferite metode și am obtinut următoarele rezultate pentru cazul ANTRENARE 80 % – TESTARE 20 % – 250 iterații (tabelele 4.3.- 4.7.):

Tabel 4.3 – Precizie recunoaștere – Zgomot Gaussian

Se observă că precizia crește pe măsură ce scade varianța, dar rămâne apropiată de valoarea obținută în urma testării fără zgomot.

Tabel 4.4 – Precizie recunoaștere – Zgomot salt&pepper

Se observă că precizia crește pe măsură ce scade distribuția, rămâne apropiată de valoarea obținută în urma testării fără zgomot, dar este mai mică decât în cazul zgomotului gaussian.

Tabel 4.5 – Precizie recunoaștere – Downsampling

Se observă că precizia este aproximativ constantă, mai mică decât valoarea obținută în urma testării fără zgomot și decât în cazul zgomotului gaussian.

Tabel 4.6 – Precizie recunoaștere – Iluminare

Se observă că precizia crește pe măsură ce scade pasul. În acest caz are loc cea mai mare variație a preciziei.

Tabel 4.7. – Precizie recunoaștere – Întunecare

Se observă că precizia crește pe măsură ce scade pasul.Precizia este asemănătoare cu cazul anterior.

Aceste teste au fost efectuate doar pentru recunoașterea cu rețele neuronale, deoarece în cazul algoritmului PCA precizia era deja destul de redusă, iar prin aplicarea zgomotului s-ar fi obținut procente ale preciziei și mai reduse, care ar fi fost irelevante.

În figura 4.5. este prezentată interfața grafică utilizată pentru recunoașterea fețelor.

Figura 4.5. Interfața grafică cu care se poate testa recunoașterea feței

Testarea Cross Variance

Am efectuat si testul cross variance. Pentru fiecare utilizator am împărțit imaginile detectate în urma algoritmului Viola-Jones în 5 intervale egale, permutând imaginile utilizate pentru antrenare și cele pentru testare. Analizând tabelul 4.8. se poate observa că procentele obținute sunt asemănătoare cu cele inițiale, atât în cazul rețelelor neuronale, cât și în cazul algoritmului PCA.

Tabel 4.8. – Procentul detecției pentru Cross Variance

CONCLUZII

Prezentarea din cuprinsul paragrafelor anterioare s-a concentrat asupra aplicațiilor orientate pe procesarea imaginilor reprezentând fețe umane, ilustrate pe baza unor exemple care să ofere o imagine intuitivă asupra utilizării diverșilor algoritmi enumerați.

Fața reprezintă o tehnică neinvazivă, utilizează drept senzori camere de fotografiat sau filmat disponibile pe scară largă, există baze de date de dimensiune mare, iar rezultatele pot fi verificate cu ușurință. Pe de altă parte, fețele sunt puternic afectate de nivelul de iluminare, expresie, transformări geometrice, îmbătrânire, iar unele aplicații video presupun viteză de operare sporită. În practică, pe lângă distincția dintre problemele de recunoaștere și cele de detecție, se disting câteva direcții particulare de folosire a acestor informații precum analiza expresiei feței, determinarea stării emoționale, detecția și urmărirea ochilor sau a buzelor.

Înainte ca un sistem biometric automat să devină pe deplin operațional, acesta este supus unui ansamblu de teste specifice, fiecare având un scop precis, fixat în accord cu o modalitate particulară de analiză și utilizând o bază de date adecvată. Putem identifica următoarele tipuri de proceduri de evaluare [4]:

evaluarea tehnologiei: urmărește validarea metodei analizate folosind baze de

date standardizate de dimensiune mică, identificând aspectele critice care necesită o analiză teoretică suplimentară și furnizând nivele de performanță cu rol de referință pentru celelalte tipuri de proceduri de testare.

evaluarea pe bază de scenariu: durează mai mult ca în cazul precedent și își propune să măsoare performanțele pentru o aplicație specifică, folosind baze de date de dimensiuni mari, achiziționate de la un număr de utilizatori nefamiliarizați în prealabil cu sistemul. Rezultatele pot evidenția zone care necesită analiză suplimentară sau posibilități de integrare și oferă valori mai exacte ale nivelelor reale de performanță.

evaluarea operațională: are în vedere cuantificarea impactului pe care introducerea sistemului biometric îl are asupra ansamblului în care acesta este inclus. În acest context, este necesară evaluarea stării existente înainte de introducerea sistemului, respectiv celei de după familiarizarea utilizatorilor cu modalitatea concretă de operare a acestuia. Astfel, de teste pot avea durate mari, de ordinul câtorva luni, iar aspectele vizate se referă atât la tehnologia propriu-zisă, cât și la efectele psihologice și economice pe care aceasta le produce.

Nu există sisteme biometrice ideale: implementarea oricărei metode de recunoaștere/verificare bazate pe utilizarea unor astfel de informații este inevitabil limitată inferior de valori a căror estimare precisă reprezintă subiectul unor proceduri riguroase de evaluare standardizată.

Potențialul unei tehnologii biometrice trebuie judecat nu numai din punct de vedere tehnic, dar și din perspectiva unor potențiale utilizări abuzive. Există o serie de decizii importante care trebuie luate înainte de introducerea în exploatare a unui astfel de sistem, printre care evidențierea nivelului satisfăcător de performanță, identificarea informațiilor private care sunt strict necesare, estimarea raportului dintre costuri și sporul de securitate pe care introducerea unei astfel de tehnologii îl poate aduce.

ANEXA 1

Codul MATLAB pentru algoritmul Viola Jones:

funcția ObjectDetection:

function Objects = ObjectDetection(Picture,FilenameHaarcasade,Options)

% Functia ObjectDetection reprezinta impementarea algoritmului Viola-Jones.

% Este folosita transformata Haar pentru detectia rapida a fetelor.

% Se folosesc clasificatorii antrenati in fisierele XML Open CV

%

% Objects = ObjectDetection(I,FilenameHaarcasade,Options)

%

% variabile de intrare:

% I : imagine sau calea fisierului

%

% FilenameHaarcasade : Numele unui document Matlab cu o cascadare a

% clasificatorilor Haar creata cu ajutorul unui fisier XML OpenCV,

% folosind functia ConvertHaarcasadeXMLOpenCV.

%

% Options : O structura cu urmatoarele optiuni

% Options.ScaleUpdate : Scala actualizata, default 1/1.2

% Options.Resize : Daca variabila de tip boolean are valoarea true (default),

% functia va redimensiona imaginea la marimea maxima intr-un timp scurt

% Options.Verbose : Afiseaza informatii de proces

%

% variabile de iesire,

% Objects : O suprafata de dimensiune n x 4 [x y width height] a obiectului

% detectat

%

% Optiuni default

defaultoptions = struct('ScaleUpdate',1/1.2,'Resize',true,'Verbose',true);

% Adaugarea caii subfunctiei la calea Matlab pentru cautare

functionname = 'ObjectDetection.m';

functiondir = which(functionname);

functiondir = functiondir(1:end-length(functionname));

addpath([functiondir '/SubFunctions'])

% Verificarea parametrilor de intrare

if(ischar(Picture))

if(~exist(Picture,'file'))

error('face_detect:inputs','Image not Found');

end

end

if(~exist(FilenameHaarcasade,'file'))

error('face_detect:inputs','Haarcasade not Found');

end

% Procesarea optiunilor de intrare

if(~exist('Options','var')), Options=defaultoptions;

else

tags = fieldnames(defaultoptions);

for i = 1:length(tags),

if(~isfield(Options,tags{i})), Options.(tags{i})=defaultoptions.(tags{i}); end

end

if(length(tags) ~= length(fieldnames(Options))),

warning('image_registration:unknownoption','unknown options found');

end

end

% Citirea imaginii din fisier

if(ischar(Picture))

Picture = imread(Picture);

end

% Obtinerea cascadei de clasificatori Haar pentru detectie

HaarCasade = GetHaarCasade(FilenameHaarcasade);

% Obtinerea imaginii integrale

IntergralImages = GetIntergralImages(Picture,Options);

Objects = HaarCasadeObjectDetection(IntergralImages,HaarCasade,Options);

% Afisarea rezultatelor finale

if(nargout == 0)

ShowDetectionResult(Picture,Objects);

end

funcția showWindows:

function showWindows(image)

% afisarea unui patrat rosu ce marcheaza suprafata detectata

root=[pwd '\poze\'];

dest=[pwd '\faces\'];

files=dir(root)

for i=3:length(files)

files2=dir([root files(i).name])

mkdir([dest files(i).name])

for j=3:length(files2)

img = imread([root files(i).name '\' files2(j).name]);

coordinates = ObjectDetection(img,'haarcascade_frontalface_alt.mat')

xx=[];

yy=[];

ww=[];

hh=[];

img2 = img;

[m,n]=size(coordinates)

for k = 1:m

img = img2;

y = coordinates(k,1)

x = coordinates(k,2)

w = coordinates(k,3)

h = coordinates(k,4)

x = floor(x);

y = floor(y);

w = floor(w);

h = floor(h);

xx=[xx x]

yy=[yy y]

ww=[ww w]

hh=[hh h]

img2 = img;

% img(x+1:x+w,y+1:y+10) = 255;

% img(x+1:x+w,y+h:y+h+10) = 255;

% img(x+1:x+10,y+1:y+h) = 255;

% img(x+h:x+w+10,y+1:y+h+10) = 255;

% img3=img(x+1:x+w,y+1:y+h,:);

% str=sprintf('%d%s',k,files2(j).name);

% imwrite(img3,[dest files(i).name '\' str ])

% figure()

% imshow(img)

% img(y:y+10,x+10:x+w)=255;

% img(y:y+10,x+10:x+w)=255;

end

if m>0

x=floor(mean(xx))

y=floor(mean(yy))

w=floor(mean(ww))

h=floor(mean(hh))

img3=img(x+1:x+w,y+1:y+h,:);

str=sprintf('%d%s',k,files2(j).name);

imwrite(img3,[dest files(i).name '\' str ])

end

end

end

% end

funcția ConvertHaarcasadeXMLOpenCV

function ConvertHaarcasadeXMLOpenCV(filename)

% Functia ConvertHaarcasadeXMLOpenCV converteste un fisier .xml openCV

% intr-un fisier de date matlab si un script cu aceeassi structura.

%

% Exemplu,

% filename='haarcascade_eye';

% ConvertHaarcasadeXMLOpenCV(filename);

%

% Exemplu,

% f = dir('*.xml');

% for i = 1:length(f),

% filename = f(i).name;

% ConvertHaarcasadeXMLOpenCV(filename(1:end-4));

% end

%

j = find(filename == '.'); if(~isempty(j)), filename = filename(1:j-1); end

fid = fopen([filename '.xml'], 'r');

c = fread(fid, inf, 'char=>char')';

fclose(fid);

c(c==13) = [];

c(c==10) = [];

fl = regexp(c, '<', 'split');

fid = fopen([filename '.m'], 'w');

h = 0; nw = 0;

infoname = cell(1,10);

infocount = zeros(1,10);

for i = 2:length(fl)

str = fl{i};

if(length(str) > 1), st = str(1); else st = ''; end

switch(st)

case {'!','','?'}

continue

case '/'

t = find(str == '>',1,'first');

name = str(2:t-1);

infocount(h) = 0;

h = h – 1;

continue

otherwise

t1 = find(str == '>',1,'first');

t2 = find(str(1:t1-1) == ' ');

if(~isempty(t2))

t = t2;

else

t = t1;

end

name = str(1:t-1);

data = str(t+1:end);

h = h + 1;

if(name == '_')

infocount(h-1) = infocount(h-1)+1;

name = 'value';

end

infoname{h} = name;

while(~isempty(data)&&(data(1)==' ')); data = data(2:end); end

while(~isempty(data)&&(data(end)==' ')); data = data(1:end-1); end

end

if(~isempty(data))

in = '';

for j = 1:h

if(infocount(j) > 0)

count = ['(' num2str(infocount(j)) ')'];

else

count = '';

end

if(j == 1)

in = [infoname{j} count];

else

in = [in '.' infoname{j} count];

end

end

in = strrep(in,'.value.','.');

num = str2num(data);

if(~isempty(num))

if(length(num) == 1)

str = [in ' = ' data ';'];

else

str = [in ' = [' data '];'];

end

else

str = [in ' = ''' data ''';'];

end

nw = nw + 1;

if(nw == 1), str = ['%' str]; end

fprintf(fid,'%s\r\n',str);

if(nw > 1)

eval(str)

end

end

end

fclose(fid);

save([filename '.mat'],'opencv_storage');

funcția ShowDetectionResult

function ShowDetectionResult(Picture,Objects)

% Vizualizarea fotografiei

figure,imshow(Picture), hold on;

% Afisarea obiectelor detectate

if(~isempty(Objects));

for n = 1:size(Objects,1)

x1 = Objects(n,1); y1 = Objects(n,2);

x2 = x1 + Objects(n,3); y2 = y1 + Objects(n,4);

plot([x1 x1 x2 x2 x1],[y1 y2 y2 y1 y1]);

end

end

funcția HaarCasadeObjectDetection

function Objects= HaarCasadeObjectDetection(IntegralImages,HaarCasade,Options)

% Calcularea grosiera a imaginii integrale

ScaleWidth = IntegralImages.width/HaarCasade.size(1);

ScaleHeight = IntegralImages.height/HaarCasade.size(2);

if(ScaleHeight < ScaleWidth ),

StartScale = ScaleHeight;

else

StartScale = ScaleWidth;

end

% Matrice pentru a stoca dimensiunile [x y width height] obiectelor detectate

Objects = zeros(100,4); n=0;

% Calcularea numarului maxim de iteratii pentru cautare

itt = ceil(log(1/StartScale)/log(Options.ScaleUpdate));

% Face detectarea obiectelor, looping prin toate scalele de imagine

for i=1:itt

% Current scale

Scale = StartScale * Options.ScaleUpdate^(i-1);

% Afi?are scala curentã ?i numãrul de obiecte detectate

if(Options.Verbose)

disp(['Scale : ' num2str(Scale) ' objects detected : ' num2str(n) ])

end

% Scalarea dimensiunii ferestrei, cu scãderea scalei de cãutare-

% ( loc de scalare intensivã CPU a imaginii ?i calculul de imagini integrale noi)

w = floor(HaarCasade.size(1)*Scale);

h = floor(HaarCasade.size(2)*Scale);

% Spatiere intre coordonatele de cãutare ale imaginii.

step = floor(max( Scale, 2 ));

% Crearea unor vectori pentru stocarea coordonatelor obtinute (pentru fiecare scara)

[x,y] = ndgrid(0:step:(IntegralImages.width-w-1),0:step:(IntegralImages.height-h-1)); x = x(:); y = y(:);

% Daca nu se obtin coordonatele datorita pasului mare, se continua cu urmatorul pas

if(isempty(x)), continue; end

% Gasirea obiectelor in imagine pentru pasul curent

[x,y] = OneScaleObjectDetection( x, y, Scale, IntegralImages, w, h, HaarCasade);

% Daca exista coordonatele, atunci contin un obiect

for k = 1:length(x);

n = n + 1; Objects(n,:) = [x(k) y(k) w h];

end

end

% Se decupeaza matricea ini?ialã cu obiecte detectate

Objects = Objects(1:n,:);

% Se reseteaza coordonatele, pentru a compensa rescalarea imaginii

% inainte de a calcula imaginea integrala

Objects = Objects * IntegralImages.Ratio;

funcția GetIntergralImages

function IntegralImages = GetIntergralImages(Picture,Options)

% Calcularea imaginii integrale a unei imagini

%

% Convertirea imaginii in double

% scalarea pe niveluri de gri nu influen?eazã rezultatul,

% deci se poate utiliza im2double

%

Picture = im2double(Picture);

% Redimensionarea imaginii pentru a reduce timpul de prelucrare,

if(Options.Resize)

if (size(Picture,2) > size(Picture,1)),

Ratio = size(Picture,2) / 384;

else

Ratio = size(Picture,1) / 384;

end

Picture = imresize(Picture, [size(Picture,1) size(Picture,2) ]/ Ratio);

else

Ratio = 1;

end

% Convertirea imaginii în nuan?e de gri (aceastã linie este la fel ca rgb2gray, a se vedea de ajutor)

if(size(Picture,3) > 1),

Picture = 0.2989*Picture(:,:,1) + 0.5870*Picture(:,:,2)+ 0.1140*Picture(:,:,3);

end

% Crearea imaginii integrale

IntegralImages.ii = cumsum(cumsum(Picture,1),2);

IntegralImages.ii = padarray(IntegralImages.ii,[1 1], 0, 'pre');

% Crearea imaginii integrale pentru a calcula o abatere standard a

% pixelilor

IntegralImages.ii2 = cumsum(cumsum(Picture.^2,1),2);

IntegralImages.ii2 = padarray(IntegralImages.ii2,[1 1], 0, 'pre');

% Stocarea altor date

IntegralImages.width = size(Picture,2);

IntegralImages.height = size(Picture,1);

IntegralImages.Ratio = Ratio;

funcția GetHaarCasade

function HaarCascade = GetHaarCasade(FilenameHaarcasade)

% Aceasta functie citeste un fisier Matlab cu o structura continand

% datele clasificatorului OpenCV ale fisierului XML openCV.

% Se schimbã structura, ?i adaugã câmpuri lipsã

load(FilenameHaarcasade);

f = fields(opencv_storage);

HaarCascade = opencv_storage.(f{1});

% Adauga toate câmpuri de date ce lipsesc

stages = HaarCascade.stages;

for i = 1:length(stages)

stages2(i).stage_threshold = stages(i).stage_threshold;

stages2(i).parent = stages(i).parent;

stages2(i).next = stages(i).next;

for j = 1:length(stages(i).trees);

for k = 1:length(stages(i).trees(j).value)

a = stages(i).trees(j).value(k);

if(~isfield(a,'left_node')) , a.left_node = []; end

if(~isfield(a,'right_node')), a.right_node = [];end

if(~isfield(a,'left_val')) , a.left_val = []; end

if(~isfield(a,'right_val')) , a.right_val = []; end

if(isempty(a.left_val)), a.left_val = -1; end

if(isempty(a.right_val)), a.right_val = -1; end

if(isempty(a.left_node)), a.left_node = -1; end

if(isempty(a.right_node)),a.right_node = -1; end

a.rects1 = a.feature.rects(1).value;

a.rects2 = a.feature.rects(2).value;

if(length(a.feature.rects) > 2),

a.rects3 = a.feature.rects(3).value;

else

a.rects3 = [0 0 0 0 0];

end

a.tilted = a.feature.tilted;

if(any(a.tilted))

warning('HaarCascade:file','Tilted features are not supported');

end

a = rmfield(a,'feature');

% Valori pe etape si caracteristici intr-o arie mare

stages2(i).trees(j).value(k,:) = [a.threshold a.left_val a.right_val a.left_node a.right_node a.rects1 a.rects2 a.rects3 a.tilted];

end

end

end

HaarCascade.stages = stages2;

funcția prototip

function varargout = prototip(varargin)

% PROTOTIP MATLAB code for prototip.fig

% PROTOTIP, by itself, creates a new PROTOTIP or raises the existing

% singleton*.

%

% H = PROTOTIP returns the handle to a new PROTOTIP or the handle to

% the existing singleton*.

%

% PROTOTIP('CALLBACK',hObject,eventData,handles,…) calls the local

% function named CALLBACK in PROTOTIP.M with the given input arguments.

%

% PROTOTIP('Property','Value',…) creates a new PROTOTIP or raises the

% existing singleton*. Starting from the left, property value pairs are

% applied to the GUI before prototip_OpeningFcn gets called. An

% unrecognized property name or invalid value makes property application

% stop. All inputs are passed to prototip_OpeningFcn via varargin.

%

% *See GUI Options on GUIDE's Tools menu. Choose "GUI allows only one

% instance to run (singleton)".

%

% See also: GUIDE, GUIDATA, GUIHANDLES

% Edit the above text to modify the response to help prototip

% Last Modified by GUIDE v2.5 16-Aug-2014 10:36:38

% Begin initialization code – DO NOT EDIT

gui_Singleton = 1;

gui_State = struct('gui_Name', mfilename, …

'gui_Singleton', gui_Singleton, …

'gui_OpeningFcn', @prototip_OpeningFcn, …

'gui_OutputFcn', @prototip_OutputFcn, …

'gui_LayoutFcn', [] , …

'gui_Callback', []);

if nargin && ischar(varargin{1})

gui_State.gui_Callback = str2func(varargin{1});

end

if nargout

[varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});

else

gui_mainfcn(gui_State, varargin{:});

end

% End initialization code – DO NOT EDIT

% – Executes just before prototip is made visible.

function prototip_OpeningFcn(hObject, eventdata, handles, varargin)

% This function has no output args, see OutputFcn.

% hObject handle to figure

% eventdata reserved – to be defined in a future version of MATLAB

% handles structure with handles and user data (see GUIDATA)

% varargin command line arguments to prototip (see VARARGIN)

% Choose default command line output for prototip

handles.output = hObject;

% Update handles structure

guidata(hObject, handles);

% UIWAIT makes prototip wait for user response (see UIRESUME)

% uiwait(handles.figure1);

% – Outputs from this function are returned to the command line.

function varargout = prototip_OutputFcn(hObject, eventdata, handles)

% varargout cell array for returning output args (see VARARGOUT);

% hObject handle to figure

% eventdata reserved – to be defined in a future version of MATLAB

% handles structure with handles and user data (see GUIDATA)

% Get default command line output from handles structure

varargout{1} = handles.output;

% – Executes on button press in incarca.

function incarca_Callback(hObject, eventdata, handles)

dest=[pwd '\viola-jones – cod sursa\resized_faces\']

[file,dir]=uigetfile('*.jpg')

mkdir([dest '\' file])

img = imread([dir '\' file]);

coordinates = ObjectDetection(img,'haarcascade_frontalface_alt.mat')

img2 = img;

[m,n]=size(coordinates)

if m > 12

start=m-12;

end

p=2;

for k = 1:m

% img = img2;

y = coordinates(k,1)

x = coordinates(k,2)

w = coordinates(k,3)

h = coordinates(k,4)

x = floor(x);

y = floor(y);

w = floor(w);

h = floor(h);

% img2 = img;

img(x+1:x+w,y+1:y+10) = 255;

img(x+1:x+w,y+h:y+h+10) = 255;

img(x+1:x+10,y+1:y+h) = 255;

img(x+h:x+w+10,y+1:y+h+10) = 255;

img3=img2(x+1:x+w,y+1:y+h,:);

str=sprintf('%d%s',k,file);

imwrite(img3,[dest file '\' str ]);

if k > start

p=p+1

str=sprintf('%s%s%s%s%s%s%s%d%s','imshow(img3',',',char(39),'Parent',char(39),',','handles.axes',p,')')

eval(str)

end

end

str=sprintf('%s%s%s%s%s%s%s','imshow(img',',',char(39),'Parent',char(39),',','handles.axes1)')

% imshow(img,'Parent',handles.axes1)

eval(str)

ANEXA 2

Codul MATLAB pentru algoritmul de recunoaștere facială:

funcția run_train_test

function run_train_test(percentTrain,percentTest)

root=[pwd '\viola-jones – cod sursa\faces\']

dest=[pwd '\viola-jones – cod sursa\resized_faces\']

files=dir(root) %cautam toate fisierele din folderul initial

k=0;y=0;Xtrain=[];Xtest=[];ktest=0;names={};

for i=3:length(files)

files2=dir([root files(i).name]); %cautam toate pozele dintr-un folder

% mkdir([dest files(i).name]);

l=length(files2);

for j=3:l

k=k+1;

img = imread([root files(i).name '\' files2(j).name]);

img=imresize(img,[100 100]);

img=rgb2gray(img);

[r c] = size(img);

temp = reshape(img,r*c,1);

if 100*((j-2)/l)<= percentTrain

Xtrain = [Xtrain temp];

if k==1

ytrain=1;

names=[names;files2(j).name];

else

names=[names;files2(j).name];

ytrain=[ytrain str2num(files(i).name)];

end

else

Xtest = [Xtest temp];

ktest=ktest+1;

if ktest==1

ytest=1;

else

ytest=[ytest str2num(files(i).name)];

end

end

end

end

save Xtrain Xtrain

save Xtest Xtest

save ytrain ytrain

save ytest ytest

save names names

m = mean(Xtrain,2);

imgcount = size(Xtrain,2);

A = [];

for i=1 : imgcount

temp = double(Xtrain(:,i)) – m;

A = [A temp];

end

L= A' * A;

[V,D]=eig(L);

L_eig_vec = [];

for i = 1 : size(V,2)

if( D(i,i) > 1 )

L_eig_vec = [L_eig_vec V(:,i)];

end

end

eigenfaces = A * L_eig_vec;

projectimg = [ ];

for i = 1 : size(eigenfaces,2)

temp = eigenfaces' * A(:,i);

projectimg = [projectimg temp];

end

Xtest=double(Xtest);

r=[];

for i=1:size(Xtest,2)

temp=Xtest(:,i);

temp = temp-m;

projtestimg = eigenfaces'*temp;

euclide_dist = [ ];

for i=1 : size(eigenfaces,2)

temp = (norm(projtestimg-projectimg(:,i)))^2;

euclide_dist = [euclide_dist temp];

end

[euclide_dist_min recognized_index] = min(euclide_dist);

r = [r recognized_index];

end

save projectimg projectimg eigenfaces m

Xtrain=Xtrain';

Xtrain=double(Xtrain);

input_layer_size = 10000;

num_labels = 51;

displayData(Xtrain);

lambda = 0.1; %modifici lambda

[all_theta] = oneVsAll(Xtrain, ytrain', num_labels, lambda);

pred = predictOneVsAll(all_theta, Xtrain);

% fprintf('\nTraining Set Accuracy: %f\n', mean(double(pred == ytrain)) * 100);

save all_theta_250 all_theta

Xtest=Xtest';

%testare cu NN

pred = predictOneVsAll(all_theta, Xtest);

save pred_NN pred

fprintf('\nTesting Set Accuracy NN: %f\n', mean(double(pred == ytest')) * 100);

fprintf('\nTesting Set Accuracy PCA: %f\n', mean(double((ytrain(r)) == ytest)) * 100);

save predPCA r

end

funcția run_find_errors

function run_find_errors(percentTrain,percentTest)

root=[pwd '\viola-jones – cod sursa\faces\']

dest=[pwd '\err_faces\']

files=dir(root) %cautam toate fisierele din folderul initial

k=0;y=0;Xtest=[];ktest=0;

load pred_NN

for i=3:length(files)

files2=dir([root files(i).name]); %cautam toate pozele dintr-un folder

mkdir([dest files(i).name]);

l=length(files2);

for j=3:l

k=k+1;

img = imread([root files(i).name '\' files2(j).name]);

img=imresize(img,[100 100]);

img=rgb2gray(img);

[r c] = size(img);

temp = reshape(img,r*c,1);

if 100*((j-2)/l)<= percentTrain

else

Xtest = [Xtest temp];

ktest=ktest+1;

if ktest==1

ytest=1;

else

ytest=[ytest str2num(files(i).name)];

end

if pred(ktest)~=ytest(ktest)

imwrite(img,[dest files(i).name '\' files2(j).name]);

end

end

end

end

end

funcția run_crossvariance_test

function run_crossvariance_test(lowLimit,highLimit)

root=[pwd '\viola-jones – cod sursa\faces\']

dest=[pwd '\viola-jones – cod sursa\resized_faces\']

files=dir(root) %cautam toate fisierele din folderul initial

k=0;y=0;Xtrain=[];Xtest=[];ktest=0;names={};

for i=3:length(files)

files2=dir([root files(i).name]); %cautam toate pozele dintr-un folder

% mkdir([dest files(i).name]);

l=length(files2);

for j=3:l

img = imread([root files(i).name '\' files2(j).name]);

img=imresize(img,[100 100]);

img=rgb2gray(img);

[r c] = size(img);

temp = reshape(img,r*c,1);

if ((100*((j-2)/l)<= lowLimit) || (100*((j-2)/l) >= highLimit))

Xtrain = [Xtrain temp];

k=k+1;

if k==1

ytrain=1;

names=[names;files2(j).name];

else

names=[names;files2(j).name];

ytrain=[ytrain str2num(files(i).name)];

end

else

Xtest = [Xtest temp];

ktest=ktest+1;

if ktest==1

ytest=1;

else

ytest=[ytest str2num(files(i).name)];

end

end

end

end

save Xtrain Xtrain

save Xtest Xtest

save ytrain ytrain

save ytest ytest

save names names

m = mean(Xtrain,2);

imgcount = size(Xtrain,2);

A = [];

for i=1 : imgcount

temp = double(Xtrain(:,i)) – m;

A = [A temp];

end

L= A' * A;

[V,D]=eig(L);

L_eig_vec = [];

for i = 1 : size(V,2)

if( D(i,i) > 1 )

L_eig_vec = [L_eig_vec V(:,i)];

end

end

eigenfaces = A * L_eig_vec;

projectimg = [ ];

for i = 1 : size(eigenfaces,2)

temp = eigenfaces' * A(:,i);

projectimg = [projectimg temp];

end

Xtest=double(Xtest);

r=[];

for i=1:size(Xtest,2)

temp=Xtest(:,i);

temp = temp-m;

projtestimg = eigenfaces'*temp;

euclide_dist = [ ];

for i=1 : size(eigenfaces,2)

temp = (norm(projtestimg-projectimg(:,i)))^2;

euclide_dist = [euclide_dist temp];

end

[euclide_dist_min recognized_index] = min(euclide_dist);

r = [r recognized_index];

end

save projectimg projectimg eigenfaces m

Xtrain=Xtrain';

Xtrain=double(Xtrain);

input_layer_size = 10000;

num_labels = 51;

displayData(Xtrain);

lambda = 0.1; %modifici lambda

[all_theta] = oneVsAll(Xtrain, ytrain', num_labels, lambda);

pred = predictOneVsAll(all_theta, Xtrain);

% fprintf('\nTraining Set Accuracy: %f\n', mean(double(pred == ytrain)) * 100);

save all_theta_250_crossvariance all_theta

Xtest=Xtest';

%testare cu NN

pred = predictOneVsAll(all_theta, Xtest);

% save pred_NN pred

fprintf('\nTesting Set Accuracy NN: %f\n', mean(double(pred == ytest')) * 100);

fprintf('\nTesting Set Accuracy PCA: %f\n', mean(double((ytrain(r)) == ytest)) * 100);

% save predPCA r

end

funcția run_attack

% function run_attack(percentTrain)

close all

clear all

percentTrain=80

root=[pwd '\viola-jones – cod sursa\faces\']

dest=[pwd '\viola-jones – cod sursa\resized_faces\']

files=dir(root) %cautam toate fisierele din folderul initial

k=0;y=0;Xtest=[];ktest=0;Xtrain=[];

for i=3: length(files)

files2=dir([root files(i).name]); %cautam toate pozele dintr-un folder

% mkdir([dest files(i).name]);

l=length(files2);

for j=3:l

k=k+1;

img = imread([root files(i).name '\' files2(j).name]);

img=imresize(img,[100 100]);

img=rgb2gray(img);

%/*zgomot

%img=imnoise(img,'gaussian',0,0.06);

%img=imnoise(img,'salt & pepper',0.4);

%*/

%/* downsampling

% img=double(img);

% img=downsample(img,7);

% img=imresize(img,[100 100]);

% % img=resample(img,2,1);

%

%*/ downsampling

% img(20:40,1:100)=255;

% img=img.*2.2;

%img=img./2;

img=uint8(img);

[r c] = size(img);

temp = reshape(img,r*c,1);

if 100*((j-2)/l)<= percentTrain

Xtrain = [Xtrain temp];

if k==1

ytrain=1;

else

ytrain=[ytrain str2num(files(i).name)];

end

else

Xtest = [Xtest temp];

ktest=ktest+1;

if ktest==1

ytest=1;

else

ytest=[ytest str2num(files(i).name)];

end

end

end

end

load all_theta_250

Xtest=double(Xtest);

Xtest=Xtest';

%testare cu NN

pred = predictOneVsAll(all_theta, Xtest);

fprintf('\nTesting Set Accuracy NN: %f\n', mean(double(pred == ytest')) * 100);

funcția prototip_recunoasterea_persoanei

function varargout = prototip_recunoasterea_persoanei(varargin)

% PROTOTIP_RECUNOASTEREA_PERSOANEI MATLAB code for prototip_recunoasterea_persoanei.fig

% PROTOTIP_RECUNOASTEREA_PERSOANEI, by itself, creates a new PROTOTIP_RECUNOASTEREA_PERSOANEI or raises the existing

% singleton*.

%

% H = PROTOTIP_RECUNOASTEREA_PERSOANEI returns the handle to a new PROTOTIP_RECUNOASTEREA_PERSOANEI or the handle to

% the existing singleton*.

%

% PROTOTIP_RECUNOASTEREA_PERSOANEI('CALLBACK',hObject,eventData,handles,…) calls the local

% function named CALLBACK in PROTOTIP_RECUNOASTEREA_PERSOANEI.M with the given input arguments.

%

% PROTOTIP_RECUNOASTEREA_PERSOANEI('Property','Value',…) creates a new PROTOTIP_RECUNOASTEREA_PERSOANEI or raises the

% existing singleton*. Starting from the left, property value pairs are

% applied to the GUI before prototip_recunoasterea_persoanei_OpeningFcn gets called. An

% unrecognized property name or invalid value makes property application

% stop. All inputs are passed to prototip_recunoasterea_persoanei_OpeningFcn via varargin.

%

% *See GUI Options on GUIDE's Tools menu. Choose "GUI allows only one

% instance to run (singleton)".

%

% See also: GUIDE, GUIDATA, GUIHANDLES

% Edit the above text to modify the response to help prototip_recunoasterea_persoanei

% Last Modified by GUIDE v2.5 24-Aug-2014 16:26:33

% Begin initialization code – DO NOT EDIT

gui_Singleton = 1;

gui_State = struct('gui_Name', mfilename, …

'gui_Singleton', gui_Singleton, …

'gui_OpeningFcn', @prototip_recunoasterea_persoanei_OpeningFcn, …

'gui_OutputFcn', @prototip_recunoasterea_persoanei_OutputFcn, …

'gui_LayoutFcn', [] , …

'gui_Callback', []);

if nargin && ischar(varargin{1})

gui_State.gui_Callback = str2func(varargin{1});

end

if nargout

[varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});

else

gui_mainfcn(gui_State, varargin{:});

end

% End initialization code – DO NOT EDIT

% – Executes just before prototip_recunoasterea_persoanei is made visible.

function prototip_recunoasterea_persoanei_OpeningFcn(hObject, eventdata, handles, varargin)

% This function has no output args, see OutputFcn.

% hObject handle to figure

% eventdata reserved – to be defined in a future version of MATLAB

% handles structure with handles and user data (see GUIDATA)

% varargin command line arguments to prototip_recunoasterea_persoanei (see VARARGIN)

% Choose default command line output for prototip_recunoasterea_persoanei

handles.output = hObject;

set(handles.mean,'string',0)

set(handles.var,'string',0.01)

set(handles.d,'string',0.01)

set(handles.down,'string',3)

set(handles.brightness,'string',1.2)

set(handles.darkness,'string',1.5)

set(handles.cutRegionX,'string',20)

set(handles.cutRegionX2,'string',40)

set(handles.cutRegionY1,'string',10)

set(handles.cutRegionY2,'string',90)

set(handles.jpegCompress,'string',70)

plot(handles.axes4,0)

set(handles.axes4,'visible','off')

set(handles.text4,'visible','off')

plot(handles.axes2,0)

set(handles.axes2,'visible','off')

set(handles.text2,'visible','off')

plot(handles.axes3,0)

set(handles.axes3,'visible','off')

set(handles.text3,'visible','off')

% Update handles structure

guidata(hObject, handles);

% UIWAIT makes prototip_recunoasterea_persoanei wait for user response (see UIRESUME)

% uiwait(handles.figure1);

% – Outputs from this function are returned to the command line.

function varargout = prototip_recunoasterea_persoanei_OutputFcn(hObject, eventdata, handles)

% varargout cell array for returning output args (see VARARGOUT);

% hObject handle to figure

% eventdata reserved – to be defined in a future version of MATLAB

% handles structure with handles and user data (see GUIDATA)

% Get default command line output from handles structure

varargout{1} = handles.output;

% – Executes on button press in incarcaPoza.

function incarcaPoza_Callback(hObject, eventdata, handles)

global img X

X=[];

[file,dir]=uigetfile(fullfile(pwd,'\viola-jones – cod sursa\faces\','*.*'),'Alegeti o poza')

img = imread([dir file]);

img=imresize(img,[100 100]);

imshow(img,'Parent',handles.axes1)

str=sprintf('%s%s','Poza folosita – ', file);

set(handles.text1,'string',str);

img2=rgb2gray(img);

[r c] = size(img2);

temp = reshape(img2,r*c,1);

X = [X temp];

X=double(X);

% – Executes on button press in buttonPCA.

function buttonPCA_Callback(hObject, eventdata, handles)

global X;

load projectimg;

load ytrain;

load names ;

r=[];

for i=1:size(X,2)

temp=X(:,i);

temp = temp-m;

projtestimg = eigenfaces'*temp;

euclide_dist = [ ];

for i=1 : size(eigenfaces,2)

temp = (norm(projtestimg-projectimg(:,i)))^2;

euclide_dist = [euclide_dist temp];

end

[euclide_dist_min recognized_index] = min(euclide_dist);

r = [r recognized_index]

FOLDER=ytrain(r)

FILE=char(names(r))

root=[pwd '\viola-jones – cod sursa\faces\'];

str=sprintf('%s%d%s%s',root,FOLDER,'\',FILE)

img2=imread(str);

imshow(img2,'Parent',handles.axes2)

str=sprintf('%s%s','Poza recunoscuta PCA – ', FILE);

set(handles.text2,'string',str,'visible','on');

r=[];

end

% – Executes on button press in recunoasteNN.

function recunoasteNN_Callback(hObject, eventdata, handles)

global X;

load all_theta_250;

load names ;

load ytrain;

X=X';

%testare cu NN

pred = predictOneVsAll(all_theta, X)

FOLDER=pred

f=find(ytrain==pred)

FILE=char(names(f(1)))

root=[pwd '\viola-jones – cod sursa\faces\']

str=sprintf('%s%d%s%s',root,FOLDER,'\',FILE)

img2=imread(str);

imshow(img2,'Parent',handles.axes3)

str=sprintf('%s%s','Poza recunoscuta NN – ', FILE);

set(handles.text3,'string',str,'visible','on');

X=X';

% – Executes on button press in buttonGaussian.

function buttonGaussian_Callback(hObject, eventdata, handles)

global img X

X=[];

m=get(handles.mean,'string');

var=get(handles.var,'string');

m=str2num(m);

var=str2num(var);

img2=imnoise(img,'gaussian',m,var);

img2=uint8(img2);

set(handles.axes4,'visible','on')

imshow(img2,'Parent',handles.axes4)

str=sprintf('%s%s','Atac folosit – ', 'zgomot Gaussian');

set(handles.text4,'string',str,'visible','on');

img2=rgb2gray(img2);

[r c] = size(img2);

temp = reshape(img2,r*c,1);

X = [X temp];

X=double(X);

% – Executes on button press in buttonSalt.

function buttonSalt_Callback(hObject, eventdata, handles)

global img X

X=[];

d=get(handles.d,'string');

d=str2num(d);

img2=imnoise(img,'salt & pepper',d);

img2=uint8(img2);

set(handles.axes4,'visible','on')

imshow(img2,'Parent',handles.axes4)

str=sprintf('%s%s','Atac folosit – ', 'zgomot Salt&Pepper');

set(handles.text4,'string',str,'visible','on');

img2=rgb2gray(img2);

[r c] = size(img2);

temp = reshape(img2,r*c,1);

X = [X temp];

X=double(X);

% – Executes on button press in buttonDownSampling.

function buttonDownSampling_Callback(hObject, eventdata, handles)

global img X

X=[];

down=get(handles.down,'string');

down=str2num(down);

img2=double(img);

img2=downsample(img2,down);

img2=imresize(img2,[100 100]);

img2=uint8(img2);

set(handles.axes4,'visible','on')

imshow(img2,'Parent',handles.axes4)

str=sprintf('%s%s','Atac folosit – ', 'Subesantionare');

set(handles.text4,'string',str,'visible','on');

img2=rgb2gray(img2);

[r c] = size(img2);

temp = reshape(img2,r*c,1);

X = [X temp];

X=double(X);

% – Executes on button press in buttonIluminare.

function buttonIluminare_Callback(hObject, eventdata, handles)

global img X

X=[];

bright=get(handles.brightness,'string');

bright=str2num(bright);

img2=img.*bright;

img2=uint8(img2);

set(handles.axes4,'visible','on')

imshow(img2,'Parent',handles.axes4)

str=sprintf('%s%s','Atac folosit – ', 'Supraexpunere');

set(handles.text4,'string',str,'visible','on');

img2=rgb2gray(img2);

[r c] = size(img2);

temp = reshape(img2,r*c,1);

X = [X temp];

X=double(X);

% – Executes on button press in buttonIntunecare.

function buttonIntunecare_Callback(hObject, eventdata, handles)

global img X

X=[];

dark=get(handles.darkness,'string');

dark=str2num(dark);

img2=img./dark;

img2=uint8(img2);

set(handles.axes4,'visible','on')

imshow(img2,'Parent',handles.axes4)

str=sprintf('%s%s','Atac folosit – ', 'Subexpunere');

set(handles.text4,'string',str);

img2=rgb2gray(img2);

[r c] = size(img2);

temp = reshape(img2,r*c,1);

X = [X temp];

X=double(X);

% – Executes on button press in buttonDecupare.

function buttonDecupare_Callback(hObject, eventdata, handles)

global img X

X=[];

img2=img;

x1=get(handles.cutRegionX,'string');

x1=str2num(x1);

y1=get(handles.cutRegionY1,'string');

y1=str2num(y1);

y2=get(handles.cutRegionY2,'string');

y2=str2num(y2);

x2=get(handles.cutRegionX2,'string');

x2=str2num(x2);

img2(x1:x2,y1:y2,:)=0;

img2=uint8(img2);

set(handles.axes4,'visible','on')

imshow(img2,'Parent',handles.axes4)

str=sprintf('%s%s','Atac folosit – ', 'decupare regiune');

set(handles.text4,'string',str,'visible','on');

img2=rgb2gray(img2);

[r c] = size(img2);

temp = reshape(img2,r*c,1);

X = [X temp];

X=double(X);

% – Executes on button press in buttonCompresie.

function buttonCompresie_Callback(hObject, eventdata, handles)

global img X

X=[];

img2=uint8(img);

v=get(handles.jpegCompress,'string');

v=str2num(v);

imwrite(img2,'backup.jpg','jpeg','Quality',v);

img2=imread('backup.jpg');

set(handles.axes4,'visible','on')

imshow(img2,'Parent',handles.axes4)

str=sprintf('%s%s','Atac folosit – ', 'compresie JPEG');

set(handles.text4,'string',str,'visible','on');

img2=rgb2gray(img2);

[r c] = size(img2);

temp = reshape(img2,r*c,1);

X = [X temp];

X=double(X);

function mean_Callback(hObject, eventdata, handles)

% – Executes during object creation, after setting all properties.

function mean_CreateFcn(hObject, eventdata, handles)

if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))

set(hObject,'BackgroundColor','white');

end

function var_Callback(hObject, eventdata, handles)

% – Executes during object creation, after setting all properties.

function var_CreateFcn(hObject, eventdata, handles)

% See ISPC and COMPUTER.

if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))

set(hObject,'BackgroundColor','white');

end

function d_Callback(hObject, eventdata, handles)

% – Executes during object creation, after setting all properties.

function d_CreateFcn(hObject, eventdata, handles)

% See ISPC and COMPUTER.

if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))

set(hObject,'BackgroundColor','white');

end

function down_Callback(hObject, eventdata, handles)

%

% – Executes during object creation, after setting all properties.

function down_CreateFcn(hObject, eventdata, handles)

% See ISPC and COMPUTER.

if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))

set(hObject,'BackgroundColor','white');

end

function darkness_Callback(hObject, eventdata, handles)

% – Executes during object creation, after setting all properties.

function darkness_CreateFcn(hObject, eventdata, handles)

% See ISPC and COMPUTER.

if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))

set(hObject,'BackgroundColor','white');

end

function brightness_Callback(hObject, eventdata, handles)

% – Executes during object creation, after setting all properties.

function brightness_CreateFcn(hObject, eventdata, handles)

if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))

set(hObject,'BackgroundColor','white');

end

function cutRegionX_Callback(hObject, eventdata, handles)

% – Executes during object creation, after setting all properties.

function cutRegionX_CreateFcn(hObject, eventdata, handles)

if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))

set(hObject,'BackgroundColor','white');

end

function jpegCompress_Callback(hObject, eventdata, handles)

% – Executes during object creation, after setting all properties.

function jpegCompress_CreateFcn(hObject, eventdata, handles)

if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))

set(hObject,'BackgroundColor','white');

end

function cutRegionY1_Callback(hObject, eventdata, handles)

% hObject handle to cutRegionY1 (see GCBO)

% eventdata reserved – to be defined in a future version of MATLAB

% handles structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of cutRegionY1 as text

% str2double(get(hObject,'String')) returns contents of cutRegionY1 as a double

% – Executes during object creation, after setting all properties.

function cutRegionY1_CreateFcn(hObject, eventdata, handles)

% hObject handle to cutRegionY1 (see GCBO)

% eventdata reserved – to be defined in a future version of MATLAB

% handles empty – handles not created until after all CreateFcns called

% Hint: edit 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

function cutRegionY2_Callback(hObject, eventdata, handles)

% hObject handle to cutRegionY2 (see GCBO)

% eventdata reserved – to be defined in a future version of MATLAB

% handles structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of cutRegionY2 as text

% str2double(get(hObject,'String')) returns contents of cutRegionY2 as a double

% – Executes during object creation, after setting all properties.

function cutRegionY2_CreateFcn(hObject, eventdata, handles)

% hObject handle to cutRegionY2 (see GCBO)

% eventdata reserved – to be defined in a future version of MATLAB

% handles empty – handles not created until after all CreateFcns called

% Hint: edit 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

function cutRegionX2_Callback(hObject, eventdata, handles)

% hObject handle to cutRegionX2 (see GCBO)

% eventdata reserved – to be defined in a future version of MATLAB

% handles structure with handles and user data (see GUIDATA)

% Hints: get(hObject,'String') returns contents of cutRegionX2 as text

% str2double(get(hObject,'String')) returns contents of cutRegionX2 as a double

% – Executes during object creation, after setting all properties.

function cutRegionX2_CreateFcn(hObject, eventdata, handles)

% hObject handle to cutRegionX2 (see GCBO)

% eventdata reserved – to be defined in a future version of MATLAB

% handles empty – handles not created until after all CreateFcns called

% Hint: edit 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

funcția predictOneVsAll

function p = predictOneVsAll(all_theta, X)

m = size(X, 1);

num_labels = size(all_theta, 1);

p = zeros(size(X, 1), 1);

X = [ones(m, 1) X];

[temp p] = max(sigmoid(X*all_theta'), [], 2);

end

funcția predict

function p = predict(Theta1, Theta2, X)

m = size(X, 1);

num_labels = size(Theta2, 1);

p = zeros(size(X, 1), 1);

a1 = [ones(m,1) X];

a2 = [ones(m,1) sigmoid(a1*Theta1')];

[a3 p] = max(sigmoid(a2*Theta2'), [], 2);

end

funcția displayData

function [h, display_array] = displayData(X, example_width)

if ~exist('example_width', 'var') || isempty(example_width)

example_width = round(sqrt(size(X, 2)));

end

colormap(gray);

[m n] = size(X);

example_height = (n / example_width)

display_rows = floor(sqrt(m));

display_cols = ceil(m / display_rows)

pad = 1;

display_array = – ones(pad + display_rows * (example_height + pad), …

pad + display_cols * (example_width + pad));

curr_ex = 1;

for j = 1:display_rows

for i = 1:display_cols

if curr_ex > m,

break;

end

max_val = max(abs(X(curr_ex, :)));

display_array(pad + (j – 1) * (example_height + pad) + (1:example_height), …

pad + (i – 1) * (example_width + pad) + (1:example_width)) = …

reshape(X(curr_ex, :), example_height, example_width) / max_val;

curr_ex = curr_ex + 1;

end

if curr_ex > m,

break;

end

end

h = imagesc(display_array, [-1 1]);

axis image off

drawnow;

end

funcția face_recognition_testing

function face_recognition_testing(flag,flag2)

if nargin<1

fprintf('\n Introduceti NN sau PCA ca intrare')

return

end

flag

root=[pwd '\viola-jones – cod sursa\faces\']

dest=[pwd '\viola-jones – cod sursa\resized_faces\']

files=dir(root)

k=0;X=[];

if nargin <2

for i=3:length(files)

files2=dir([root files(i).name]);

mkdir([dest files(i).name]);

for j=8:length(files2)

k=k+1;

if k==1

ytest=1;

else

ytest=[ytest str2num(files(i).name)];

end

img = imread([root files(i).name '\' files2(j).name]);

img=imresize(img,[100 100]);

% imwrite(img,[dest files(i).name files2(j).name]);

img=rgb2gray(img);

[r c] = size(img);

temp = reshape(img,r*c,1);

X = [X temp];

end

end

X=double(X);

save X X

save ytest ytest

else load X

end

%testarea cu PCA

load projectimg;

load all_theta;

load y;

switch flag

case 'PCA'

r=[];

for i=1:size(X,2)

temp=X(:,i);

temp = temp-m;

projtestimg = eigenfaces'*temp;

euclide_dist = [ ];

for i=1 : size(eigenfaces,2)

temp = (norm(projtestimg-projectimg(:,i)))^2;

euclide_dist = [euclide_dist temp];

end

[euclide_dist_min recognized_index] = min(euclide_dist);

r = [r recognized_index];

end

fprintf('\nTraining Set Accuracy: %f\n', mean(double((y(r))' == ytest)) * 100);

case 'NN'

X=X';

%X e uint8 si trebuie double

input_layer_size = 10000; % 20×20 Input Images of Digits

num_labels = 25; %numarul de utilizatori

lambda = 0.1; %pasul de incrementare 0.001-10;

%testare cu NN

pred = predictOneVsAll(all_theta, X);

fprintf('\nTraining Set Accuracy: %f\n', mean(double(pred == ytest)) * 100);

case ''

fprintf('\n Introduceti NN sau PCA ca intrare')

end

end

funcția face_recognition_train

function face_recognition_train(flag,flag2)

if nargin<1

fprintf('\n Introduceti NN sau PCA ca intrare')

return

end

root=[pwd '\viola-jones – cod sursa\faces\']

dest=[pwd '\viola-jones – cod sursa\resized_faces\']

files=dir(root) %cautam toate fisierele din folderul initial

k=0;y=0;X=[];

names={};

if nargin <2

for i=3:length(files)

files2=dir([root files(i).name]); %cautam toate pozele dintr-un folder

mkdir([dest files(i).name]);

for j=3:8%length(files2)

k=k+1;

if k==1

y=1;

else

y=[y str2num(files(i).name)];

end

names=[names;files2(j).name];

img = imread([root files(i).name '\' files2(j).name]);

img=imresize(img,[100 100]); %testez cu dimensiuni diferite , se tine cont si de input_layer_size

imwrite(img,[dest files(i).name '\' files2(j).name]);

img=rgb2gray(img);

[r c] = size(img);

temp = reshape(img,r*c,1);

X = [X temp];

end

end

save names names

save X X

save y y

else load X

load y

end

switch flag

case 'PCA'

m = mean(X,2);

imgcount = size(X,2);

A = [];

for i=1 : imgcount

temp = double(X(:,i)) – m;

A = [A temp];

end

L= A' * A;

[V,D]=eig(L);

L_eig_vec = [];

for i = 1 : size(V,2)

if( D(i,i) > 1 )

L_eig_vec = [L_eig_vec V(:,i)];

end

end

eigenfaces = A * L_eig_vec;

projectimg = [ ];

for i = 1 : size(eigenfaces,2)

temp = eigenfaces' * A(:,i);

projectimg = [projectimg temp];

end

save projectimg projectimg m eigenfaces

case 'NN'

X=X';

y=y';

X=double(X);

input_layer_size = 10000;

num_labels = 25;

displayData(X);

lambda = 0.1; %modifici lambda

[all_theta] = oneVsAll(X, y, num_labels, lambda);

pred = predictOneVsAll(all_theta, X);

save all_theta all_theta

fprintf('\nTraining Set Accuracy: %f\n', mean(double(pred == y)) * 100);

case ''

fprintf('\n Introduceti NN sau PCA ca intrare')

end

end

funcția oneVsAll

function [all_theta] = oneVsAll(X, y, num_labels, lambda)

m = size(X, 1);

n = size(X, 2);

all_theta = zeros(num_labels, n + 1);

X = [ones(m, 1) X];

for c=1:num_labels

initial_theta = zeros(n+1,1);

options = optimset('GradObj','on','MaxIter',250);

[theta] = fmincg (@(t)(lrCostFunction(t, X, (y == c), lambda)), initial_theta, options);

all_theta(c,:)=theta;

end;

end

BIBLIOGRAFIE

A [2] BUCKNALL, J. M.: How to Find a Face, in PC Plus, Issue 296, July 18th 2010.

B [2] Deborah Thomas, “FACE RECOGNITION FROM SURVEILLANCE-QUALITY VIDEO”

[3] Mihnea Horia Vrejoiu, Anca Mihaela Hotăran,”DETECTAREA AUTOMATĂ A FEȚELOR UMANE. METODA VIOLA-JONES”, Articol în revistă

[4] NIST Subcommittee on Biometrics: www.biometricscatalog.org

[5] Pedro Tome *, Julian Fierrez, Ruben Vera-Rodriguez, Daniel Ramos,” Identification using face regions: Application and assessment in forensic scenarios” – http://www.fsijournal.org/article/S0379-0738(13)00397-6/abstract

[6] Prof.dr.ing. Ștefan HOLBAN, “REȚELE NEURONALE. Arhitecturi și algoritmi”, Editura Politehnică, Timișoara 2002

[7] S. Kong, J. Heo, B. Abidi, J. Paik, and M. Abidi, "Recent Advances in Visual and Infrared Face Recognition – A Review," the Journal of Computer Vision and Image Understanding, Vol. 97, No. 1, pp. 103-135, June 2005.

[8] Vinay Kumar Bettadapura, “Face Expression Recognition and Analysis: The State of the Art”

[9] W. ZHAO, R. CHELLAPPA , P. J. PHILLIPS, A. ROSENFELD “Face Recognition: A Literature Survey”

[10] http://rria.ici.ro/ria2013_2/art03.php?lang=en

[11] http://makematics.com/research/viola-jones/

[12] http://scs.etc.tuiasi.ro/iciocoiu/courses/ESL/homeworks/hw2/Capitolul1.pdf

[13] http://www.cl.cam.ac.uk/research/dtg/attarchive/facedatabase.html

[14] http://users.utcluj.ro/~rdanescu/PI-L10r.pdf

[15] http://www.vision.caltech.edu/html-files/archive.html

[16] http://homepages.abdn.ac.uk/m.burton/pages/gfmt/Glasgow%20Face%2 Recognition%20Group.html

[17] http://vision.ucsd.edu/~leekc/ExtYaleDatabase/ExtYaleB.html

[18] http://ro.wikipedia.org/wiki/JPEG

[19] http://help.adobe.com/ro_RO/photoshop/cs/using/WS4DE92D2D-5A4C-42a8-90E1-FD4E912A9BFDa.html

[20] http://andrei.clubcisco.ro/cursuri/f/f-sym/5master/aac-tdmrc/41_ Elemenete%20de%20baza %20in%20standardul%20MPEG.pdf

BIBLIOGRAFIE

A [2] BUCKNALL, J. M.: How to Find a Face, in PC Plus, Issue 296, July 18th 2010.

B [2] Deborah Thomas, “FACE RECOGNITION FROM SURVEILLANCE-QUALITY VIDEO”

[3] Mihnea Horia Vrejoiu, Anca Mihaela Hotăran,”DETECTAREA AUTOMATĂ A FEȚELOR UMANE. METODA VIOLA-JONES”, Articol în revistă

[4] NIST Subcommittee on Biometrics: www.biometricscatalog.org

[5] Pedro Tome *, Julian Fierrez, Ruben Vera-Rodriguez, Daniel Ramos,” Identification using face regions: Application and assessment in forensic scenarios” – http://www.fsijournal.org/article/S0379-0738(13)00397-6/abstract

[6] Prof.dr.ing. Ștefan HOLBAN, “REȚELE NEURONALE. Arhitecturi și algoritmi”, Editura Politehnică, Timișoara 2002

[7] S. Kong, J. Heo, B. Abidi, J. Paik, and M. Abidi, "Recent Advances in Visual and Infrared Face Recognition – A Review," the Journal of Computer Vision and Image Understanding, Vol. 97, No. 1, pp. 103-135, June 2005.

[8] Vinay Kumar Bettadapura, “Face Expression Recognition and Analysis: The State of the Art”

[9] W. ZHAO, R. CHELLAPPA , P. J. PHILLIPS, A. ROSENFELD “Face Recognition: A Literature Survey”

[10] http://rria.ici.ro/ria2013_2/art03.php?lang=en

[11] http://makematics.com/research/viola-jones/

[12] http://scs.etc.tuiasi.ro/iciocoiu/courses/ESL/homeworks/hw2/Capitolul1.pdf

[13] http://www.cl.cam.ac.uk/research/dtg/attarchive/facedatabase.html

[14] http://users.utcluj.ro/~rdanescu/PI-L10r.pdf

[15] http://www.vision.caltech.edu/html-files/archive.html

[16] http://homepages.abdn.ac.uk/m.burton/pages/gfmt/Glasgow%20Face%2 Recognition%20Group.html

[17] http://vision.ucsd.edu/~leekc/ExtYaleDatabase/ExtYaleB.html

[18] http://ro.wikipedia.org/wiki/JPEG

[19] http://help.adobe.com/ro_RO/photoshop/cs/using/WS4DE92D2D-5A4C-42a8-90E1-FD4E912A9BFDa.html

[20] http://andrei.clubcisco.ro/cursuri/f/f-sym/5master/aac-tdmrc/41_ Elemenete%20de%20baza %20in%20standardul%20MPEG.pdf

Similar Posts