Controlul Unui Caracter Virtual cu Ajutorul Miscarilor Capului
CONTROLUL UNUI CARACTER VIRTUAL CU AJUTORUL MIȘCĂRILOR CAPULUI
CUPRINS
Cuprins
Introducere 4
Tehnologii folosite în dezvoltarea aplicației 6
II.1. Microsoft .Net
II.1.a. Cadrul de lucru .NET
II.1.b. Limbajul C#
II.2. Intel OpenCV
II.3. EmuCV
II.4. Microsoft DirectX
II.5. Circuitele de tipul TX2 și RX2
Proiectarea aplicației și modul de interacțiune dintre tehnologii
III.1. Descrierea aplicației
III.2. Diagrama aplicației
Componetele specifice ale aplicației 36
IV.1. Detecția feței
IV.2. Rendarea grafică
IV.3. Transmiterea mișcărilor către macheta teleghidată
Posibile aplicații ale soluției 43
Aplicații similare
VI.1. Microsoft XBOX – Project Natal
VI.2. Sony EyePet
Concluzii
Bibliografie
Anexe
I. Introducere
Acest proiect va implementa un algoritm de urmărire a mișcării capului unei persoane și va folosi ieșirea produsă de acest algoritm pentru a controla un caracter virtual într-un mediu virtual, de asemenea aceste mișcări ale capului pot fi utilizate pentru a controla o machetă teleghidată.
Dificultatea întâmpinată în detecția și localizarea într-o imagine a obiectelor, reprezintă o provocare în domeniul informatic, însă astfel de algoritmi prezintă oportunitatea de a implementa noi moduri de a interacționa în lumea virtuală.
Pornirea aplicației determină inițializarea unui mediu virtual în interiorul căruia se va afla un personaj, denumit generic avatar. Avatarul răspunde comenziilor date prin mișcările capului, astfel apropierea sau îndepărtarea de webcam determină înaintarea sau deplasarea înapoi a avatarului față de punctul său original. Mișcările laterale determină deplasarea la stânga sau la dreapta a avatarului.Pot de asemenea să existe combinații de mișcări față-dreapta , față-stânga și spate-dreapta, spate-stânga, având astfel control asupra mișcărilor pe diagonală a avatarului.
Regulile de mișcare a avatarului sunt și regulile cu care utilizatorul controlează macheta teleghidată.
În paginile următoare vor fi descrise tehonologiile ce permit implementarea unei astfel de aplicații, tehnologii ca :
Microsoft .Net
OpenCV
EmguCV
Microsoft DirectX
Transmisia pentru circuitele TX2/RX2
urmatede o analiză a obiectivului și a modului de a obține rezultatele dorite, o descriere tehnică a aplicației, încheind prin utilizabilitatea în viitor a aplicației, proiecte similare și concluzii.
Implementarea aplicației în limbajul de programare C# a fost aleasă ca urmare a ușurinței de dezvoltare și a performanței apropiate de aplicațiile devoltate în limbajul C, totodată mediul de dezvoltarea pentru C# dat de Visual Studio 2008, oferă un control și o organizare sporită asupra întregului proiect
II. Tehnologii folosite în dezvoltarea aplicației
Tehnologiile folosite în dezolvoltarea aplicației sunt elementele care permit dezvoltarea aplicației în modul de funcționare prevăzut, unele dintre aceste sunt constant reînoite, altele sunt îmbunătățite foarte rar, fiind considerate elemente de referință și astfel schimbarea sau alterarea surselor ar putea produce efecte negative asupra utilizatorilor.
II.1. Microsoft .Net
.NET este un cadru (Framework) de dezvoltare software unitară care permite realizarea, distribuirea și rularea aplicațiilor-desktop Windows și aplicațiilor WEB [1]. Tehnologia .NET pune împreună mai multe tehnologii (ASP, XML, OOP, SOAP, WDSL, UDDI) și limbaje de programare (VB, C++, C#, J#) asigurând totodată atât portabilitatea codului compilat între diferite calculatoare cu sistem Windows, cât și reutilizarea codului în programe, indiferent de limbajul de programare utilizat. [1]
Pentru a dezvolta aplicații pe platforma .NET este necesar să avem 3 componente esențiale:
un set de limbaje (C#, Visual Basic .NET, J#, Managed C++, Smalltalk, Perl,Fortran, Cobol, Lisp, Pascal etc),
un set de medii de dezvoltare (Visual Studio .NET, Visio),
și o bibliotecă de clase pentru crearea serviciilor Web, aplicațiilor Web și aplicațiilordesktop Windows.
II.1.a. Cadrul de lucru .NET
Micorost .Net a aparut să aducă o schimbarea, o nouă direcție pentru Microsoft, înainte , programele care nu erau dezolvate în .Net, codul sursă era compilat în cod nativ x86, după care era executat de procesorul calculatorului.[1]
Fig. II.1. Arhitectura .NET [2]
Framework-ul .Net compilează codul sursă în jetoane ( tokens ), care sunt executate de un instrument Runtime, datorită faptului ca tehnologiile apărute în cadrul Microsoft în ultimii 20 de ani au dus la apariția acestui mod de lucru, se poate considera ca mediul de lucru .Net este „culminație firească a tehnologiilor Microsoft, într-o tentativă îndrăzneață de a unifica programare Windows” [1].
În general se consideră că .Net este format din trei părți importante : biblioteca Framework Class, limbajele .Net și intrumentul Runtime. Biblioteca Framwork Class este un set de două tipuri de clase, cele care reprezintă o versiune de intefață API pentru Win32 divizată în componente și cele ce reprezintă noua paradigmă de programare.Instrumentul Runtime execută cod sursă scris în limbaje .Net și compilate în limbaj imtermediar.
Astfel programul apelat trebuie să aibe semnătura specificată de programul apelant și se execută verificări pentru a asigura că întreg programul are permisiunea de a-și efectua acțiunile. Asta înseamna că instrumentul Runtime trebuie să rezolve câteva probleme importante – securitate, gestionarea memoriei și interoperarea cu cod ce nu aparține .Net.
Limbajele .Net sunt alcătuite din program care apelează metode pe tipuri de cadre de lucru și tipuri particularizate. În limbajul .Net există compilatoare compilează cod scripting si compilatoare care permit extinderea unui tip existent.
În esență programare .Net nu diferă cu mult de programare Win32, astfel dezvoltarea unei aplicații urmează în general următoarea desfășurare : identificarea problemei ce trebuie rezolvată, conceperea programului și scrierea acestuia folosind serviciile puse la dispoziție de bibliotecile disponibile și apelarea codului printr-un fișier binar executat de sistem.
Common Type System ( CTS – sistemul de tipuri uzuale ) definește tipurile de bază și de valori sub forma unui standard ce trebuie urmat de toate limbajele atunci când se compilează un program [1].CTS definește și specificațiile ce trebuie urmate de tipurile noi. Tipurile scrise într-un limbaj pot fi compilate în cod intermediar și utilizate într-un alt limbaj al cadrului de lucru .Net. Un alt element standard al cadrului de lucru este componenta numita CLS ( Common Language Specification – specificația de limbaje uzuale . Orice element compatibil CLS, împreună cu tipurile pe care le generează, poate fi utilizat de codul generat de alt element compatibil CLS [1], aceste propietăți dau numele componentei Runtime și denumirea de Common Language Runtime ( CLR – instrument Runtime de limbaje uzuale ). CLR execută totuși doar cod în limbaj intermediar , iar denumirea înseamnă defapt că orice limbaj .Net poate genera limbaj intermediar [1].
Memoria este protejată de alterare, astefel se asigură securitatea, prin utilizarea unor informații denumite metadate, informații care permit compararea limbajul din programul apelant cu metadatele metodei corespondente pe tipul cerut și dacă acestea nu potrivesc perfet, tipul nu va fi apelat[2]. Metadatele în principu descriu tipuri ce aparțin limbajului .Net.
Fig. II.2 Execuția unui program în .Net [1]
Întregul program .Net este conținut în pachete de desfășurare, numite ansambluri. Ele includ limbajul intermediar al tipurilor pe care le conțin și metadatele ce descriu tipurile respective. Fiecare ansamblu conține și informații despre ansamblurile pe care le folosesc tipurile sale, în acest mod există posibilitatea de localizare și de incărcare a tipului. După încărcarea tipului cu ajutorul instrumentului Runtime, acesta substituie punctul de intrare al fiecărei metode cu o porțiune de cod racord, care în momentul apelării motodei, codul de racord execută compilatorul JIT pe limbajul său intermediar. Compilatorul JIT generează cod nativ pentru platforma pe care este rulat ansamblul și îl depozitează undeva în memorie [3].
Programul compilat JIT rămâne în memorie și este abandonat la descărcarea tipului. Altă opțiune ( numită pre-JIT ) este de a compila limbajul intermediar în cod nativ la instalarea unui ansamblu. Pre-JIT extinde timpul instalării ansamblului, asta insemnând că prima executare a fiecărui tip este mai rapidă, fiindcă nu mai este necesară etapa JIT. Ansamblurile bibliotecii Framework Class sunt toate pre-JIT și se poate opta a efectua pre-JIT la propria aplicație, folosind instrumentul „ngesn.exe” [1].
Compilatorul JIT are avantajul de a rula pe calculatorul unde va fi executat programul. Asta înseamnă că compilatorul JIT poate examina informații cum sunt tipul procesorului și cantitatea de memorie instalată în calculator, folosindu-se pentru a regla codul nativ care este produs.
Compilatoarele convenționale nu dețin acest avantaj, acestea generează cod multi-funcțional, fie programatorul trebuie să creeze câteva versiuni optimizate pentru parametri diferiți ( exemple : compilatorul C++ dispune de opțiunile /G1 /G2 /G3 /G4 /G5 și /G6 pentru optimizarea diverselor procesoare ) [1]. Această problema apare doar în cazul compilatorului pre-JIT, deoarece generează programele în funcție de configurația calculatorului pe care rulează. În cazul în care se modifică cantitatea de memorie instalată pe calculator, compilatorul pre-JIT va trebui reaplicat.
Diferit de bibliotecile native Win32, .NET , oferă o singură sursă de memorie alocată și anume memoria heap gestionată .NET și pe lângă oferă și o modalitate de gestionare a memoriei respective, rutină denumită generic Garbage Collector ( runtină de colectare a deșeurilor ).
În cadrul .NET tipurile pot exista fie în două stări : refrințe și tipuri de valori. Tipurile de referință sunt alocate pe memoria heap gestionată de instrumentul Runtime([3]). Această memorie este implementată ca heap de performanță ridicată. Memoria heap este gestionată GC, în acest fel fiind posibilă urmărirea referințelor la un obiect. Dacă pentru un obiect nu există nici o referință atunci memoria utulizată de acel obiect este marcată ca disponibilă, astfel când se realizează procesul de curățare a memoriei GC va refolosi memoria care nu mai este utilizată ([2]).
Runtina de colectare a deșeurilor poate să compacteze memoria heap și în cadrul procesului de compactare să permită deplasarea prin heap a obiectelor existente. Acest proces este cel mai costisitor din intreaga rutina GC ([1]). Totuși Framework Class vă poate permite modificări în modul în care funcționează GC, de exemplu permite inițializare procedeului de compactare într-un moment de incativitate a aplicației. Procesul de compactare mai implică și gestionarea pointerilor în cazul deplasării obiectelor prim memorie, astfel GC are și responsabilitate de a regla orice pointeri pe care referințele la obiecte din program le folosesc ([3]).
Folosirea unei rutine de colectare a deșeurilor izolează programatorul de detaliile alocării memoriei și-l scutește de responsabilitate eliberării memoriei. Același lucru se aplică șirurilor și tablourilor, deoarce cadrul de lucru pune la dispoziție clase ce gestionează șirurile și tablourile. Limitele tablourilor sunt verificate la fiecare accesare, pentru a nu permite accesări înafara limitelor ( out of bounds exceptions ).
Noțiunea de generație este întrodusă tot de mecanismul de colectare de deșeurilor, mecanism care permite obiectelor ce supravițuiesc unei colectări să fie trecute într-o generație mai veche, astfel se poate optimiza activitatea de colectare doar prin monitorizarea și colectarea deșeurilor de la generațiile mai recente ([2]). Optimizare bazată pe o dovadorice pointeri pe care referințele la obiecte din program le folosesc ([3]).
Folosirea unei rutine de colectare a deșeurilor izolează programatorul de detaliile alocării memoriei și-l scutește de responsabilitate eliberării memoriei. Același lucru se aplică șirurilor și tablourilor, deoarce cadrul de lucru pune la dispoziție clase ce gestionează șirurile și tablourile. Limitele tablourilor sunt verificate la fiecare accesare, pentru a nu permite accesări înafara limitelor ( out of bounds exceptions ).
Noțiunea de generație este întrodusă tot de mecanismul de colectare de deșeurilor, mecanism care permite obiectelor ce supravițuiesc unei colectări să fie trecute într-o generație mai veche, astfel se poate optimiza activitatea de colectare doar prin monitorizarea și colectarea deșeurilor de la generațiile mai recente ([2]). Optimizare bazată pe o dovadă empirică că obiectele mai recente vor avea o durată de viață mai scurtă decât, astfel încât colectarea deșeurilor pe obiecte mai recente va elibera mai mult spațiu decât colectarea deșeurilor pe obiectele mai vechi.
Conceptul de Interoperări a apărut ca o necesitate evidentă după ani de dezvoltare de aplicații și se prezintă ca fiind o paradigmă ce permite o viață prelungită codului dezolvatat pentru sistemul de operare Windows înainte de apariția .NET. Această prelungire a vieții aplicațiilor precedente este posibilă pentru că .Net reutilizează în esență acealși componente inițiale sau derivări ale acelor componente. Spre exemplu librăriile de ferestre din .Net, Windows.Forms, se bazează pe cod nativ GDI+, adică pe o nouă librărie grafică pentru Windows, librărie care este o derivare a codului GDI, utilizat încă din primele zile de viață a sistemului de operare Windows ([1]).
Astfel cerința de interoperare între cod .NET și cod nativ non-.NET este evidentă.Interoperare se poate realiza prin patru tehnologii :
Platform Invoke
It Just Works
COM Interop
Manual Marshalling
Platform Invoke ( P/Invoke) permite apeluri la biblioteci care au fost compilate pentru o platformă specifică, iar în Windows aceasta înseamnă apelarea funcțiilor exportate din bibliotecile cu legare dinamică ( DLL ). Programatorul trebuie să identifice acea bibliotecă ce conține metoda și poate fi nevoie să furnizeze indicii.Astfel că în mare măsură, programatorul nu trebuie să-și facă griji despre transformarea parametrilor, o problemă potențială apare dacă programatorul dorește să transfere înregistrarea unei date spre o funcție de instrument Runtime și în mod prestabilit nu există nici o garantare a localizării absolute a unui câmp în interiorul tipului..NET asigură totuși un mecanism pentru a indica faptul că într-o înregistrare câmpurile ar trebuie să aibe o locație absolut ([1]).
It Just Works ( IJW ) constituie un caz special de P/Invoke și ca tehnologie este disponibilă numai în extensiile de tip managed pentru C++. IJW permite apelarea unui program fără a mai fi nevoie ca tipurile de clase să fie compatibile între codul de tip managed sau unmanaged ([1]).
Component Object Model ( COM ) a devenit o tehnologie de succes deoarece permite divizarea programului în componente. Astfel o mare parte din programul bibliotecă poate fi accesat numai ca obiecte COM ( funcționlitatea DirectX și Windows Shell este asemănătoare ).
Fig. II.3 Container apelabil de instrumentul Runtime ([1])
Pentru ca un tip .NET să apeleze un obiect COM, programatorul trebuie să genereze o clasă container ( înfășurătoare ) .NET, pentru asta .NET pune la dispoziție instrumentul „tlbimp.exe”, care primește la intrare o bibliotecă de tipuri, sau un fișier care are o legătură la biblioteca de tipuri resursă și generează un ansamblu ce deține clasele container necesare ( containere apelabile de instrumentul Runtime, sau RCW ) pe care le apelează programul .NET.
În Fig.II.3. este prezentat un container apelabil de instrumentul Runtime, care permite tipurilor .NET să utilizeze tipuri COM. Durata de viață a obiectului COM este determinată de contorul său de referință. Runtina de colectare a deșeurilor determină durata de viață a unui obiect .NET, astfel că RCW va regla contorul de referință al obiectului COM atunci când reprezentantul nu mai este utilizat ([1]).
Dacă nici una dintre metodele enumerate mai sus nu funcționează intercolectivitatea se poate realiza și manual, astfel sunt permise apelări din .NET spre cod nativ unmanaged. Cadrul de lucru oferă multe clase ce permit aceste operații, astfel fiind posibilă transformarea tipurilor managed în tipuri unmanaged, sau transferul de referință al obiectelor managed spre unamanaged.
În .NET termenii managed ( gestionat ) și unmanaged ( negestionat ) se referă la felul în care este menținută capacitatea de stocare pentru instanțele tipului. Un tip managed este creat întodeauna cu operatorul new din .NET și întodeauna în memoria heap gestionată de rutina de colectare a deșeurilor. Deoarece tipurile unamanged sunt create pe memoria heap care nu este gestionată, trebuie folosiți operatori de tip unmanaged ( delete ), atunci când obiectul nu mai este necesar.
II.1.b. Limbajul C#
Limbajul C# a apărut la sfârșitul anilor 1990 ca un concurent direct al limbajului Java. C# este un limbaj orientat-obiect ce aparține platformei .NET, dezvoltate de Microsoft, iar ca și Java este un derivat al limbajului C++ ([3]).
C# permite utilizarea OOP respectând toate principiile limbajului C++, cu mici diferențe în cadrul unor principii, spre exemplu moștenirea se poate face de la o singură clasă, dar C# întroduce noțiunile de abstract și sealed, care obligă o clasă la moștenire sau să se opună procesului de moștenire.
Toate componentele limbajului sunt într-un fel sau altul, asociate noțiunii de clasă. Programul însuși este o clasă având metoda statică Main() ca punct de intrare, clasă ce nu se instanțiază. Chiar și tipurile predefinite byte, int sau bool sunt clase sigilate derivate din clasa ValueType din spațiul System. Pentru a evita unele tehnici de programare periculoase, limbajul oferă tipuri speciale cum ar fi: interfețe și delegări ([2]).
Evenimentele sunt membri ai unei clase ce permit clasei sau obiectelor clasei să facă notificări, adică să anunțe celelalte obiecte asupra unor schimbări petrecute la nivelul stării lor. Clasa furnizoare a unui eveniment publică (pune la dispoziția altor clase) acest lucru printr-o declarare event care asociază evenimentului un delegat, adică o referință către o funcție necunoscută căreia i se precizează doar antetul, funcția urmând a fi implementată la nivelul claselor interesate de evenimentul respectiv ([2]). Este modul prin care se realizează comunicarea între obiecte. Tehnica prin care clasele implementează metode (handler-e) ce răspund la evenimente generate de alte clase poartă numele de tratare a evenimentelor. Sintaxa:
[atrib] [modificatori]event [tip_delegat] [nume]
Modificatorii permiși sunt aceiași ca și la metode. Tipul delegat este un tip de date ca oricare altul, derivat din clasa sigilată Delegate, din spațiul System. Definirea unui tip delegat se realizează prin declararea:
[atrib][modificatori] delegate [tip_rezultat] [nume_delegat] ([listă_param_formali] )
Undelegat se poate defini și în afara clasei generatoare de evenimente și poate servi și altor scopuri în afara tratării evenimentelor ([2]).
De exemplu, dacă dorim să definim o metodă asociată unui vector de numere întregi, metodă ce verifică dacă vectorul este o succesiune „bine aranjată” (orice două valori succesive respectă o anumită regulă), o implementare „generică” se poate realiza folosind delegări.
Un exemplu teoretic de declarare și tratare a unui eveniment se poate enunța în felule următor:în clasa Vector se consideră că interschimbarea valorilor a două componente ale unui vector e un eveniment de interes pentru alte obiecte sau clase ale aplicației. Se definește un tip delegat TD (să zicem) cu niște parametri de interes și un eveniment care are ca asociat un delegat E (de tip TD). Orice obiect x din clasa Vector are un membru E (inițial null). O clasă C interesată să fie înștiințată când se face vreo interschimbare într-un vector pentru a genera o animație, de exemplu, va implementa o metodă M ce realizează animația și va adăuga pe M (prin intermediul unui delegat) la x.E. Cumulând mai multe astfel de referințe, x.E ajunge un fel de listă de metode (handlere). În clasa Vector, în metoda sort, la interschimbarea valorilor a două componente se invocă delegatul E. Invocarea lui E realizează de fapt activarea tuturor metodelor adăugate la E
Interfețele sunt foarte importante în programarea orientată pe obiecte, deoarece permit utilizarea polimorfismului într-un sens mai extins.O interfață este o componentă a aplicației, asemănătoare unei clase, ce declară prin membrii săi (metode, proprietăți, evenimente și indexatori) un „comportament” unitar aplicabil mai multor clase, comportament care nu se poate defini prin ierarhia de clase a aplicației ([2]). De exemplu, dacă vom considera arborele din Fig.II.4. , în care AVERE este o clasă abstractă, iar derivarea claselor a fost concepută urmărind proprietățile comune ale componentelor unei averi, atunci o clasă VENIT nu este posibilă, deoarece ea ar moșteni de la toate clasele evidențiate, iar moștenirea multiplă nu este admisă în C#.
Fig. II.4. Structura clasei Avere ([2])
Pentru metodele din cadrul unei interfețe nu se dă nici o implementare, ci sunt pur și simplu specificate, implementarea lor fiind furnizată de unele dintre clasele aplicației. Nu există instanțiere în cazul interfețelor, dar se admit derivări, inclusiv moșteniri multiple ([2]). În exemplul nostru, se poate defini o interfață VENIT care să conțină antetul unei metode calc (să zicem) pentru calculul venitului obținut, fiecare dintre clasele care implementează interfața VENIT fiind obligată să furnizeze o implementare (după o formulă de calcul specifică) pentru metoda calc din interfață. Orice clasă care dorește să adere la interfață trebuie să implementeze toate metodele din interfață. Toate clasele care moștenesc dintr-o clasă care implementează o interfață moștenesc, evident, metodele respective, dar le pot și redefini (de exemplu, clasa Credit_acordat redefinește metoda calc din clasa Investiție, deoarece formula de calcul implementată acolo nu i se „potrivește” și ei).
În C# există două categorii de tipuri de date([3]):
• tipuri valoare
• tipul simple: byte, char, int, float etc.
• tipul enumerare – enum
• tipul structură – struct
• tipuri referință
• tipul clasă – class
• tipul interfață – interface
• tipul delegat – delegate
• tipul tablou – array
Toate tipurile de date sunt derivate din tipul System.Object . Toate tipurile valoare sunt derivate din clasa System.ValueType, derivată la rândul ei din clasa Object (alias pentru System.Object).
Limbajul C# conține un set de tipuri predefinite (int, bool etc.) și permite definirea unor tipuri proprii (enum, struct, class etc.).Tipuri simple definite.
Limbajul C# 3.0 a întrodus conceptul de variabilă a cărui tip este determinat de Runtime, aceste variabile se declară prin folosirea cuvântului rezervat ”var” ([2]) :
var myVariable = 10; // tipul lui myVariable la Runtime va fi int
myVariable = ”atribuie string”; // această atribuire va fi semnalată ca și eroare deoarce tipului Int
//nu ii pot fi atribuite valoari de tipul String
II.2. Intel OpenCV
Intel Open Source Computer Vision Library (OpenCV) , reprezintă o colecție de funcții care permit o analiză în timp real a imaginilor ([4]). În lipsa de unui API standard ( de exemplu OpenGL sau DirectX pentru grafică sau OpenSSL pentru criptografie ) cele mai frecvente librării de vizualizare bazate pe vizualizare artificială făceau parte dintr-un dintre categoriile:
Cod de cercetare ( funcții încete, instabile cu tipuri independente/incompatibile cu unele librarii )
Soft comercial scump ( Halcon, MATLAB + Simulink )
Soluții specializate , realizate cu harware specializat ( supraveghere video, echipamente medicale )
OpenCV e o alternativă la aceste tipuri, oferind o soluție standard care să simplifice dezvoltarea de noi aplicații mult mai ușor și rapid, în același timp având optimizări pentru arhitecturile Intel, de exemplu atingerea performanțelor de timp-real pentru algoritmi considerați greoi de cele mai multe sistem ( detecția feței ) ([5])..
Astfel în perioada 1999-2001 se naște proiectul CVL, a cărui obiective erau dezvoltarea unei librării de aplicații de vizualizare artificiala ( Computer Vision ) care sa poată fi folosită în interfațele grafice de către programatori, oferirea unei soluții low-cost pentru videoconferințe și pentru integrarea în jocurile de consolă și pe calculator([4]). În anul 2000 este lansată sub format Open Source librăria OpenCV alpha 3, astfel cod pentru librărie poate fi dezvoltat de comunitate. Astfel în prezent comunitatea are peste 14000 de membri care contribuie la proiectul OpenCV prin raportarea problemelor, aplicarea de patch-uri sau adăugarea de noi funcții.
Principalul avantaj al OpenCV este că e o librărie cross-platform, conținând API de nivel mediu și înalt , totalizând aproximativ 500 de funcții , care nu se bazează pe librării externe , având obiectele și funcțiile matematice proprii.
Librăria OpenCV e defapt alcătuită din mai multe librării integrate ([4]) într-un singur pachet:
CV – algoritmi legați de vizualizare artificială și procesarea imaginilor
CVAUX – conține funcții experimentale , variante alpha și beta precum și funcții auxiliare OpenCV
CXCORE – conține funcții de algebra liniară , de exemplu suport pentru funcții cu matrici, suport XML, funcții de desenare.
HIGHGUI – conține funcții pentru interacțiuni I/O media și de fereastră , citește/scrie filme în format .AVI, creează obiecte de tipul ImageBox
ML – conține funcționalitatea legată de Machine Learning
CvCam – conține module cross-platform pentru procesarea video și a streamurilor pentru camere digitale.
Fig. II.5. Structura librăriei OpenCV ([4])
Detecția obiectelor a fost pentru prima oară propusă de Paul Viola și după aceea înbunătățită de Rainer Lienhart. Detecția se face cu ajutorul unui element clasificator ( classifier – și anume o cascadă de clasificatori funcționând cu elementele unei funcții Haar ). Clasificatorul e ”antrenat” cu o mulțime de imagini a unui obiect, în cazul aplicației noastre fețe, care sunt scalate la acealeași dimensiune. Imaginile sunt împărțite în exemple pozitive, cazul în care imaginea este o față, și exemple negative, imagini aleatorii, care nu conțin fețe([5]) .
După ce un clasificator e antrenat, el poate fi aplicat unei regiuni de interes ( de aceiași dimensiuni cu imaginile de test ), astfel clasificatorul întoarce 1, dacă în regiune există probabilitatea de a conține obiectul căutat, altfel întoarce 0. Pentru a căuta un obiect în intreaga imagine, se parcurge împarte imaginea în regiuni și fiecare locație este verificată cu clasificatorul. Clasificatorul e astfel proiectat încât poate , cu ușurință să se redimensioneze pentru a căuta obiectul dorit la dimensiuni diferite, acest lucru este mult mai eficient decât redimensionarea întregii imagini. Așadar pentru a găsi un obiect de o mărime necunoscută, clasificatorul se rulează de mai multe ori la dimensiuni diferite.
Se folosește termenul de ”cascadă” pentru că clasificatorul final este compus dintr-o serie de clasificatori mai simpli , numiți etape, care sunt aplicate secvențial pe o regiune de interes până când una dintre etape e respinsă sau toate etapele sunt acceptate([4]) .
În cazul detecțiilor feței regiunile căutate sunt definite de diferența de contrast dintre ochi și obraji sau folosind mărimi de contrast scalate peste suprafața dată de nas și în jurul ochilor, astfel trăsăturile selectate sunt sortate în ordinea importanței lor, pentru a fi folosite în ”cascadă”. Viteza cu care trăsăturile sunt evaluate , e importantă deoarece algoritmul de detecție frontală a feței consistă din evaluare la scări diferite peste imaginea de intrare. Folosind acest algoritm detecția frontală a feței este posibilă în codiții în care intensitatea luminii variază, când este parțial acoperită sau ”zgomotul” de imagine este ridicat([5]) .
II.3. EmguCV
EmguCV este un container peste librăria Intel OpenCV, care permite chemarea de obiecte și funcții ce aparțin librăriei OpenCV din limbaje compatibile .NET([7]). Există o multitude de implementări peste OpenCV care să permită interoperabilitatea cu limbajul .Net, dintre ele însă amintim OpenCVdotNet, SharperCV și librăria oferită de Code Project, însă EmguCV este considerată cea mai completă și competitivă atât din punct de vedere al performanței cât și privitor la funcțiiledin OpenCv implementate, astfel librăria EmguCV este singură care oferă posibilitatea de algortmi inteligenți ( machine learning )([7]).
Dintre algortmii inteligenți oferiți de EmguCV amintim :
Clasificator Bayesian (Normal Bayes Classifier )
Algoritmul kNN – K-Nearest Neighbour
Vector Space Model
există mai multe implementări pentru învățarea artificială, dar aceștiatrei dau rezultatele cele mai competitive în cadrul librăriei EmguCV.
Algoritmi de clasificare sunt folositi pentru a grupa date multi-dimensionale în grupe (clusters) definite algoritmic. Aceasta metoda este utila pentru cuantificarea unor cantitati mari de informatie, fiecare grupa reprezentând mai multe puncte având caracteristici similare. Clusterele distincte sunt disjuncte([8]).
Analiza clasificarii consta dintr-o serie de algoritmi ce exploateaza mai multe euristici bazate în principal pe experienta noastra „vizuala” în gruparea punctelor în regiuni de puncte. În general, pentru a putea folosi un algoritm de clasificare, este nevoie de urmatoarele informatii:
distanta între punctele unui spatiu multidimensional;
strategia de alegere a punctului reprezentativ (adica a „centrului”) pentru orice
grupare de puncte;
distanta între doua grupe de puncte.
Teorema lui Bayes reprezintă un prim mijloc de a determina probabilitatea unui eveniment Ai (componentă a unei repartiții) în situația în care se stie că apariția acestuia este influențată de îndeplinirea unui alt eveniment independent B.Fiind date două evenimente A si B, se numeste “probabilitatea evenimentului A condiționat de evenimentul B” si se notează :([8])
probabilitatea ca evenimentul A să fie îndeplinit atunci când se stie că evenimentul B a avutloc. Înrelația de mai sus, valoarea Pr(AB) reprezintă probabilitatea ca evenimentele A și Bsă aibă locsimultan([8]). Teorema lui Bayes spune că fiind date evenimentele A1, A2, … , Ak, mutual exclusive, și evenimentul B dependent de acestea, se poate demonstra expresia :
([8])
Normal Bayes Classifier e un termen în statistica Bayesian care lucrează cu un simplu casificator probabilistic bazat pe teorema lui Bayes([8]). Acesta presupune absența sau prezența unei propietăți a unei clase nu este în legătura cu prezența sau absența unei alte propietați. Spre exemplu un fruct poate fi considerat a fi o portocală daca e portocaliu, rotund și are un diametru de aproximativ 10 cm. Deși aceste propietăți depind una de existența celălaltei, un clasificator Bayes naiv consideră că toate aceste propietăți sunt independente și contribuie la probabilitatea ca fructule e o portocală([8]).
În ciuda designului simplist și a presupunerilor simplificate , clasificatorii Bayes naivi se ridică peste așteptări în multe situații complexe reale. Avantajul unor astfel de clasificatori este dat de numarul mic de date pentru antrenament pentru a estima parametrii necesari clasificării.
Principul algoritmului kNN este clasificarea unui document prin găsirea documentului cel mai apropiat din setul de antrenament. Metodele care se bazează pe acest principiu sunt numite metode de ”învățare bazată pe memorie”([8]). Sunt folosite ponderile termenilor Tf și Idf, calculându-se similaritatea dintre exemplele de test și centroizii clusterelor. Ponderea asignată unui termen este o combinație a ponderilor sale într-o interogare originală și documentele considerate relevante și irelevante.În algoritmul de mai jos se folosește distanța Euclidiană pentru a determina similaritatea dintre două documente.
Algoritm([8]):
%intrare
K: numărul de vicini
X: paternuri de test
Y: etichetele claselor de test
z: patern nou.
%ieșire
l: eticheta prezisă a noului patern
pentru fiecare x in X
calculeaza distanța Euclidianăa lui z față de x
d(x) = distance(z,x)
;d e un vector ce conține distanțeletuturor x din X față de z
end;
;sortează patternurile lui X crescător față de d(x)
(sorted_d, index) = sort(X,d)
;sorted_d e lista de elemente a lui d sortată crecător,
;șiindex(i) e indexul înX al elementului idin sorted_d
neighbours = index(1:k);
;index(1:k) reprezintă primele k elemente din index
label_neighbours = Y(neighbours);
;Y(neighbours) sunt elementele din Y care au indexul egal cu al vecinilor
l = majority(label_neighbours);
;majority(label_neighbours) e clasa de vecini ce se repetă de mai multe ori în ; lista label_neighbours.
In cadrul ”Vector Space Model”, fiecărui document îi este atașat un vector de caracteristici, a cărui dimensiune este dată de numărul de atribute unice care se regăsesc în documentul din colecție([8]). Fiecare element al vectorului are o pondere care specifică importanța atributului în clasificarea documentului. De regulă, aceste atribute sunt extrase din document folosind metode de regăsirea a informației. Faza de extragere a termenilor care caracterizează un document este numită indexarea documentului. În faza de atribuire de ponderi pentru fiecare termen se stabilește semnificația în caracterizarea documentului. Aceste ponderi pot avea valorile 0 sau 1, indicând existența (1) sau nu (0) a termenilor in document([8]). De regulă, este mult mai raspândită folosirea frecvenței de întâlnire a termenului în cadrul documentului. Tf se folosește pentru a reprezenta frecvența de apariție a termenului în document, iar Idf reprezintă inversul frecvenței de întâlnire a termenului în întreaga colecție.
, unde k n este numărul de documente în care apare termenul, iar N este numărul total de documente. În etapa următoare trebuie aleasă o măsura de similaritate pentru calculul asemănării dintre două documente. Cea mai folosită măsură pentru similaritate este cea a coeficienților cosinus, care determină cosinusul unghiului dintre doi vectori de caracteristici. Alte măsuri utilizate sunt cele ale coeficienților Jaccard sau ale coeficienților Dice, ambele fiind normalizări ale potrivirii simple a coeficienților. Coeficienții Jaccard sunt măsuri de similaritate între seturi de atribute, si sunt definiți ca raport între numărul de elemente ale intersecției și numărul de elemente ale reuniunii setului de atribute : ([8]).
Distanța Jaccard, care determină diferență între seturile de test, este complementară coeficientului Jaccard si este obținută prin scăderea coeficientului Jaccard din 1:
([8])
Coeficienții Dice sunt măsuri de similaritate între seturi de atribute, si sunt definiți conform formulei:([8]).
Pe lângă acești algoritmi de învățare, librăria EmguCV mai are avantajul de a putea lucra direct cu clasa Image definită de doi parametri generici depth și color, reprezentând numărul de culori și adâncimea în biți a imaginii, de exemplu codul pentru a creea o imagine de tipul grayscale de pe 8 biți fără semn este :
Image<Gray, Byte> img = new Image<Gray, Byte> ( lungime, lățime) ;
astfel de parametri impedică interacțiunea dintre imagini de adâncime diferită, lucru foarte util în timpul programării, spre exemplu dacă se dorește a seta o valoare unui obiect cu o adâncime de 32 de biți cu culori BGR ( Blue Green Red – tipul din EmguCV ) într-un obiect definit ca și ”img” din exemplul de mai sus, se întâlnește o eroare la compilare, prin care se atenționează atribuirea ilegală([7]).
Un alt avantaj al EmguCV este existența unui obiect garbage collector care se ocupă automat de managementul memoriei, astfel la când nu mai sunt referințe la un obiect Image , se cheamă metoda Disposed , care dealocă întreagă structură a obiectului. Cu toate acestea timpul de colectare a deșeurilor nu este garantat , astfel că este recomandat pentru obiectele mari să se folosească manual metoda Dispose ( ) , pentru a dezaloca obiectul, alternativ se poate folosi o structură .NET using.
De asemenea EmguCv oferă serializare avansată pentru obiectul Image și ca un avantaj asupa librăriei OpenCV oferă posibilitatea folosirii uneltei de Intellisense din editorul Visual Studio, fiecare funcție având o definiție text pentru parametri și pentru output.
Dacă nu se dorește folosirea clasei Image dezvoltată în OpenCV se poate folosi P/Invoke pentru a accesa direct funcții OpenCV, de exemplul apelul .Net :
IntPtr image = CvInvoke.cvCreateImage(new System.Drawing.Size(400, 300),CvEnum.IPL_DEPTH.IPL_DEPTH_8U, 1);
este echivalent cu apelul C :
IplImage* image = cvCreateImage(cvSize(400, 300), IPL_DEPTH_8U, 1);
EmguCV oferă o funcționalitate puternică, inaccesibilă până acuma în .NET pe parte de procesare imaginilor, fiind produsă sub licență open source și având o comunitate care participă activ la dezvoltarea și tratarea posibilelor probleme detectate, este considerată o librărie competitivă și stabilă.
II.4. Microsoft DirectX
DirectX este o colecție de API-uri care împreună pot gestiona cereri de nivel scăzut al hardware-ului specializat în scopul folosirii hardware-ului la performanțe maxime în prelucrarea multimedia, în jocuri și în redări video. Pachetele inițiale erau numite Direct3D,DirectDraw,DirectMusic,DiractPlay, DirectShow, iar în timp Microsoft le-a denumit generic pe toate DirectX.
Librăria Direct3D , este librăria care se ocupă de prelucrările 3D, fiind folosită pentru dezvoltarea aplicațiilor 3D pentru plaforma Windows, Xbox și Xbox360. Aplicațiile dezvoltate cu ajutorul acestei librării fac parte dintr-o gamă largă de produse, variind de la jocuri până la aplicații CAD/CAM de proiectare([9]).
Pachetul DirectX pentru dezvoltatori se distrubie sub forma unui SDK ( software development kit ), în care conține pe lângă librării și exemple de folosire a codului, împreună cu codul sursă a acestor exemple. Librăriile DirectX sunt sub formă de .dll pentru că codul sursă este propietatea Microsof, iar aplicație este considerată closed-source software.
Componentele care alcătuiesc API-ul DirectX se împart în câteva mari categorii ([9]):
DirectX Graphics , care la rândul ei este împarțită în :
DirectDraw , librărie care desenează grafică 2D, considerată depășită, dar pentru a asigura compabilitatea înapoi, această opțiune rămâne inclusă în pachet.
Direct3D ( D3D ) : librăria folosită pentru rendarea 3D în aplicații în care performața este un element critic.
DXGI : este o componentă utilizator din Windows Vista sau Windows 7, care are posibilitatea de a enumera monitoarele, modurile de vizualizare, formatul bufferelor și modul în care resursele sunt împărțite procesorului, atât aplicațiile DirectX cât și OpenGL interacționează cu Windows Vista prin DXGI.
Direct Input, folosit pentru interfațarea cu dispozitivele de input ca mouse-ul,tastatura sau controllere de joc, este considerata o librărie învechită începând cu versiunea 8 a DirectX locul său fiind luat de catre XInput și sistemul de comunicare cu mesaje VM INPUT pentru tastură și mouse.
DirectPlay este librăria care face posibilă comunicarea prin rețea, la fel ca DirectInput este considerat depășit odată cu apariția lui DirectX 8, locul său fiind luat de către tehnologia Games for Windows – Live.
DirectSound este librăria care permite redarea sunetului, ea conține și o componentă numită DirectSound3D folosită pentru redarea sunetelor 3D.
DirectX Media reprezintă o colecție de obiecte ce permit rendarea multimedia atât prin DirectShow cât și prin DirectAnimation pentru grafică 2D/3D. Acestă librărie poate oferi și funcționalitate avansată pentru interacțiunea web.
Istoria DirectX a început odată cu lansarea sistemului de operare Windows 95, când odată lansat, sistemul de operare era văzut inferior predecesorului MS-DOS pentru activitatea de gameming([9]). MS-DOS oferă acces direct la periferice ca plăci video, tastatură, mouse , plăci de sunet și alte părți ale sistemului, pe când Win95 oferă o protecție a memoriei și astfel restricționează accesul la aceste părți. Astfel din dorința de a le da mai multă putere programatorilor, Microsoft a decis să ofere rapid o soluție pentru acest tip de acces, soluție pe care echipa de producție au numit-o eventual DirectX.
Prima apariție numită Windows Game SDK , a fost lansată după noua luni de producție în Septembrie 1995, astfel permițând oricărei versiuni de Windows începând cu Win95, să poată oferi performanță în rendare și multimedia([9]).
Datorită varietății de plăci video, plăci audio și a celor de bază, s-a decis pe lângă testarea individuală facută de Microsoft pe un număr de configurații și distribuirea de pachete de test producătorilor de hardware pentru a se asigura ca viitoarele produse hardware sunt compatibile DirectX.
Deși înainte de DirectX, Microsoft a folosit OpenGL în platforma WindowsNT, cerințele de sistem cerute de OpenGL, au făcut ca acest produs să fie folosit doar de utilizatorii specializați, care își permiteau hardware compatibil OpenGL. În timp odată cu evoluția industriei de jocuri, OpenGL a reușit să devină o alternativă pentru DirectX, cele două produse fiind în ziua de azi concurente, cu toate că echipa care a dezvoltat o mare parte din DirectX, este responsabilă și cu suportul pentru funcționalitatea de OpenGL, astfel cazurile în care o funcționalitate suportată de DirectX și nesuportată de OpenGL era integrată în OpenGL chiar de echipa dezvoltatoare DirectX([9]).
Versiunile DirectX aduc fiecare câte un nou element esențial făcut pentru a oferi o dezolvarea mai ușoară, performanță sau noi facilități care să permită un avans în domeniul graficii pe calculator. Versiunea cea mai recentă este DirectX 10.1, versiunea 11 fiind fixată a se lansa chiar în iulie 2009, iar schimbările produse de această versiune intruduc conceptul de rendare multithreading, tessellation – permiterea afișării mai multor poligoane vizibile pentru modele poligonale cu detalii scăzute, un efect de mozaic peste un plan – și shadere computaționale, precum și noi metode de compresie a texturilor([10]).
Odată cu lansarea Windows Vista a fost necesară trecerea la un nou capitol în librăria DirectX, astfel că DirectX 10 este compatibil doar cu Windows Vista și versiunile ulterioare a sistemului de operare Windows, precum Windows 7. Interfețele vizuale din Vista sunt posibile în mare măsură datorită librăriei DirectX, fiind cerută o placă video compatibilă minim cu DirectX 9([9]). Acest lucru a făcut din Vista un candidat mult prea pretențios pentru piața sistemelor de operare, fiind considerat un sistem de operare care necesită investiții dacă se dorește trecerea de la un sistem de operare anterior .
II.5. Circuitele de tipul TX2 și RX2
Radio controlul sau R/C reprezintă folosirea de semnale radio pentru a controla un dispozitiv. R/C se referă în general la controlul de machete de o telecomandă portabilă de mici dimensiuni.
Ideea de control la distanță a fost prima oară demonstrată de Tesla în cadrul unei demonstrații în anii 1898, reușind să controleze o barcă prin semnale radio, cu ajutorul unor circuite specializate, iar în acest mod reușind să dea start cercetărilor în domeniu([14]).
Prima aplicație de larg consum a controlului teleghidat a fost în anii 1950 , iar machetele teleghidate erau ansamblate de utilizator, fiind comercializate doar kituri de de transmisie receptie, cu necesități de baterii de dimensiune considerabile, astfel machetele terestre teleghidate era ceva mult mai obișnuit ca machetele gen avion. Un alt mare dezavantaj a acelor circuite era banda de transmisie, în cazul în care mai două modele intrau unu în raza de acțiune a celuilalt, se întâmpla frecvent ca telecomanda unui model să controleze amândouă machetele sau doar macheta celuilalt utilizator([14]).
Odată cu apariția tranzistorului, necesitățile de putere a aparatelor ce efectuează transmisia și recepția au scăzut, iar frecvențele de transmisie au început să fie standardizate, trecând peste benzile de 27MHz și ajungând în zilele noastre să opereze în medie pe frecvente de 40Mhz.
Toate aceste lucruri au dus la apariția unei comunități de hobiști, comunitatea care mai târziu a dus la naștere unei competiții comerciale, care există și se manifestă și astăzi în încercarea de a realiza cele mai performante machete , din punct de vedere al puterii machetelor, a distenței de transmisie și a consumului de operare.
Majoritatea modelelor de pe piață folosesc circuite TX2 / RX2 dezvoltate de compania RealTek. Aceste circuite, datorită simplității de programare și de folosire au reușit să creeze o influzie pe piața de machete, facând machetele teleghidate, gata asamblate și la cutie disponibile în majoritatea magazinelor de jucării([13]).
TX2/RX2 a fost construit pentru mașini teleghidate, astfel că este un circuit CMOS LSI , cu funcții de auto-oprire. Circuitul are în principal 5 funcții de control, care permit direcționarea machetei: stânga, dreapta, față , spate și turbo.
Fig. II.5 Transmisia pentru TX2 ([13])
Pentru transmise se folosește circuitul TX2 , circuit care prin apăsarea unui buton pe telecomandă, să realizează o legătura pe pinul corespunzător funcției descrise de buton, de exemplu pentru funcția de față([14]).
Funcțiile mapate pe pini sunt următoarele ([14]):
Prin apăsarea butonului este începută o transmisie către chipul de recepție prin pinii 7 sau 8în funcție de modul în care a fost selectată ieșirea. Transmiterea se face printr-o secvență bine determinată care identifică unic o funcție. Formatul de ieșire la codare este dat de următoarea schemă, astfel funcții le sunt mapate conform W1 și W2, având cuvinte de start și stop
Fig. II.6. Formatul de bit la ieșirea codată pentru TX2 ([13])
Formatul unei funcții este următorul :
W2 W2 W2 W2 (n) x W1 W2 W2 W2 W2 (n) x W1 W2 W2 W2 W2.
Valorile lui n determină RX2 să decodeze funcțiile transmise , astfel :
pentru n=4 , se va citit terminarea transmisiei
n=10 , înseamnă înainte
n=16 , înainte și turbo
n=22 , doar turbo
n=28 , înainte, turbo și stânga
n=34 , înainte, turbo și dreapta
n=40 , spate
n=46 , spate și dreapta
n=52 , spate și stânga
n=58 , stânga
n=64 , dreapta
Decodarea se realizează la nivelul RX2 , iar în urma decodării se controlează motorașele machetelor care îi dau cele patru direcții .
TX2/RX2 mai are avantaje specifice precum o arie de operare destul de largă 2.4V – 5V , consum redus în modul stand-by și funcție de auto-închidere pentru partea de transmitere, iar număr de componente externe necesare este mic.
III. Proiectarea aplicației și modul de interacțiune dintre tehnologii
Acest proiect va implementa un algoritm de urmărire a mișcării capului unei persoane și va folosi ieșirea produsă de acest algoritm pentru a controla un caracter virtual într-un mediu virtual, de asemenea aceste mișcări ale capului pot fi utilizate pentru a controla o machetă teleghidată.
Tehnologiile folosite în acest proiect au fost alese în urma umătoarelor criterii ( ordinea e neesențială ) :
tehnologii care să permită finalizarea proiectului într-un timp util
o interacțiune cât mai simplă între modulele aplicației
abilitățile personale de programare
sistemul de operare al utilizatorului
O analiză a acestor criterii a dus la alegerea limbajului .NET C#, împreună cu wrapperul EmguCv, DirectX pentru .NET și un port serial.
Astfel aplicația e scrisă în intregime in limbajul .NET C#, motivația din spatele acestei alegeri este una personală, preferând C# peste C++, deoarece codul este mult mai intuitiv, există posibilitatea folosirii modului intellisense, fiind la prima implementare cu EmguCV și DirectX pur ( fără librării third-party , precum Ogre3D care să permită automatizarea unor pași ) am considerat intellisense o funcționalitate importantă.
EmguCV a fost ales datorită funcționalității avansate oferite pentru .NET față de alte implementari OpenCV peste .NET, de exemplu EmguCv oferă obiecte avasate pentru toolbox-ul Visual Studio, specifice OpenCV, care au o performanță mult mai mare față de obiectele standard ca ImageBox și Image. EmguCv este singurul wrapper pentru .NET care oferă, momentan, aceste obiecte.
DirectX a fost încorportat în această aplicație pentru a creea un mediu virtual , unde avatarul să poată fi redat. DirectX a fost prima opțiune pentru rendarea grafică datorită ușurinței de implementare în limbajul .NET, un SDK fiind distriubit chiar de către Microsoft, dar și datorită faptului că pentru a dezvolta în OpenGL cu .NET C#, este necesar un nou wrapper cu mult inferior față de ceea ce DirectX oferă.
Pentru a controla macheta teleghidată, am ales să folosesc o machetă a unei mașiunțe care folosește circuite RX2/TX2 pentru comunicare dintre telecomandă și mașina propriu zisă, de asemenea mașinuțaa fost aleasă ca să poată răspunde la comnezile transmise într-un timp acceptabil, fiind observate machete la care timpii de stop și start aveau o anumită întârziere între apăsarea butonului și efectuarea comenzii. Acest criteriu de selecție a mașinuței este important deoarce se consideră ca o anumită întârziere software va fi întrodusă odată cu prelucrarea imaginii.
III.1. Descrierea aplicației
Când aplicația pornește, își caută un device de captură , în cazul în care nu este găsit aplicația se termină cu un mesaj de eroare, dacă însă se găsește un webcam e inițializat obiectul de captură și se adaugă un eveniment la form, care se va executa constant. Odată inițializat formul, se trece la pregătirea mediului virtual prin instanțierea clasei D3DManager, în care se specifică obiectul în care se va face randarea 3D, împreună cu dimensiunile sale. Odată trecută aplicația de partea de inițializare, captura de la webcam este constantă, iar algoritmul de detecție al feței este aplicat fiecărui frame citit, iar în cazul în care este detectată o față, algoritmul calculează ce mișcarea trebuie sa efectueze avatarul, aplică acea mișcare și rendează scena.
În cadrul interfeței se prevede un control de tip checkbox , care să permită controlul machetei printr-un port serial care transmite date direct în telecomandă, iar în funcție de mișcările capului să permitămișcările pe care și avatarul le poate efectua.
Aplicația funcționează după principiul orientat obiect, astfel pe lângă clasa principală există clase care reprezintă obiecte, cu metode pentru a administra instața DirectX, cu mai multă ușurință ( clasa D3Dmanager ), pentru a putea folosi transformări ale vertexurilor și propietăți de genul culorii vertexului se poate aplica clasa CustomVertexFormat ,iar o clasă denumită DreptunghiFață se poate folosi pentru a ușuramemoria în timpul execuției ( prin folosirea propietăților clasei pentru a reține doar informațiile necesare reținerii poziței feței în frame-ul anterior, de exemplu poziția X și Y în cadrul imaginii, precum si lățimea și lungimea feței detectate ) toate aceste informații se folosesc în determinarea mișcărilor avatarului și a machetei prin calcularea pozițiilor X și Y și a dimensiunilor relative față de un deptunghi de control.
Probleme de dezvoltare care se prevăd încă din acest stadiu incipient se referă în mare măsură la modul în care aplicația va rula, dacă va fi cursiv sau nu. Părțile cele mai stresante pentru calculatorul utilizatorului se prevăd a fi partea de prelucrare a imaginii împreună cu detecția feței și transmiterea informațiilor serial. Pentru a preveni o parte din aceste întârzieri, se pot folosi de exemplu pentru detecție imagini de dimensiuni reduse, dar care pot creea detecții fals-pozitive.
Interfața aplicației este simplu realizată, având un număr minim de controale :
Fig. III.1. Fereastra principală de interfață a aplicației
În aplicație e prezent un singur form, care conține un obiect EmguCV pentru afișarea frame-urilor citite de la webcam, împreună cu două etichete care afișează poziția X și Y a obiectului reținut în urma aplicării secvenței de detecție. Mediul Virtual este afișat într-un panou simplu, instanței DirectX îi este suficient pentru a putea afișa partea de 3D. CheckBox-ul după cum am mai menționat este necesar pentru a inițializa obiectul care va realiza transmisia pe un port serial pentru a controla macheta în funcție de mișcările capului.
Este de menționat faptul ca obiectul EmguCV.ImageBox deține un meniu de context ( se accesează prin click dreapta pe obiect ) care permite operații adiționale ale controlului peste imaginea capturată, acestă funcționalitate aplică în mare măsură transformări matematice peste imaginea capturată, de exemplu operații de transformări extrude, blur, min, maxim fiind posibile și rotiri ale imaginii, conversii la alte tipuri de obiect Image<,>.
Forma avatarului este încărcată dintr-un fișier de format .x, fișier de grafică care poate fi realizat în diferite programe de proiectare 3D și exportat pentru a putea fi folosit în cadrul aplicațiilor DirectX. În această aplicație modelul .x folosit este distribuit gratuit cu SDK-ul DirectX.
Protocolul de comunicare serială se realizează printr-un tip specializat .NET, denumit generic SerialPort. Acest obiect permite setarea vitezei de transmisie, a numărului de biți pe care se realizează transmisia, dacă să se realizeze sau nu controlul parității, mărimea bufferului de input și mărimea bufferului de output, împreună cu alte propietăți. Acest obiecte sunt inclus într-o clasă de comunicare, clasă care își pornește transmisia odată cu bifarea checkboxului și termină acea transmisie în momentul închiderii aplicației sau la debifarea checkboxului.
Odată terminată aplicația toate obictele sunt eliberate din memorie, porțile de comunicare închise , iar webcam-ul folosit devine inactiv dinou.
III.2. Diagrama funcțională a aplicației
Funcționarea aplicației poate mai ușor descrisă printr-o diagramă care prezintă modul în care circulă informația într-un ciclu de viață a aplicației.
Fig. III.2. Diagrama funcțională a aplicației
IV. Componente specifice ale aplicației
Dezvoltarea software practică oferă o gamă variată de probleme față de conceptele teoretice ( spre exemplu : funcții care returnează tipuri ce nu pot fi folosiți înainte de convertire , astfel, în practică, este probabil ca lucrurile simple să devină complicate sau o soluție simplă a unei probleme să ducă la folosirea unui număr mare de resurse, resurse care nu sunt disponibile tutor sistemelor de calcul.
În cursul realizării aplicației s-au întâlnit diverse probleme, iar soluțiile acestor probleme vor fi abordate în subcapitolele ce urmează.
Clasa principală folosită în program, este cea care realizează instanțierea ferestrei de interfață, care la rândul său inițializează obiectul de captură oferit de EmguCV, bazat pe obiectul original provenit din OpenCV. Obiectul de captură reprezintă unul dintre cele mai importante obiecte din toată aplicația, astfel orice eroare apărut pe partea de captură, duce automat la asișarea excepției care a provocat eroarea și implicit la terminarea aplicației.
if (_capture == null)
{
try
{
_capture = newCapture();
}
catch (NullReferenceException excpt)
{
MessageBox.Show(excpt.Message);
Application.Exit();
}
}
Codul de mai sus reprezintă inițializarea obiectului ”_capture”, declarat ca variabilă publică pentru fereastă de interfață. Pentru că imaginea capturată de la webcam este inversată orizontal este necesară setarea unui flag care să idice dacă ,pe viitor, toate imaginile vor fi inversate automat la captură, acest lucru se realizează tot în partea de inițializare conținută de către formul de inițializare.
Pentru a nu permite ferestrei de interfață să se inchidă se creează un ciclu care în cazul în care există inactivitate legată de mesaje între ferestre se semnalează către eveniment onIdle, iar în cadrul acestui eveniment se chemă toate celălalte funcții de detecție, rendare și mișcare a machetei.
Programul principal continuă cu inițializarea unui obiect D3DManager care în esență este o clasă ce permite controlul asupra întreg mediului virtual. Inițializarea este făcută prin apelarea constructorului care primește ca parametri , un control, în care această fereastră va efectua rendarea, înalțimea, lățimea ferestrei și o variabilă booleană care indică dacă rendarea se va face pe tot ecranul sau nu.
În cadrul constructorului clasei D3DManager parametri de inițializare primesc valori prestabilite, precum și parametri din argumentele funcției. Variabilele au fost alese astfel încât mediul virtual să funcționeze cursiv și simplu.
Ca o observație este necesar a specifica, o problemă întâlnită a cărei rezolvarea a dus la eliminarea unui eveniment DirectX, care nu era necesar, dar care provoca o excepție în rularea aplicației și anume evenimentul de AutoResize ( auto scalare ), eveniment care la dimensionarea ferestrei ”resetează” obiectul Device ce aparține de D3DManager, obiect care în esență e cel ce administrează resursele folosite de aplicație. Evenimentul este anulat prin setarea unui flag care nu permite propagarea detecției că mărimea spațiului de rendare a fost redimensionat.
Variabilele de vizualizare a mediului virtual trebuiesc și ele inițializate fiind nevoie de setarea unei matrici numite viewMatrix și projectionMatrix, care permit setarea puncului de vizualizare ( un punct în spațiu de unde se privește scena ) și alte variabile de proiecție ca unghiul de vizualizare și intervalul pe axa Z la care se realizează operația de culling.
Vector3[] viewVectors = {
newVector3(1, 1, 100),
newVector3(0, 0, 0),
newVector3(0, 20, 0)};
d3dManager.setViewMatrix(viewVectors);
publicvoid setProjectionMatrix()
{
setProjectionMatrix(3.141592654f / 4.0f, parameters.BackBufferWidth / (float)parameters.BackBufferHeight, 0.5f, 100.0f);
}
publicvoid setProjectionMatrix(float fov, float aspectRatio, float zClose, float zFar)
{
Matrix projectionMatrix = Matrix.PerspectiveFovLH(fov, aspectRatio, zClose, zFar);
device.SetTransform(TransformType.Projection, projectionMatrix);
}
Programul principal asignează și un mod de tratare a evenimentului de KeyUp, al ferestrei de interfață, eveniment care realizează citirea tastelor apăsate când fereastră de interfață este selectată, acest eveniment fiind necesar pentru o funcționalitate a aplicației care permite blocarea poziției avatarului în mediul virtual, pentru repoziționarea utilizatorului, permițând astfel o arie mai mare de deplasare, într-o direcție, a avatarului . Avatarul este și el inițializat cu o clasă denumită generic clsMesh, clasă care primește ca referință obiectul D3DManager și adaugă acel obiect dintr-un fișier .X mediului virtual, locația fișierului este și ea specificată în constructorul clasei clsMesh.
Odată cu terminarea inițializărilor , aplicația așteaptă intrarea pe evenimentul onIdle sau KeyUp, al ferestrei care marchează începerea rutinelor de detecție, randare și mișcare a machetei (mișcarea machetei este opțională și se inițiealiează prin setarea unui check box de pe interfață ).
IV.1. Detecția feței
Detecția feței este o operație ce ține exclusiv de librăria EmguCV împreună cu un fișier xml de date, care permite algoritmului Haar folosit să poată identifca corect o față din cadrul imaginii capturate.
Astfel că odata începută operația de tratare a evenimentului onIdle, se extrage imaginea din obiectul de captură. O problemă legată de performață apare în acest punct deoarece, pentru că algoritmul de detecție este lent am ales utilizarea unei imagini reduse și astfel este necesară direct extracția din obiectul de captură a imaginii reduse, prin metoda QuerySmallFrame() a obiectului.
Algoritmul de detecție are nevoie de imaginea în forma alb-negru și nuanțe de gri, deoarece acesta este formatul în care datele din fișierul xml au fost obținute, astfel imaginea este procesată printr-o funcție de egalizare a histogramei, adică de normalizare a intensitații luminii și mărirea contrastului. Imaginea astfel opțiuntă este supusă unei detecției Haar în cascadă, cu ajutorul funcției EmguCV DetectHaarCascade. Detecția Haar returnează un matrice de dreptunghiuri, ordonate după scalări diferite, reprezentând în cazul nostru fețe umane. Dacă cel puțin o față a fost detectată, matricea se prelucrează o singură dată cu scalarea cea mai mică. În timpul procesării, se filtrează o singură față din colecție, fața având cele mai mari mărimi, lungime și lățime, pentru a spori performanța, am ales compararea produsului dintre lungime și lățime.
O variabilă locală reține cea mai mare față detectată și se desenează un dreptunghi in jurul acesteia direct pe imaginea din captură, care a fost dată spre afișare în obiectul de pe interfață ImageBox, controlul asignat pentru redarea imaginilor capturate. După care fața cea mai mare este reținută într-o variabilă globală , prin memorarea poziției sale X,Y precum și a lungimii și lățimii, coordonate ce mai târziu vor fi folosite la mișcarea avatarului în mediul virtual și a machetei teleghidate. Vechilde coordonate ale variabilei globale sunt și ele reținute pentru a asigura o mișcare fluentă a avatarului, lucru ce ajută la filtarea variaților dintre cadre.
Problema fiind că se poate considera în detecție ca deși nu a existat nici o mișcarea a capului, dreptunghiul detectat în jurul capului să aibe o lungime și/sau o lățime mai mare, lucru care ar determina o mișcare a avatarului, dar prin întroducerea unor valori limită în funcție de valorile anterioare se poate fixa un spațiu de eroare, care nu va determina mișcări ale avatarului.
Codul detecției este atașat în Anexa 1. Controlul în funcție de dreptunghi a fost gândit în așa fel încât o apropiere de webcam, să facă avatarul să înainteze în mediul virtual, o depărtarea să facă avatarul să se apropie de punctul de vedere, mișcările stânga-dreaptă rămân neschimbate.
O reprezentare a modului în care a fost gândit controlul se poate observa în desenul de mai jos :
Fig. IV.1. Axele folosite pentru mișcarea avatarului din lumea reală
Axele folosite pentru mișcarea avatarului se pot observa cu ușurință fiind în acelși format cu axele folosite de librăria DirectX, astfel permițând ca mișcarea să fie intuitivă.
În continuarea, în cadrul aceluiași eveniment onIdle, device-ul din D3DManager, începe rendarea scenei și efectuarea transformărilor asupra scene.
IV.2. Rendarea grafică
Partea de rendare grafică trebuie efectuată dupa inițializarea scenei, inițializare care e efectuată cu obiectul manager DirectX, prin device.BeginScene( ). Odata începută scena, se desenează cu ajutorul clsMesh avatarul și se apelează funcția rendeaza( ) , care va efectua transformările asupra matricii de mediu și anume o translație față de punctele X și Y , pe axele x și y. La matricea rezultantă se adună matricea de scalare, matrice rezultantă în urma operației de scalare efectuată pentru variabilele Height și Width.
În urma acestor operații, funcția render își încheie execuția și revine în funcția care tratează evenimentul de onIdle, se închide scena și se trimite către display-ul obiectului Device din D3DManager, obiect inițializat la începutul programului, conținutul următorului buffer prezent în conținutul de buffere ce aparține aceluiași obiect Device.
Probleme întâlnite în această partea a aplicației au determinat crearea unei clase de inițializare și redare a unui Mesh. Apariția clasei de management pentru obiectul Mesh, a ușurat testarea și desenarea elementelor, înainte fiind necesar pentru fiecare obiect, mai exact grup de vertex-uri a le specifica într-o ordine de densenare, pentru ca funcția de Device drawPrimitives să le poata face în ordine, un exemplu în acest sens este desenul unui simplu cub, problema apăre nu în momentul desenării ci în momentul alegerii modului în care se face desenul.
Un cub fiind format din 6 fețe și are 8 vertexuri definite, spre exemplu numerotate de la 0 la 7, până și alegerea modului celui mai popular de desenare , TriangleStrip, în care se desenează tringhi cu triunghi , face ca operația de desenare să fie formată din 6 x 4 vertexuri , 4 vertexuri pentru definirea fiecărei fețe. O combinație posibilă ar putea fi formată din fețele :
0 – 1 – 2 – 3
1 – 4 – 3 – 6
5 – 4 – 0 – 1
4 – 5 – 6 – 7
5 – 0 – 7 – 2
2 – 3 – 7 – 6
Fig. IV.2. Cub 3D
IV.3. Transmiterea mișcărilor către macheta teleghidată
Transmiterea se face de către o clasă specializată numită transmisie, în esență transmisia se realizează prin intermediul unui port serial, al cărui nume este setat la bifarea checkbox-ului pentru controlul machetei din fereastră de interfață, odată bifată pe ecran apare o fereastră de tip dialog care îi cere utilizatorului să întroducă numele portului serial ( Anexa 1 , fig. 1 ) pe care urmează a se efectua transmisia, odata selectat portul, se apasă butonul de OK, se deschide portul de comunicare și se începe o transmisie de test care face macheta să înainteze și să vină înapoi în aceaiași direcție.
Pentru aplicație am ales o machetă a unei mașinuțe de producție Dikie Toys , care să conțină pentru chipuri RX2/TX2, pentru care partea de transmisie să poată fi simulată și transmisă prin cablul serial.
Probleme întâlnite în cadrul acestei părți din dezvoltarea aplicației, au făcut dezolvarea clasei de transmisie o necesitate, pentru început, odată achiziționat modelul de machetă și prin testarea telecomenzii, am observat ca chipul de transmisie este o reproducție a originalului TX2/RX2 și astfel s-a ajuns în situația capturării cuvintelor transmise de chipul de pe telecomandă într-un program gen hyperterm.
Odată dezvoltată clasa de transmisie, folosirea acesteia este intuitivă, facând din aplicație un mod ușor de a manevra macheta, cu mișcări de apropiere se face mașinuță să înainteze , iar în funcție de direcția apropierii, stanga – mijloc – dreapta , mașinuța fie efectuează o ușoară curbă la stânga, fie o usoară curba la dreapta, sau înaintează simplu. Controlul pentru spate este asemănător, ceea ce face ca mașinuța să se poată deplasa în toate cele șase direcții pe pe care le permite si telecomanda acționată din butoane. Am considerat necesară alocarea unei zone neutre pentru toate direcțiile, zona care să fie considerată poziția de origine, în funcție de care macheta sa efectueze primele mișcări.
Mișcările sunt efectuate continuu, până când utilizatorul intră în zona neutră , fiind astefel posibil un control avansat asupra machete, de exemplu dacă utilizatorul rămâne în zona ”înainte stânga” o perioadă de timp, mașina va efectua un cerc complet, reușind să revină în poziția inițială.
O reprezentarea a modului de control pentru cele șase direcții este redată mai jos :
Fig. IV.2. Zonele de interes pentru controlul machetei
O posibilă elaborare a acestei părți s-ar putea face schimbând motoarele ce acționează macheta, cu motoare pas cu pas și a chipurilor de transmisie recepție , toate acestea, pentru a putea acționa și asupra unghiului de întoarcere, lucru imposibil pentru modelul de față din cauza limitațiilor tehnice.
V. Posibile aplicații ale soluției
Această soluție oferă un model pentru în viitor, în cazul perfecționării librăriilor sau a folosirii unei librării de antrenament mai complexe, pentru aplicații de tipul control unui parametru sau în cazul persoanelor cu dizabilități pentru a putea interacționa cu mașini complexe care le-ar putea oferi un loc de muncă.
De exemplu o aplicație de control al unui parametru ar putea supraveghea zonele dintr-o grădină botanică pentru a detecta vizitatorii care nu respectă regulile de perimetru și se apropie excesiv de exponate sau chiar le deteriorează, astfel de comportament ar putea fi detectat și filmat în timp ce se petrece, fără supraveghere umană și semnalat auditiv, prin identificare în funcție de culorile hainelor cu care vizitatorul e îmbrăcat, că a depășit perimetrul admis și rugat să părăsească zona interzisă sau în cazul în care a deteriorat un exponat, să își păstreze poziția până la sosirea unui om de ordine, care să evalueze situația.
Un alt caz care ar putea fi aplicat ar fi cel în care este implementată o librărie de comportamente considerate suspecte, iar în funcție de imaginile captate într-o mulțime , să zicem într-un aeroport, să evidențieze pentru personalul responsabil cu securitatea conturul celor considerați suspecți, pentru ca aceștia să poată efectua un control amănunțit.
Astfel de aplicații ar putea fi considerate pe viitor pentru că ele elimină problemele legate de intimitate a oamenilor nevinovați – sau care nu trezesc suspiciuni – deoarece imaginile video nu sunt analizate de alți oameni ci de calculatoare, care ,pentru moment, nu este interesat de altceva decât comportamentul cu care a fost antrenat să-l observe.
VI. Aplicații similare
În cadrul evenimentului E3 2009 , mai multe companii din zona de gamming au prezentat pe piață produse prin care omul este capabil să interacționeze cu un caracter virtual atât prin mișcările corpului cât și prin interacțiuni vocale.
Astfel de proiecte aparțin companii lor Sony și Microsoft ( divizia XBox ), și apar ca un răspuns la controlul lasat pe piață de compania Nintendo cu ocazia lansării consolei WII în anul 2006.
VI.1. Microsoft XBOX – Project Natal
Reprezintă în esențăun tip de gamming fără a avea un o manetă de control pentru consola de Xbox360. Aparatul care se atașeajă la consolă este format dintr-o mulțime de senzori aplicați în aceiași cutie orizontală amplasată peste sau sub dispozitivul de vizualizare. Senzori foloșiti sunt :
cameră digitală
senzor de adâncime
o mulțime de microfoane
un procesor customizat peste care rulează soft propietar
Acești senzori reușesc să ofere captură 3D a întregului corp, recunoaștere facială și vocală.Senzorii aparatului denumit ”Project Natal” reușete să implementeze conceptul de localizare acustică.
Senzorul de adâncime este în esență un proiector de lumină infraroșu și senzor monocrom CMOS, care îi permit aparatului să vădă locația 3D indiferent de condițiile de lumină în care este utilizat([11]). Locația 3D este posibilă datorită camerei ce funcționează după principiului Time-of-Flight, cameră care emite pulsuri de lumină de intervale precise reușind astfel să iși dea seama, printr-o măsurarea timpului de în care lumina se reflectă, de distanța la care se află un pixel din imaginea capturată. Raza de detecție 3D fiind ajustabilă, se poate mapa camera în care utilizatorul va folosi aplicația și eventualele obstacole întâlnite pe drum. O imagine capturată folosind principul descris se poate vedea mai jos.
Fig. V.1. Imagine capturată cu o cameră TOF ([11])
Tehnologia folosită de Microsoft a fost pentru prima oară implementată în proiectul ZCam, proiect care mai târziu a fost cumpărat de Microsoft împreună cu compania producătoare, iar rezultatul obțiunt se crede a fi Project Natal ([11]).
Punctul forte al aplicației este considerat a fi maparea pe schelet a mai multor utilizatori find posibilă astfel urmărirea chiar și a structurii unui deget, în funcție de distanța la care se află utilizatorul de cameră. Numărul maxim de puncte de interes este de48 iar viteza cu care Project Natal este capabil să urmărească mișcările este de 30 Hz ([11]).
Jocurile folosite în demonstarea acestor concepte, cum ar fi un model interacțiunea cu o minge virtuală care trebuie lovită de un perete folosind părți ale corpului care să dea direcția de deplasare precum și viteza ( un joc de tipul BreakOut ), demonstrează abilitatea uimitoare de a urmări întreg corpul într-un spațiu 3D, extensiile unui astfel de control variind de la practicarea unui sport ca boxul cu un adversar virtual până la realizarea de animații în aplicații ca 3D Studio Max, în care punctele de interes să fie mapate software fără alte dispozitive exterioare.([11])
Pentru moment data de lansare nu a fost confirmată, deși tehnologia a avut de demonstrații televizate, precum apariția în prime time-ul american în cadrul emisiunii”Late Night with Jimmy Fallon”. Ultimul semestru din 2010 reprezintă pentru mulți o posibilă perioadă de lansare.
VI.2. Sony EyePet
EyePet este un joc pentru consola Sony PS3, care se folosește de tehnologia PlayStation Eye ( o cameră digitală) pentru a interacționa cu personaje virtuale ce sunt generate pe baza principiului de augmented reality ( combinarea elementelor virtuale în cadrul imaginilor capturate în timp real, spre exemplu de la o cameră video )([12]).
Folosirea EyePet determină apariția unei creaturi, pet, care pare să fie conștientă de mediul său înconjurător, astfel în cazul aprițiilor unor obiecte cunoscute în suprafața de joacă, creatura virtuală va interacțiuna cu obiectul și va simula un răspuns inteligent. De exemplu în cazul în care se gâdilă creatura, aceasta va produce raset , redar și auditiv, precum și vizual.
Apariția creaturii este condiționată de afișarea unei cărți care, fiind recunoscută de către EyePet, știe ce creatură sa instațieze. O astfel de carte e prezentată mai jos :
Fig. V.2. Cartea ce crează personajul virtual în jocul EyePet
Codul de pe carte este tratat ca un cod de bară, care duce la identificarea unică a unei creaturi. Cretura se comportă asemenea unui animal de companie, astfel un utilizator poate să se implice în mai multe activități de exemplu să se joace împreună cu creaturăjocuri care să implice interacțiunea cu mediul virtual prin mișcări ale corpului.
VII. Concluzii
Librăriile ce fac detecția feței dintr-o imagine devin din ce în ce mai performante, contribuțiile open source în acest domeniu determină ca funcționalitatea implementată să fie analizată de către mai mult lume ce aparține comunității OpenCV, iar schimbările reușesc să ofere noi performanțe sau fac codul mai ușor de implementa.
În această lucrare am reușit să ating scopul propus și anume controlul unui caracter virtual cu ajutorul mișcărilor capului, demonstrând că este posibil ca acest tip de control să interacționeze și cu un obiect exterior, atât timp cât există o linie de comunicație între aplicație și obiectul exterior. Posibilele aplicări a acestei soluții ar putea determina schimbări în viețile mai multor oameni cu dizabilități, astfel de aplicații, le-ar putea permite reintegrarea socială și acceptarea înapoi în populația activă, din punct de vedere al producției.
Recunoașterea facială nu a avut un mare succes în aplicațiile comerciale datorită folosirii unei astfel de opțiuni total nepotrivit, în majoritatea cazurilor, oferind spre exemplu recunoașterea tuturor fețelor în timpul fotografierii, funcție care rar este considerată utilă de către utilizatorul unei camere foto digitale.
Controlul doar cu ajutorului webcamului, pe baza geturilor este pe cale să devină o realitatea cotidiană în viitorul apropiat, iar combinarea unui număr de tehnologii în a obține acest scop, fac ca proiecte de tipul Project Natal și EyePet să permită o interacțiune directă între mediul real și cel virtual, precum și o ferestră de vizualizare în acest nou spațiu augmentat.
Bibliografie
Grimes, Richard, 2002, Dezvoltarea aplicațiilor cu Visual Studio .Net, Teora, București
http://www.microsoft.com/romania/educatie/cursnet/default.mspx ( 03.07.2009 )
http://en.wikipedia.org/wiki/C_Sharp_(programming_language) ( 12.07.2009 )
http://en.wikipedia.org/wiki/OpenCV ( 04.07.2009 )
http://www.cs.indiana.edu/cgi-pub/oleykin/website/OpenCVHelp/ ( 04.07.2009 )
Popovici Dorin Mircea, Către un sistem de comunicare vizuală naturală om-calculator, Conferința Națională de Învățământ Virtual, ediția a VI-a, 2008
http://www.emgu.com/wiki/index.php/Main_Page ( 03.08.2009 )
http://software.ucv.ro/~ganea_eugen/AIR/AIR_lab5.pdf ( 03.08.2009 )
http://en.wikipedia.org/wiki/DirectX ( 20.07.2009 )
http://en.wikipedia.org/wiki/Direct3D ( 20.07.2009 )
http://en.wikipedia.org/wiki/Project_Natal ( 04.08.2009 )
http://en.wikipedia.org/wiki/PlayStation_Eye (04.08.2009 )
http://www.jbprojects.net/projects/wifirobot/TX2RX2.doc ( 04.08.2009 )
http://en.wikipedia.org/wiki/Radio_control ( 04.08.2009 )
http://en.wikipedia.org/wiki/EyePet ( 05.08.2009 )
Anexa 1
Cod detecție :
Image<Bgr, Byte> imagineCaptura = window._capture.QuerySmallFrame();
Image<Gray, Byte> imagineGrayScale = imagineCaptura.Convert<Gray, Byte>();
imagineGrayScale._EqualizeHist();
window.imageBox1.Image = imagineCaptura;
System.Drawing.Rectangle imageArea = imagineGrayScale.ROI;
System.Drawing.Rectangle mouseStableArea =
new System.Drawing.Rectangle((int)(imageArea.Width * 0.4), (int)(imageArea.Height * 0.4), (int)(imageArea.Width * 0.2), (int)(imageArea.Height * 0.2));
imagineCaptura.Draw(mouseStableArea, newBgr(255, 0, 0), 1);
MCvAvgComp[] faces = imagineGrayScale.DetectHaarCascade(face, 1.2, 2, Emgu.CV.CvEnum.HAAR_DETECTION_TYPE.FIND_BIGGEST_OBJECT, Min_Size)[0];
if (faces.Length > 0)
{
MCvAvgComp biggestFace = faces[0];
for (int i = 1; i < faces.Length; i++)
{
if (faces[i].rect.Width * faces[i].rect.Height > biggestFace.rect.Width * biggestFace.rect.Height)
biggestFace = faces[i];
}
imagineCaptura.Draw(biggestFace.rect, newBgr(255, 255, 0.0), 1);
Point biggestFaceCenter = newPoint(biggestFace.rect.X + biggestFace.rect.Width / 2, biggestFace.rect.Y + biggestFace.rect.Height / 2);
Point imageAreaCenter = newPoint(imageArea.X + imageArea.Width / 2, imageArea.Y + imageArea.Height / 2);
imagineCaptura.Draw(
newCross2DF(biggestFaceCenter, biggestFace.rect.Width * 0.1f, biggestFace.rect.Height * 0.1f),
newBgr(0, 255, 0), 1);
olderFace.X = oldFace.X;
olderFace.Y = oldFace.Y;
olderFace.Height = oldFace.Height;
olderFace.Width = oldFace.Width;
oldFace.X = biggestFace.rect.X;
oldFace.Y = biggestFace.rect.Y;
oldFace.Width = biggestFace.rect.Width;
oldFace.Height = biggestFace.rect.Height;
window.lbl_FaceX.Text = oldFace.X.ToString();
window.lbl_FaceY.Text = oldFace.Y.ToString();
Anexa 2
Bibliografie
Grimes, Richard, 2002, Dezvoltarea aplicațiilor cu Visual Studio .Net, Teora, București
http://www.microsoft.com/romania/educatie/cursnet/default.mspx ( 03.07.2009 )
http://en.wikipedia.org/wiki/C_Sharp_(programming_language) ( 12.07.2009 )
http://en.wikipedia.org/wiki/OpenCV ( 04.07.2009 )
http://www.cs.indiana.edu/cgi-pub/oleykin/website/OpenCVHelp/ ( 04.07.2009 )
Popovici Dorin Mircea, Către un sistem de comunicare vizuală naturală om-calculator, Conferința Națională de Învățământ Virtual, ediția a VI-a, 2008
http://www.emgu.com/wiki/index.php/Main_Page ( 03.08.2009 )
http://software.ucv.ro/~ganea_eugen/AIR/AIR_lab5.pdf ( 03.08.2009 )
http://en.wikipedia.org/wiki/DirectX ( 20.07.2009 )
http://en.wikipedia.org/wiki/Direct3D ( 20.07.2009 )
http://en.wikipedia.org/wiki/Project_Natal ( 04.08.2009 )
http://en.wikipedia.org/wiki/PlayStation_Eye (04.08.2009 )
http://www.jbprojects.net/projects/wifirobot/TX2RX2.doc ( 04.08.2009 )
http://en.wikipedia.org/wiki/Radio_control ( 04.08.2009 )
http://en.wikipedia.org/wiki/EyePet ( 05.08.2009 )
Anexa 1
Cod detecție :
Image<Bgr, Byte> imagineCaptura = window._capture.QuerySmallFrame();
Image<Gray, Byte> imagineGrayScale = imagineCaptura.Convert<Gray, Byte>();
imagineGrayScale._EqualizeHist();
window.imageBox1.Image = imagineCaptura;
System.Drawing.Rectangle imageArea = imagineGrayScale.ROI;
System.Drawing.Rectangle mouseStableArea =
new System.Drawing.Rectangle((int)(imageArea.Width * 0.4), (int)(imageArea.Height * 0.4), (int)(imageArea.Width * 0.2), (int)(imageArea.Height * 0.2));
imagineCaptura.Draw(mouseStableArea, newBgr(255, 0, 0), 1);
MCvAvgComp[] faces = imagineGrayScale.DetectHaarCascade(face, 1.2, 2, Emgu.CV.CvEnum.HAAR_DETECTION_TYPE.FIND_BIGGEST_OBJECT, Min_Size)[0];
if (faces.Length > 0)
{
MCvAvgComp biggestFace = faces[0];
for (int i = 1; i < faces.Length; i++)
{
if (faces[i].rect.Width * faces[i].rect.Height > biggestFace.rect.Width * biggestFace.rect.Height)
biggestFace = faces[i];
}
imagineCaptura.Draw(biggestFace.rect, newBgr(255, 255, 0.0), 1);
Point biggestFaceCenter = newPoint(biggestFace.rect.X + biggestFace.rect.Width / 2, biggestFace.rect.Y + biggestFace.rect.Height / 2);
Point imageAreaCenter = newPoint(imageArea.X + imageArea.Width / 2, imageArea.Y + imageArea.Height / 2);
imagineCaptura.Draw(
newCross2DF(biggestFaceCenter, biggestFace.rect.Width * 0.1f, biggestFace.rect.Height * 0.1f),
newBgr(0, 255, 0), 1);
olderFace.X = oldFace.X;
olderFace.Y = oldFace.Y;
olderFace.Height = oldFace.Height;
olderFace.Width = oldFace.Width;
oldFace.X = biggestFace.rect.X;
oldFace.Y = biggestFace.rect.Y;
oldFace.Width = biggestFace.rect.Width;
oldFace.Height = biggestFace.rect.Height;
window.lbl_FaceX.Text = oldFace.X.ToString();
window.lbl_FaceY.Text = oldFace.Y.ToString();
Anexa 2
Copyright Notice
© Licențiada.org respectă drepturile de proprietate intelectuală și așteaptă ca toți utilizatorii să facă același lucru. Dacă consideri că un conținut de pe site încalcă drepturile tale de autor, te rugăm să trimiți o notificare DMCA.
Acest articol: Controlul Unui Caracter Virtual cu Ajutorul Miscarilor Capului (ID: 149658)
Dacă considerați că acest conținut vă încalcă drepturile de autor, vă rugăm să depuneți o cerere pe pagina noastră Copyright Takedown.
