Aplicatie Pentru Studiul Gesturilor
PROIECT DE DIPLOMĂ
APLICAȚIE PENTRU STUDIUL GESTURILOR
Cuprins
Capitolul 1. Introducere
1.1. Introducere în recunoasterea gesturilor
Capitolul 2. Obiectivele Proiectului
2.1. Scopul lucrarii
2.2. Obiectivele lucrarii
Capitolul 3. Studiu Bibliografic
3.1. Recunoașterea gesturilor
3.2. Computer Vision
3.3. OpenCV
3.4. Limbajul Java
3.5. JavaCV
Capitolul 4. Analiză și Fundamentare Teoretică
4.1. Exemple OpenCV și JavaCV
4.1.1. Afișeare unei imagini. OpenCV
4.1.2. Afișeare unei imagini. JavaCV
4.1.3. Capturare, Salvarea unei imagini de la cameră. JavaCV
4.2. Cum se prelucreză imaginea
Capitolul 5. Proiectare de Detaliu si Implementare
5.1. Structura generală
5.2. Interfața principal
5.3. Fereastra Test
5.4. Capturare, Filtrare, Mișcare
5.5. Preluarea Coordonatelor
5.6. Desenare careuri
5.7. Fereastra Deseneaza
5.8. Fereastra Galerie
5.9. Baza de Date
Capitolul 6. Testare și Validare
Capitolul 7. Manual de Instalare si Utilizare
7.1. Instalarea componentei Microsoft Visual C++
7.2. Setarea mediului de dezvoltare
Capitolul 8. Concluzii
Bibliografie
Anexa 1 (dacă este necesar)
Introducere
Introducere în recunoasterea gesturilor
Numeroase metode ca mouse-ul, tastatura, creionul, vocea si imaginea au fost propuse pentru realizarea comunicației dintre oameni si calculatoare. Tehnologiile recunoasterii gesturilor care recunosc si traduc dinamica gesturilor umane devin o interfața din ce în ce mai comuna în câmpul calculatoarelor omniprezente și portabile. O importanta provocare pentru urmatoarea generație tehnologica HCI (Human Computer Interface) este sa studieze cum proceseaza informația, cele cinci simțuri si sa asigure realismul utilizând toate cele cinci simțuri umane. Recunoasterea gesturilor a fost un subiect al multor studii, în ultima vreme fiind ca o promisiune tehnologica pentru comunicația om-masina.
Un sistem de recunoastere a gesturilor bazat pe un PC desktop, care utilizeaza module de comunicare cu fir are mai multe restricții cum ar fi restricții de spațiu, limitari de miscare, precum si schimbarile în capacitatea de recunoastere depinzând de schimbarile condițiilor de iluminare când obținem date semnificative ale gesturilor din imagini.
Acest proiect propune o aplicație de recunoastere a gesturilor care foloseste o camera si un laser pentru a rezolva aceste probleme. Aplicația recunoaște din imaginea furnizată de cameră punctul roșu al laserului pe care o transforma in imagine binară dupa care se colorează pe un spațiu de lucru patrațelul corespunzator coordonatelor centrului punctului roșu.
Imagile furnizate de camera au numeroase restricții si probleme pentru că sunt date imprecise, necesitatea unor algoritm complex de calculare si diferențele în recunoasterea gesturilor raportate la funcțiile camerei si schimbarilor de mediu.
Obiectivele Proiectului
Scopul lucrarii
Scopul acestei lucrari este de a crea o aplicație prin care utilizatorii își pot comunica rapid intențiile lor, de a dezvolta o aplicație care poate recunoaste expresiile variate generate de gesturile unui laser și să analizeze intențiile cu ajutorul unei camere.
Obiectivele lucrarii
Oamenii folosesc gesturile în viața de zi cu zi pentru a comunica, aratând catre un obiecte pentru a atrage atenția acelui obiect, salutând s.a.m.d. Mi-am propus capturarea imaginilor, dupa care filtrearea imaginilor furnizate de către camera video. Filtrarea să se realizeaze urmărind culoarea roșie (lumina,obiect), dupa care să realizeze o imagine alb-negru în care doar culoarea detectata va reprezenta culoarea alba și in rest negru.
Dupa realizare imaginii alb-negru să se calculeaza pozitia in spatiu a obiectului si calcularea centrului de greutate a obiectului. După calcularea poziției și centrului să se afișeaze întru-un tablou cu careuri. Să se poate realiza un desen dupa care sa se inregistreze in baza de date de unde ulterior să se poată reafișa desenul.
In proiect doresc să realizez o colecție de gesturi pentru proiectoarea ulterioara a unor algoritmi de recunoanștere a gesturilor pentru a ușura interacțiunea om-calculator.
Studiu Bibliografic
În acest capitol voi menționa materialul bibliografic parcurs în vederea elaborării acestui proiect, făcând cate o scurtă descriere a fiecăruia precum și a conceptelor fundamentale.
Punctul de plecare în dezvoltarea proiectului a fost studiul asupra detectarii mișcariilor, lucru ce mi-a strârnit curiozitate și m-a determinat să studiez o descriere mai amanuntită de la pagina[1]. Aici detectarea mișcarii este definite ca și procesul de a detecta o schimbare poziției a unui sau mai multor obiecte în raport cu împrejurimile sale sau schimbarea în împrejurimilor fața de obiect. Detectarea mișcării poate fi realizat prin ambele metode mecanice și electronice, în acest proiect se va utiliza detectarea electrica. Când detectarea mișcării este realizată de vietați, se numește percepția mișcare.
Mișcarea poate fii detectată prin:
Infraroșu (senzori active și pasive)
Optic (sisteme video și aparat de fotografiat)
Radio frecvență (radar, cuptor cu microunde și tomografic de detectare a mișcării)
Sunet (microfoane și senzori acustici)
Vibrații (triboelectric, seismic)
Magnetism (senzori magnetici și magnetometre)
În figura 3.1 este prezentată o imagine in care miscarea detectată de la o
camera este incadrată intr-un chenar roșu. [7]
Figura 3.1 Reprezintă detecția mișcarii a doi oameni [7]
Recunoașterea gesturilor
Conform [2] recunoașterea gesturilor este definita prin interpretarea gesturilor cu ajutorul algoritmilor matematici. Cele mai frecvente utilizari in recunoasterea gesturilor este dată de recunoaștere faciala și maini.În prezent se fac cercetari pentru detectarea emotiilor cu ajutorul recunoasterii mainii si al feței.
Prin recunoasterea gesturilor se poate face comunicarea om-mașină făra a mai utiliza perifericele tradiționale.
Computer Vision
Potrivit carții [3] o parte semnificativă din informațiile pe care le obținem din lumea inconjuratoare este prin vedere. Ochii nostri fac un lucru minunat prin schimbarea atenției dupa cum este necesar pentru a vedea lucrurile. Creierul nostru face o munca mai grea dar și mai frumoasa prin procesara fluxul de informații de la ambii ochi pentru a ne creea o „hartă 3D” a lumii din jurul nostru și făcându-ne conștenți de poziția și orientarea pe această ,,hartă”. Nu ar fii grozav dacă roboți (și calculatoarele in general) ar putea vedea, și să intelegă cea ce ei văd, așa cum facem noi?
Pentru roboți, văzând în ei o problemă mai mică, camere de tot felul sunt disponibile si usor de utilizat. Cu toate acestea, la un calculator cu o camera montat la el, camera din punct de vedere tehnic este doar un set de numere diferite de timp. In figura 3.2 este exemplificat cum vedem noi o imagine și cum vede camera o imagine. Camera vede o o imagine printr-o matrice de numere.
Fig.3.2. Cum vede o camera o imagine [3]
Pentru a face roboți destui de inteligenți pentru a lua decizii bazate pe ceea ce vad exista o ramura a tehnologiei numita Computer Vision.
Computer Vision (CV) este un domeniu care include metode de dobandire, procesare, analizare, și întelegerea imagini și, în general, de datele din lumea reală, în scopul de a produce informații numerice sau simbolice. O parte din dezvoltarea acestui domeniu ar fii, imitarea abilitații omului de a vedea, prin percepția electronica și ințelegerea imaginilor. Computar Vision a fost, de asemenea, 35llege35t ca întreprindere de automatizare și integrare a unei game largi de procese și reprezentari pentru percepția imaginilor.
Aplicațiile variaza de la mașinarii industrial numite Machine Vision System, care sa zicem, inspecteaza calitatea sticlelor de pe o linie de prducție, pana la cercetarea inteligenței artificiale a computer-lor si robotiilor care pot ințelege lumea din jurul lor.
Ca o disciplină științifică , Computer Vision este preocupat de teoria din spatele sistemelor artificiale care extrag informații din imagini . Datele de imagine poate lua multe forme , cum ar fi secvențe video , vizualizarea de la mai multe camere , sau de date multi- dimensionale de la un scanner medical.
Cateva din domeniile Computing Vision includ reconstrucțiea scenariilor, de detectare, de urmărire video, recunoașterea obiectelor , de învățare , de indexare , de estimare a mișcării , și restaurare a imaginii.
Aplicabilitatea tehnologiei Computer Visoin include sisteme ca:
Controlul proceselor petru roboți industriali.[1]
Navigare pentru automobile si roboti.[3]
Detectare pentru supravechere.[2]
Interactiune om-masina s.a.m.d
Prima și cea mai folosita biblioteca de funcții și algoritmi pentru realizarea unor programe care să utilizeze Computer Vision este OpenCV si numeroalse versiuni optimizate folosint biblioteciile OpenCV cum ar fii: FastCV, JavaCV, SimpleCV s.a.m.d.
OpenCV
OpenCV abreviat de la Open Source Computer Vision este o librărie de funcții și algoritmi, mai mult de 2500 de algoritmi optimizate, bazându-se pe procesarea imagiinilor în timp real , este prima biblioteca si cea mai folosita in acest sens, dezvoltat de Intel. Este open source și licență BSD. Este suportat de mai multe platforme.
OpenCV este scris în C++ ca și interfață primară dar și într-un limbaj mai vech dar mai extensibil precum C. Acum se pot folosi interfețe precum: Python, Java și MATLAB. Toate inbunatațiriile aduse bibliotecii sunt scrise în C++.
OpenCV rulează pe sisteme ca: Windows, Linux, Android, iOS, Maemo, FreeBSD, MAC OS, OpenBSD, BlackBarry 10. Biblioteca se folosește în numeroase companii precum Google, Yahoo, Microsoft, Intel, IBM, Sony s.a.m.d.
Biblioteca are o serie de module destul de puternice pentru a rezolva cele mai întalnite 35llege35 cum ar fii: decuparea imaginii, reglare luminozitații contrastului și a formelor, detectarea formelor in imagine, segmentarea imaginii în regiuni intuitive detectarea obiectelor in miscare, recunoasterea obiectelor cunoscute, estimarea miscariilor robotului de la o camera, si folosirea a doua camere pentru capturarea 3D a imaginii s.a.m.d. Pe langa aceste module biblioteca mai pune la dispozitie management-ul memoriei,suport GPU. În tabelul 4.1 sunt pezentate toate modulele bibliotecii dar in acest proiect vom folosii doar Core, Imgproc si Highgui, pentru a captura de la cameră imagini, pentru a analiza fiecare imagine, pentru a detecta punctul, pentru a calcula centrul de greutate al lui și al afișa.
Tabelul.4.1. Modulele si funcționalitatea lor
În lucrare am folosit limbaj Java și OpenCV care poate fii folosit pentru mai multe limbaje de programare, dar cum toata biblioteca este scrisa in C si C++ a fost creat o bibliotecă optimizată pentru a simplifica OpenCV standard în limbaj Java și anume JavaCV.
Limbajul Java
Java este un limbaj de programare de calculator bazat pe clase și orientat pe obiecte, special concepute pentru a avea cât mai puțina dependența posibila de implementare. Conform paginii [9] Acesta este destinat pentru a permite dezvoltatorilor de aplicații "write once, run anywhere" (WORA), ceea ce înseamnă că codul care ruleaza pe o platforma nu are nevoie să fie recompilat pentru a rula pe un alt. Aplicațiile Java sunt, de obicei compilate în bytecode (fișier de clasă), care poate rula pe orice mașină virtuală Java (JVM), indiferent de arhitectura de calculator. Java este, din 2014, una dintre cele mai populare limbaje de programare, în utilizare, în special pentru aplicații client-server de web. Java a fost inițial dezvoltat de James Gosling la Sun Microsystems (care a fuzionat de atunci în Oracle Corporation) și lansat în 1995 ca o componentă esențială a platformei Java Sun Microsystems. Limba provine o mare parte din sintaxa de la C și C + +, dar are mai puține facilități de nivel scăzut decât oricare dintre ei.
Referința originală de implementare a compilatorului Java, mașina virtuala și biblioteciile de clasă au fost dezvoltate de Sun din 1991 și primul lansat în 1995. O caractendența posibila de implementare. Conform paginii [9] Acesta este destinat pentru a permite dezvoltatorilor de aplicații "write once, run anywhere" (WORA), ceea ce înseamnă că codul care ruleaza pe o platforma nu are nevoie să fie recompilat pentru a rula pe un alt. Aplicațiile Java sunt, de obicei compilate în bytecode (fișier de clasă), care poate rula pe orice mașină virtuală Java (JVM), indiferent de arhitectura de calculator. Java este, din 2014, una dintre cele mai populare limbaje de programare, în utilizare, în special pentru aplicații client-server de web. Java a fost inițial dezvoltat de James Gosling la Sun Microsystems (care a fuzionat de atunci în Oracle Corporation) și lansat în 1995 ca o componentă esențială a platformei Java Sun Microsystems. Limba provine o mare parte din sintaxa de la C și C + +, dar are mai puține facilități de nivel scăzut decât oricare dintre ei.
Referința originală de implementare a compilatorului Java, mașina virtuala și biblioteciile de clasă au fost dezvoltate de Sun din 1991 și primul lansat în 1995. O caracteristică a limbajului Java este portabilitatea, ceea ce înseamnă că programele scrise în limbajul Java trebuie să ruleze la fel pe orice platformă hardware sau sistem de operare. Acest lucru este realizat prin compilarea codului limbajului Java pentru o reprezentare intermediară numită Java bytecode, direct la platforma-specifica de cod mașină. Instrucțiuniile Java bytecode sunt legate de cod mașină, dar ele sunt destinate să fie interpretate de către o mașină virtuală (VM) scris special pentru gazda hardware. Utilizatorii folosesc de obicei un Java Runtime Environment (JRE) instalat pe propria mașină pentru aplicații Java standard, sau într-un browser Web pentru applet-uri Java.
Biblioteci standard oferă un mod generic pentru a accesa caracteristicile specifice gazdei, cum ar fi grafica, fire de execuție, și rețele.
Programele scrise în Java au o reputație pentru a fi mai lent și care necesită mai multă memorie decât cele scrise în C + +. Cu toate acestea, viteza de executie a programelor Java sau îmbunătățit semnificativ odată cu introducerea de compilare Just-in-time. Unele platforme oferă suport hardware direct pentru Java; există microcontrolere care pot rula cu program Java în hardware-ul său în loc de un software.
Java utilizează un colector automat de gunaie pentru a gestiona memoria în ciclul de viață al obiectului. Programatorul determină când sunt create obiecte, și în timp ce rulează aplicația programul Java este responsabil pentru recuperarea memoriei odată ce obiectele nu mai sunt în utilizate.
JavaCV
La adresa [8] există varianta optimizată pentru limbajul Java se numește JavaCV care include pe lângă bibliotecile OpenCV și biblioteci precum Ffmpeg, OpenKinect, videoimput, și FlyCapture care fac programele scrise în Java să fie mai usor de implementat, incluzând și Android.
JavaCV vine cu un accelerator hardware de imagine full-screen (CanvasFrame și GLCanvasFrame), metode și execuție ușoar de folosit a codului pe multi-core, calibrarea geometriei și a culoriilor a camerei (GeometricCalibration, ProCamColorCalibration), detectarea și mecanismul de găsire a punctelor unu obiect prin ObjectFinder, un set de clase care implementează direct alinerea sistemului de camere (ProCamTransformer). Unele clase au și OpenCL (Open Computing Language), un framework pentru scrierea și executarea programelor pentru procesoare, și OpenGL (Open Graphics Library) foarte utilizat pentru programarea componentelor grafice 2D și 3D ale programelor de calculator.
JavaCV este proiectat in asa fel incat majoritatea funcțiilor bibliotecii OpenCV pot fii utilizate și în JavaCV in exact acelas mod cum sunt ele in jimbaj C si C++. În schimb sunt multe functii care trebue tratate in mod diferit.
Analiză și Fundamentare Teoretică
Exemple OpenCV și JavaCV
În continuare vreau să vă prezint un exmplu scris cu OpenCV si acelaș exemplu scris cu JavaCV, pentru a arata diferențele dintre biblioteciile scrise in limbajul C++ si limbajul Java.
Afișeare unei imagini. OpenCV
Exemplul de jos este în limbaj C++ care deschide o imagine, fără să verificare, crează o fereastră,afiseaza imaginea si așteaptă 5 secunde după care iese din program.
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
int main() {
// citirea imaginii
cv::Mat image = cv::imread("boldt.jpg");
// crearea ferestrei cu numele "Imaginea mea"
cv::namedWindow("Imaginea mea");
// afișează imaginea în fereastră
cv::imshow("Imagina mea", image);
// așteaptă 5000 ms după care se termină programul
cv::waitKey(5000);
return 1;
}
Afișarea unei imagini. JavaCV
Acum acelaș exemplu din C++ transcris în limbajul java cu ajutorul pachetului JavaCV care are cateva diferențe și care este prezentat în figura 4.4.
import com.googlecode.javacv.CanvasFrame;
import static com.googlecode.javacv.cpp.opencv_core.IplImage;
import static com.javacv.cpp.opencv_highgui.cvLoadImage;
public class MyFirstOpenCVApp {
public static void main(String[] args) {
// citirea imaginii
final IplImage image = cvLoadImage("boldt.jpg");
// crearea ferestrei cu numele "Imaginea mea"
// Rețineți că aveți nevoie pentru a indica CanvasFrame să nu se //aplice corecție texturii,prin setarea texturii la 1, în caz //contrar imaginea nu va arata corect.
final CanvasFrame canvas = new CanvasFrame("Imaginea mea", 1);
// Necesită inchiderea aplicației cand fereastra imaginii este inchisa.
canvas.setDefaultCloseOperation
(javax.swing.JFrame.EXIT_ON_CLOSE)
// afișează imaginea în fereastră
canvas.showImage(image);
}
}
În subcapitolul primului capitol este tabelul care explcă fiecare functie din OpenCV în cod JavaCV .
Capturare, Salvarea unei imagini de la cameră. JavaCV
În exemplul urmator am prezent o aplicație, realizat cu pachetul JavaCV ,care folosește pentru capturarea imaginii una sau mai multe camere și in timp ce capturează salvează imaginea pe disc.
public class GrabberShow {
public static void main(String[] args) {
// crearea ferestrei cu numele "Web Cam"
CanvasFrame canvas = new CanvasFrame("Web Cam")
// setarea camerei care va fii folosită
CvCapture capture1= cvCreateCameraCapture(0);
int i=0;
try {
while (true) {
// în „img1” se va initializa cu pixelii capturii camerei //selectate
IplImage img1 = cvQueryFrame(capture1);
if (img != null) {
// aceasta functie intoarce imaginea capturata pentru ca //camera furnizeaza
// o imagine intoarsa. Se va seta 1 pentru rasucire la stanga; //pentru dreapta
cvFlip(img, img, 1);
//se salveaza fiecare captura si se denumeste fiecare captura in //ordine crescatoare
cvSaveImage((i++)+"-aa.jpg", img);
// afisarea imaginii pe obiectul “pânză”.
canvas.showImage(img);
}
}
} catch (Exception e) {}
}
}
Cum se prelucreză imaginea
Pornind de la programul din articolul [5] în care se desenează cu un obiect roșu o multitudine de cerculețe, fară nici o interfața anume doar două ferestre. În continuare voi explic cum funcționează clasa cea mai importantă a aplicației, cea care se ocupă de prelucrarea imaginilor capturate.
Prima dată se va crea două variabile care aparțin bibliotecii OpenCV în care se va seta limitele minime și maxime a culorii detectate. Ea se setează astfel: cvScalar(C1,C2,C3,C4). Valoriile sunt in format HSV (Hue, Saturation, Value) vom vorbi mai jos despre spațiul de culori HSV. Numărul parametriilor sunt setați în funcție de spectrul de culori cu care se va folosii transformarea. Se pot seta pana la 4 valori care reprezintă elementele unu pixel din imagine care se mai numesc și canale.
Pentru prelucrarea imaginilor este nevoie și de variabile de imagini, goale. În JavaCV deobicei se lucrază cu tipul IplImage dar în biblioteca OpenCV se lucrează cu tipul Mat. Voi descrie pe scurt tipul de imagine folosit de JavaCV, IplImage.
IplImage este derivată din clasa Image care poate conține ROI (Region of Interest) și COI (Color of Interest) pe langă mărime, adancime, titlu, canale s.a.m.d. OpenCV acceptă numai un subset de posibile formate IplImage. Intel Image Processing Library procesează zona de intersecție între sursă și destinația imaginilor (sau ROI), permițându-le să varieze în mod independent.
Declarearea unei imagini goale se realizează cu funcția cvCreateImage care are trei parametrii:
Marimea – reprezinta marimea imaginii.
Adâncimea – reprezinta adancimea elementelor imaginii. Sunt mai multe tipuri de adancimi pe care le voi prezenta mai jos.
Canalul – numarul de canale a unui imagini.
OpenCV folosește 4 tipuri de adancime pe când JavaCV doar 3 tipuri.
Tipurile folosite de OpenCV:
IPL_DEPTH_8U – 8 biți intregi fără semn. Echivalent cu CV_8U în matricea imaginii
IPL_DEPTH_8S – 8 biți intregi cu semn. Echivalent cu CV_8S în matricea imaginii
IPL_DEPTH_16U – 16 biți intregi fără semn. Echivalent cu CV_16U în matricea imaginii
IPL_DEPTH_16S – 16 biți intregi cu semn. Echivalent cu CV_16S în matricea imaginii
Tipuriile folosite de JavaCV sunt reprezentate de numarul de biți prin 8, 16, 32. Toate valoriile sunt fără semn.
JavaCV dispune de o funcție alocă dinamic spațiu în memorie pentru că aplicația să se poata executa fără problemele de spațiu pentru că imaginiile și în general prelucrarea imaginilor au nevoe de foarte mult spațiu. Aceasta funcție este: opencv_core.CvMemStorage.create().
Imaginile care vor fii încarcate in program pentru prelucrare se pot declara ori prin incarcarea unei imagini, ori prin incarcarea unui fisier video ori cu ajutorul camerei web care se poate declara in 2 feluri: CvCapture și FrameGrabber. Cel mai folosit este CvCapture care va apela funcția cvCreateCameraCapture.
Funcția cvCreateCameraCapture alocă și inițializează structura CvCapture pentru citirea unui flux video de cameră. Parametrul este numarul camerei care va fii folosită. În cazul în care există o singură cameră sau nu contează ce cameră folosește poate fii trecut valoarea -1. Se mai poate seta o cameră la distanța daca se are acces la ea. Structura CvCapture nu are interfață publică și este utilizat numai ca un parametru pentru funcțiile de captură video.
Deobicei capturiile realizate sunt la rezoluția maxima la care poate face camera web poza, daca nu este nevoe de o rezoluștie mare a imaginii se poate apela o funcție numită cvSetCaptureProperty la care se poate aplica o proprietate de redimensionare a imaginii. În figura 5.2 este prezentată o imagine cu rezoluție mare de 640×480 și o imagine mică de 320X240.
Figura 5.2 Diferențe rezoluție 640X480 si 320X240 [10]
Parametrii funcții sunt:
Imagine – reprezinta imaginea capturată
Proprietate – poate fii una din urmatoarele proprietați:
CV_CAP_PROP_POS_MSEC – Poziția capturii curente in milisecunde
CV_CAP_PROP_POS_FRAMES – poziția cadrului ce urmeaza a fii prcesat
CV_CAP_PROP_POS_AVI_RATIO – Poziția relativa a capturii: 0 – la începutul cadrelor, 1 – la sfârsitul cadrelor.
CV_CAP_PROP_FRAME_WIDTH – Reprezintă lățimea cadrelor capturat.
CV_CAP_PROP_FRAME_HEIGHT – Reprezintă înălțimea cadrului capturat
CV_CAP_PROP_FPS – Rata cadrelor FPS(Frames per Second).
CV_CAP_PROP_FRAME_COUNT – Setarea numarului de cadre din captură.
CV_CAP_PROP_FORMAT – Se poate seta formatul imaginii din IplImage în Mat.
CV_CAP_PROP_BRIGHTNESS – Luminoziteatea imaginii.
CV_CAP_PROP_CONTRAST – Contrastul imaginii.
CV_CAP_PROP_SATURATION – Saturația imaginii.
CV_CAP_PROP_HUE – Nuanța imaginii.
CV_CAP_PROP_EXPOSURE – Expunerea imaginii.
CV_CAP_PROP_CONVERT_RGB – Este de tip boolean si indica daca se va realiza o conversie RGB
CV_CAP_PROP_WHITE_BALANCE – Inca nu e suportat de biblioteca
CV_CAP_PROP_RECTIFICATION – Este un indicator pentru redictifare a imaginii pentru folosirea a 2 camere
Valoare – Valoarea proprietații
După setarea camerei trebue să fie capturate și imaginile. Acest lucru se face cu functia cvQueryFrame care returneaza imaginea propriu zisă. Aceasta este metoda cea mai convenabilă de a citi fișiere video sau capturarea de date dintr-o imagine.. În cazul în care nu a fost luat nici un cadru (camera a fost deconectat, sau nu există mai multe cadre în fișierul video), funcțiile returnează pointer NULL.
Imaginile capturate deobicei sunt intoarse, trebue o funcție care rastoarna poza în stanga sau in dreapta daca este nevoie. Acest lucru se realizează cu funcția cvFlip care ia o matrice 2D și il rastoarna răstoarnă în jurul unei axe verticale și / sau orizontale. Aceasta funcție trebue aplicade aproape fiecare dată când se lucra cu camera pentru ca imaginile captate de la cameră sunt deobicei întoarse spre stanga. Parametrii acestei funcții sunt:
Sursa – Matricea sursa a imaginii capturate.
Destinație – Matrcea destinatie care va fii imaginea întoarsă.
Mod – Se specifică cum se va întoarce imaginea. Se va seta cu 1 dacă se dorește rotirea imaginii pe axa Y; 0 dacă se dorește rotirea imaginii pe axa X iar -1 pe ambele axe.
În figura 5.3 este demonstrate aces lucru intorcând pe ambele axe.
Figura 5.3 o imagine rasucită pe ambele axe [11]
Transformarea dintr-un spectru in altul se realizează cu funcția cvCvtColor care convertește o imagine de intrare de la un spațiu de culoare la altul. În cazul în care o transformare la spațiul de culoare RGB, ordinea canalelor trebuie să fie specificate în mod explicit (RGB sau BGR). Rețineți că formatul de culoare implicit în OpenCV este adesea menționată ca RGB, dar este de fapt BGR (octeții sunt inversate). Deci, primul octet într-o imagine de culori standard (24-bit) va fi un albastru componentă de 8-biți, al doilea octet va fi verde, iar al treilea octet va fi de culoare roșie. În figura 5.4 este un exemplu cum ”vede” OpenCV culoriile.
figura 5.4 este un exemplu cum ”vede” OpenCV culoriile în format BGR [12]
Parametrii acestei funcții sunt:
Sursa – Matricea sursa a imaginii.
Destinația – Matrcea destinatie. Noua imagine in alt spectru de culori.
Codul – Codul conversiei spețiului de culori. Sunt 6 spectre de culoarecare sunt:
Pentru spectrul BGR-GRAY – CV_BGR2GRAY și invers CV_GRAY2BGR
Pentru spectrul RGB – CIE XYZ – CV_BGR2XYZ și invers CV_XYZ2BGR
Pentru spectrul RGB – YCrCb JPEG – CV_BGR2YCrCb și invers CV_YCrCb2BGR
Pentru spectrul RGB – HSV – CV_BGR2HSV și invers CV_HSV2BGR
Pentru spectrul RGB – HLS – CV_BGR2HLS și invers CV_HLS2BGR
Pentru spectrul RGB – CIE Lab – CV_BGR2Lab și invers CV_Lab2BGR
Pentru spectrul RGB – CIE Luv – CV_BGR2Luv și invers CV_Luv2BGR
Pentru mai multe detalii cu privința la spațiile de culoare si cum sunt calculate ele se poate citii la pagina [4]. Deobicei pentru a putea obține un interval de culori se folosește conversia CV_BGR2HSV pentru a transforma imaginea intro imagine mai ”prietenoasă”. In figura 5.5 este prezentă o conversie BGR-HUV.
Figura 5.5 Conversia BGR la HSV[13]
Instrucțiune este cvInRangeS. Aceste funcție pot fi utilizate pentru a verifica dacă pixelii dintr-o imagine se încadrează într-o anumită intervalul specificat. Fiecare pixel al sursei, este comparată cu valoarea corespunzătoare în imaginile cu valoarea de inceput și valoarea de sfarsit a spectrului HSV,deci in spectrul HSV(Hue Saturation Value) intevalele setate pot fii intre:
Pentru prima valoare adica Hue este între 0-180
Pentru prima valoare adica Saturation este între 0-255
Pentru prima valoare adica Value este între 0-255
Dacă valoarea din sursa este mai mare sau egal cu valoarea din specificat. Fiecare pixel al sursei, este comparată cu valoarea corespunzătoare în imaginile cu valoarea de inceput și, de asemenea, mai mică decât valoarea din valoarea de sfarsit, tunci valoarea corespunzătoare în destinație va fi setat la 0xff, adica 255; în caz contrar, valoarea în destinație va fi setat la 0. în cazul în care are mai multe canale, atunci fiecare canal va fi tratat separat. Rețineți că destinație trebuie să fie de aceeași mărime și număr de canale și de asemenea, trebuie să fie o imagine de 8 biți. Imaginea creata va fii una binară, adica doar pixelii ce ne interesează vor fii albe adica de valoare maxima și luate în considerare restul nu ne intereseaza si sunt de valoare 0. In figura 5.6 este prezentată o imagine binara. Pentru mai multe detalii privind threshold pentru ca așa se numesc imaginile de interes, se pot gasii in cartea[3].
Figura 5.6 Transformare din imagine normala in truna binară[14]
Una dintre cele mai simple moduri de a compara două contururi este de a calcula momentele de contur. În linii mari, un moment este o caracteristică brută a conturului calculat prin integrarea (sau însumarea) tutulor pixelilor conturului.
Calculul momentului oferă câteva caracteristici rudimentare ale unui contur, care poate fi folosit pentru a compara a două contururi. Cu toate acestea, momentul rezultat
ale calculului, care în cazurile cele mai practice, nu sunt cei mai buni parametri pentru astfel de comparații. În special, s-ar dori de multe ori să utilizeze momente normalizate (ca obiecte de aceeasi forma, dar dimensiunile diferite cu valori similare). În mod similar, simple momente din secțiunea anterioară depind de sistemul de coordonate ales, ceea ce înseamnă că obiectele nu sunt potrivite corect dacă sunt rotite.
Funcția cvMoments calculează momentele spațiale și centrale până la al ordinal trei, depre care vom vorbi la urmatoarea instrucțiune și le scrie în variabilă de moment. Momentele pot fi utilizate apoi pentru a calcularea centrului de greutate al formei, arena său axele principale și diferite caracteristici ale formei.
Parametrii acestei funcții sunt:
Sursa – Imaginea (cu un canal sau cu 3 canale).
Momentul – Pointer la coordinate.
Cod – Dacă este diferită de zero, toate valorile pixelilor de zero sunt tratate ca zerouri, toate celelalte sunt tratate ca 1, iar dacă este 0 sa proceda invers valoriile pixelilor de 0 vor fii tratate ca 1.
Cu funția cvGetSpatialMoment returnează o valoare de tip double in care se gasește momentul spațial cu ajutorul poiterului Moment. În acesta funție se poate seta axa de pe care se va lua coordonatele. Parametrii funcției sunt:
Moment– Pointer la coordonate.
X – dacă este 1 atunci se consideră axa-x axă de coordonate.
Y – dacă este 1 atunci se consideră axa-y axă de coordonate.
În acest cod se va apela de doua ori această funcție, o data pentru coordonata x si o data pentru y.
Mai avem nevoe de o altă funcție inrudită cu funcția precedentă, este vorba despre cvGetCentralMoment care calculează centrul. Parametrii sunt aceeași ca și la intrucțiunea precedentă doar că dacă se setează x sau y atunci mijlocul se va calcula raportat la axa care este setată.
Ca să calculam adevăratele coordonate (pentru că coordonatele setate la intrucțiunea anterioară cvGetSpatialMoment nu sunt raportate la centru obiectului ) vom imparții momentul spațial la centrul obiectului.
Proiectare de Detaliu și Implementare
Structura generală
Acest proiect urmartește realizarea unei colecții de gesturi, de coordonate pentru realizarea ulterioară a unui program la care nu o să mai fie nevoie de mouse, de exemplu, pentru a lansa o aplicație. Pentru acest lucru este nevoe de urmatoarele:
Cameră web, orce cameră din comerț, cu cât camera este mai performată cu atât și detecția va fii mai exactă
System de operare Windows xp/7/8 se poate rula și pe versiunea X64 cat și X86.
NetBeans IDE 8.0 cat și Java SDK 8 se pate gasii la pagina [6].
Structura generală a aplicațiri mele constă intr-o interfață principală, un JFrame numită Start_Frame.java unde se poate alege dintre butoanele Test, Experiment și Galerie.
Dacă se apasă pe butonul Test va aparea un nou JFrame in care se va gasii un JPanel un buton de start si două JLabel-uri în care vor aparea, după apăsarea butonului start, imaginea video de la cameră si in dreapta imaginea binară cu sporul rosu detectat, după care in JPanel va fii un careu de patrațele și dacă camera a detectat un obiect sau spot roșu se va colora patrățica corespunzatoare poziției spotului roșu.
Figura 5.2 Interfața Test
Urmatorul buton este Experiment unde dacă este apăsat va aparea un JFrame în care există un JPanel cu careuri și 3 butoane: Start, Clear, Save. Dacă se apasă pe butonul Start atunci camera va pornii și va începe să urmarească spotul afisând pe JPanel urma pe unde a trecut sporul luminos colorând careurile.
Figura 5.3 Interfața Experiment
Butonul Clear este petru a șterge careurile și butonul Salve este folosit pentru a introduce in baza de date rezoluția careurilor, data și valoarea fiecărui patrățelelor.
Dacă se apasă pe butonul Galerie din JFrame-ul principal se va deschide un JFrame în care se găsește un tabel unde se vor afișa ănregistrăriile din baza de date si un JPanel in care dacă se selectează o înregistrare se va afișa în JPanel gestul inregistrat in baza de date.
Figura 5.4 Interfața Galerie
Interfața principal
Cum am spus și mai sus, fereastra principală are 3 butoane, Test, Experiment și Galerie, care apeleză fiecare un alt JFrame.
Butonul Test verifică dacă restul ferestrelor sunt închise după care apelează JFrame-ul Test căruia îi mai setează locația unde va apărea JFrame-ul, îl mai setează ca vizibil după care va seta variabila booleană frame1ON pe true pentru a indica că o fereastră este deschisă. Dacă mai este apăsat o dată acest buton JFrame-ul test va disparea
și se va seta variabila booleană pe false pentru a semnala că nu mai sunt ferestre deschise. Butonul are urmatorul cod:
if(frame1ON==false){
test = new Test();
test.setLocation(320,80);
test.setVisible(true);
frame1ON = true;
} else {
test.dispose();
frame1ON = false;
}
Butonul Experiment va face acelaș lucru doar că va apela alt JFrame pe nume Desenare. Codul este:
des = new Desenare();
des.setLocation(320,80);
des.setVisible(true);
La fel și butonul Galerie va apela un JFrame pe nume Galerie. Aceast JFrame are nevoie de tratarea unei excepțiilor pentru că in această clasă se lucră cu bază de date.
try {
galerie=new Galerie();
} catch (SQLException ex) {
Logger.getLogger(Start_Frame.class.getName()).log(Level.SEVERE, null, ex);
} catch (ClassNotFoundException ex) {
Logger.getLogger(Start_Frame.class.getName()).log(Level.SEVERE, null, ex);
}
galerie.setLocation(320,80);
galerie.setVisible(true);
Butonul Exit va verifica dacă toate ferestrele sunt închise, dacă nu le va inchide și va iesii din aplicație
test.dispose();
this.dispose();
galerie.dispose();
System.exit(0);
Fereastra Test
Fereastra Test are două JLabel-url, un buton de start și un JPanel. Într-un JLabel se va afișasa imaginea captată de la cameră și în celălalt JLabel se va afișa imaginea filtrată după prelucrarea imaginii captate de la cameră.
În JPanel se va colora patratul corespunzător coordonatelor luate după filtrarea imaginii.
Figura 5.5 Detecția și cololarea patratului
Tot în JPanel, implicit desenează patratele de rezoluție 20X20 folosind codul:
@Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Careu.dsn(g);
}
Pentru a desena careurile se folosește funcția paintComponent din clasa JComponent care apelează o funcție din clasa Careu despre care vom vorbi în curand.
Butonul Start Camera va trimite clasei ThreadSpot 4 parametrii, și anume:
JLabel-ul unde va fii afișată captura.
JLabel-ul unde va fii afișată imaginea filtrate.
JPanel-ul incarese va colora patratul corespunzător.
O variabila booleana care indica dacă se lasă patratul colorat anterior sau nu.
justtest = new ThreadSpot(LVideo,LBin,TestPanel,false);
Clasa ThreadSpot este un fir de exacuție pentru ca să nu îngereuneze funcționarea optima a firului principal. Astfel continuarea codului va fii:
w=new Thread(justtest);
w.start();
Capturare, Filtrare, Mișcare
Clasa Filtreaza este clasa principală care seteaza camera și intervalele de culori care va trebuii filtrat, capturarea imaginii, transformarea ei in imagine alb-negru si calcularea pozitiei laserului cu centrul punctului. Toate funcțiile sunt realizate cu ajutorul bibliotecii OpenCV.
Primul lucru ce trebue realizat este setarea limitei minime si maxime a culoriilor detectate necesare pentru filtrare, culoarea aleasă în acest proiect va fii roșu.Valoriile acestei funcții se vor sta in spctrul HSV (Hue, Saturation, Value) nu RGB (Red, Green, Blue).Setarea se realizează cu urmatoarele funcții:
opencv_core.CvScalar rgba_min = cvScalar(170, 150, 60, 0);// RED
opencv_core.CvScalar rgba_max = cvScalar(190, 255, 255, 0);
După setarea limitelor de culoare vom declara dimensiunea, adâncimea și numarul de canale imaginilor care le vom folosii pentru filtrare. Imaginile declarate vor fii imagini goale de o anumita dimensiune, adâncime și canale. Imaginile se declară astfel:
opencv_core.IplImage imghsv = cvCreateImage(cvSize(w, h), 8, 3);
opencv_core.IplImage imgMedian = cvCreateImage(cvSize(w, h), 8, 3);
opencv_core.IplImage imgBin = cvCreateImage(cvSize(w, h), 8, 1);
Avem nevoie de 3 declaratii de imagine, fiecare de aceași dimensiune, adâncime (deobicei pe 8 biți) si canale. Doar ultima variabilă va fii pe un canal pentru că va fii o imagine binară.
Mai trebue declarate două variabile pentru cameră și pentru o imagine în care se va stoca imaginea capturată.
opencv_highgui.CvCapture capture1;
opencv_core.IplImage imgOrig;
Se va declara o variabilă care este folosită la alocarea spațiului dinamic în memorie pentru ca aplicața să ruleze fară erori din cauza insuficienței spațiului. În general prelucrarea imaginilor au nevoe de foarte mult spațiu. Alocarea spațiului se face prin urmatoarea declarație:
opencv_core.CvMemStorage storag = opencv_core.CvMemStorage. create();
După care vom declara variabila de moment. Momentul este compararea a două contururi. Voi prezenta mai multe detalii în cele ce urmează. Declarația acestei variabile se face cu următoarea instrucțiune:
opencv_imgproc.CvMoments moments = new opencv_imgproc.CvMoments(Loader.sizeof(opencv_imgproc.CvMoments.class))
De aici începe codul propriu zis, pâna acuma au fost doar crearea variabilelor. În biblioteca OpenCV se apleleaza puțin altfel decat in JavaCV care este un pachet care înclude OpenCV și care l-am folosit în acest proiect.
Primul lucru și una dintre cele mai importante setari este setarea camerei. Unde vom seta care cameră va captura imagini pentru prelucrare. Se pot seta și cameră de la distanță. Se declară astfel:
capture1 = cvCreateCameraCapture(0);//setare sursa imaginii->0: prima camera; 1: urmatoarea camera
Urmatoarea funcție setează o proprietate camerei. In acest proiect voi seta o propretate pentru a micii imaginea originală, de rezoluție 640X480, la o rezoluție de 320X240.
cvSetCaptureProperty(capture1, CV_CAP_PROP_FRAME_WIDTH, w);//setare width imagine capturata
cvSetCaptureProperty(capture1, CV_CAP_PROP_FRAME_HEIGHT, h);//setare height imagine capturata
Urmatoarea instrucțiune dupa setarea parametriilor imaginii este foarte importan-tă pentru că fără ea nu voi putea captura imagina de la cameră. Aceasta este metoda cea mai convenabilă de a citi fișiere video sau capturarea de date dintr-o imagine. În cazul în care nu a fost luat nici un cadru (camera a fost deconectat, sau nu există mai multe cadre în fișierul video), funcțiile returnează pointer NULL.
imgOrig = cvQueryFrame(capture1);//capturare cadrului
Se verifică daca exista date de la cameră dupa care se va aplica o funcție care va întoarce imaginea, pentru că de obicei imaginile sunt capturate rasturnat . Se va seta cu 1 dacă se dorește rotirea imaginii pe axa Y; 0 dacă se dorește rotirea imaginii pe axa X iar -1 pe ambele axe. Rotirea se face cu instrucțiunea:
cvFlip(imgOrig, imgOrig, 1);//întoarce imaginea
După rotire urmează convertirea imaginii originale din sectrul BGR , pentru că OpenCV foloseste spectrul BGR, în sectrul HSV pentru că acest spectru este mai convenabil pentru a calcula limitele de culori care o voi prezenta la urmatoarea instrucțiune. Convertirea spectrului se face cu ajutorul intructiunii:
cvCvtColor(imgOrig, imghsv, CV_BGR2HSV);
Următoarea funcție pot fi utilizate pentru a verifica dacă pixelii dintr-o imagine se încadrează într-o anumită intervalul specificat. Această instrucțiune caută în imagine toate culoriile care se incadrează in limitele setate si va crea o altă imagine de aceaș marime doar că imaginea va conține doar culori alb-negru.
cvInRangeS(imghsv, rgba_min, rgba_max,imgBin);// cautare în intervale de nuanța
În următoarele trei instrucțiuni se va calula momentul si după aceea momentul spațial. Momentrul, după cum am spus și mai sus, este compararea a două conturui dintre doua capturi. . În linii mari, un moment este o caracteristică brută a conturului calculat prin integrarea (sau însumarea) tutulor pixelilor conturului. Momentul spațial va returna o valoare unde se gasește coordonatele de la un contur pană la noul contur depasat. Vor fii două funcții de momente spașiale pentru axa X și pentru clasa Y după care se va calcula și centrul imaginii. Funcțiile vor arata astfel:
cvMoments(imgBin, moments, 1);
double mom10 = cvGetSpatialMoment(moments, 1,0);
double mom01 = cvGetSpatialMoment(moments, 0,1);
double area = cvGetCentralMoment(moments, 0, 0);
Ultimul lucru ce mia trebue facut este să calculez centrul de greutate al spotului. Acest lucru se realizează imparțind fiecare moment spatial de pe o axa ,X și Y, la centrul imaginii capturate.
spotX = (int) (mom10 / area);
spotY = (int) (mom01 / area);
Preluarea Coordonatelor
Clasa ThreadSpot un fir de execuție separată care cu ajutorul unui while se va apela funcția Calculate() din clasa Filtreaza care va furniza imaginile capturate de la camera și imaginea filtrată cât și coordonatele furnizate.
Clasa ThreadSpot are un constructor cu 4 parametrii cum am specificat mai sus:
public ThreadSpot(JLabel video, JLabel filtrat, JPanel p1, boolean gest) throws AWTException {
this.video = video;
this.filtrat = filtrat;
this.Panel = p1;
this.gest=gest;
}
După setarea costructorului urmează metoda run()care este o metodă din clasa Thread în care este un while cu o condiție booleană care indica continuitatea cadrelor capturate și filtrarea acestora.
În acest while se apelează metoda Calculate() din clasa Filtreaza după care se verifică dacă există cele două JLabel-uri unde vin trebue afișate imaginea capturată și cea filtrată.
public void run() {
System.out.println("\n*** start fir \n");
try {
System.out.println("initializare camera");
while (go) {
fil.Calculate();
// identificare coord spot(spotX, spotY)
if(video!=null && filtrat!=null){
video.setIcon(new ImageIcon(fil.imgOrig.getBufferedImage()));
// imaginea video
filtrat.setIcon(new ImageIcon(fil.imgBin.getBufferedImage()));
// imaginea filtrata
}
Se veifică dacă este necesară desemarea unui singur patrat sau este nevoie de desenarea si patratului anterior lui. În acel if se va aplela funcția clear() al clasei Careu care va seta toate careurille pe culoarea albă. Codul necesar pentru acest lucru este:
if(gest==false){ //cu sau fara gest
Careu.clear();
}
Se verifică dacă variabilele raspunzătoare coordonatelor obiectului urmarit din clasa Filtreaza sunt diferite de 0, adica dacă se mișca obiectul roșu detectat, se scrie pe consolă valoriile după care se apeliază funcția setCareu din clasa Careu cu parametrii valoriilor coordonatelor imparțite la rezoluție petru a încadra patratul colorat în careul corespunzător și se apelează metoda repaint pentru JPanel-ul în care se va desena. Acest cod este:
if(fil.spotX!=0 && fil.spotY!=0){
System.out.println(fil.spotX + " , " + fil.spotY );
Careu.setCareu(fil.spotX/20,fil.spotY/20);
Panel.repaint();
}
Aici se termină funcția run și urmează funcția release(). În această funcție se va oprii capturarea, se trece pe false variablia din while și dacă există cele două JLabel-uri se inchid imaginile pentru a putea închide aplicația.
public void release() {
go = false;
System.out.println("\n*** release capture\n");
cvReleaseCapture(fil.capture1);
if(video!=null && filtrat!=null){
System.out.println("\n*** release All\n");
cvReleaseImage(fil.imgOrig);
cvReleaseImage(fil.imgBin);
}
}
Desenare careuri
Clasa Careu se folosește pentru a desena careurile in JPanel, a seta și colora un careu dacă sau găsit coordonatele și pentru a sterge careurile colorate.
Prima dată se va declara un tablou bidimensional de tip Color de dimensiuniile rezonuției imagini. Declarația variabilei se declară astfel:
public static Color careu[][] = new Color[320][240];
Pentru a sterge careurile, adică să readucă toate careurile la starea inițială se iterează tabloul bidimensional pe binie și coloana după care se setează fiecare careu cu culoarea albă. Acest lucru se realizează cu metoda clear(). Codul este urmatorul:
public static void clear(){
for(int i=0;i<320;i++)
for(int j=0;j<240;j++)
careu[i][j]=Color.WHITE;
}
Funcția setCareu() care a fost folosit mai sus se găseste in clasa Careu, care setează culloarea albastră pentru pozișia patratului dat ca și parametru.
public static void setCareu(int i,int j){
careu[i][j]=Color.BLUE;
}
Mai există o singură funcție și anume dsn care este apelată la fiecare JPanel din program și care este responsabilă de desenarea careurilor dacă în tablul bidimensional de culor este culoarea albă, iar dacă în tablu se gasește o altă culoare diferită de alb atunci coloreză patratul de la acea poziție în albastru. Iterația se face la rezoluție imparțit la 20 pentru ca rezoluția careurilor sunt de 20X20 și desenarea careurilor pe punn variabilele de poziție dupa care se îmulțeste la 20 pentru a potrivii careurilecu careurile colorate Acest funcție este prezentată mai jos:
public static void dsn(Graphics g){
for(int i=0;i<320/20;i++){
for(int j=0;j<240/20;j++){
if(careu[i][j]==Color.WHITE){
g.setColor(Color.BLACK);
g.drawRect(i*20+110,j*20+40,20,20);
}
else
{
g.setColor(careu[i][j]);
g.fillRect(i*20+110,j*20+40,20,20);
}
}
}
}
Fereastra Deseneaza
În fereastra Desenează este asemănător cu fereastra Test, deosebirea între ele este faptul că în fereastra Deseneaza nu vor mai fii afișate imaginiile capturate și filtrate ci doar JPanelul în care spre deosebire de fereastra Test aici se va vedea toate careurile colorate pe unde a trecut spotul și dupa aceea se poate salva prin apasare butonului Save sau se poate sterge prin apăsarea butonului Clear. Fereastra dispune și de un buton de Start care va inițializa camera și va incepe prelucrarea capturiilor.
Butonul Start este defapt un buton On/Off care dacă se setează se lansează o funcție și se va schimba textul butonului în Stop iar dacă se mai apasă o dată se va apela funcția release() din clasa Filtreaza dupa care va apărea pe buton textul Stop. Codul pentru buton este urmatorul:
if(ToggStartStop.isSelected()){
execExp();
ToggStartStop.setText("Stop");
} else {
ToggStartStop.setText("Start");
ts.release();
}
Funcția exeExp() este aceași ca și butonul Start Camera din fereastra Test doar cu diferența că constructorul are ca parametrul doar JPane-lul folosit pentru că in această fereastră nu avem nevoie de imagine și de imaginea filtrată.
public void execExp() {
try {
ts = new ThreadSpot(null,null,PanelDes,true);
ts.ix=true;
w=new Thread(ts);
w.start();
}catch (Exception ex) {}
}
Butonul Clear apelează funcția clear() din clasa Careu după care apelează repaint pentru JPanel. Codul va fii:
Careu.clear();
PanelDes.repaint();
Și butonul Save în momentul în care este apăsat va crea o variabilă de tip string după care se va itera tabloul bidimensional careu. Se verifică la fiecare iterație dacă există un careu alb atunci în scring va pune un 0 iar dacă va gasi un careu colorat va adauga 1. După care va trimite clasei DB parametrul string iar apoi va apela funcția insert() și după aceea funcția query() a clasei DB. Funcția query() se apelează pentru ca va afișa pe consolă înregistrarea facută. Codul urmator face acest lucru:
try {
String strCapture="";
for(int i=0;i<320/20;i++){
for(int j=0;j<240/20;j++){
if(careu[i][j]==Color.WHITE){
strCapture += "0";
}else{
strCapture += "1";
}
}
}
db=new DB(strCapture);
db.insert();
db.query();
System.out.println("id "+db.id+": rows "+db.row+": cols "+db.col+": capture"+db.capture+": time "+db.time);
} catch (Exception ex) {
Logger.getLogger(Desenare.class.getName()).log(Level.SEVERE, null, ex);
}
Fereastra Galerie
Fereastra Galerie conține un JPanel și un tabel în care se va afișa înregistrăriile din baza de date după care dacă se selectează o înregistrare se va desena gestul introdus În baza de date. În această clasă trebue declarat o variabilă de tip DB și acea variabilă folosită ca model pentru Tabelul în care vor apărea înregistrăriile și după aceea apelarea unei funcții care va sorta automat înregistrăriile. Clasa DB extinde clasa AbstractTableModel care ajută să la crearea tabelului si a pune inregistrari in el.
initComponents();
this.etm = new DB();
jTable1.setModel(etm);
jTable1.setAutoCreateRowSorter(true);
Baza de Date
Clasa DB face două lucruri intr-o singura clasa: va insera in baza de date si va fi folosit pentru model al JTabel-ul din fereastra Galerie.
Clasa DB extinde clasa AbstractTableModel care este folosita pentru a insera in JTabel.
După declaratiile de variabile printre care si un tablou de tip string in care sunt capurile de tabel, Este functia Conectare() unde este conectarea propriu zisa cu baza de date cu ajutorul JDBC. Codul este prezentatmai jos:
String[]numeColoane = {"Id", "Rows","Cols","Time"};
PreparedStatement pst= null;
String capture;
JDialog interfata;
String row,col;
Timestamp time;
int id;
Connection con;
Statement smt;
ResultSet rs;
public final void Conectare() throws ClassNotFoundException{
try {
Class.forName("com.mysql.jdbc.Driver");
con = (Connection) DriverManager.getConnection
("jdbc:mysql://localhost/gesture", "root", "");
smt = (Statement) con.createStatement
(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
System.out.println(con);
} catch (SQLException ex) {
Logger.getLogger(DB.class.getName()).
log(Level.SEVERE, null, ex);
}
}
Dupa functia Conectare() urmează doi constructori: unul cu un parametru si unul fara paramerii. Cel cu parametrii este folosit pentru inserare in baza de date pentru ca i se atribue ca parametru stringul care conțime ”codificare” careurilor daca sunt colorate sau nu și se mai apelează funcția Conectare(), iar cel fara parametrii este folosit doar pentru a apela funcția Conectare si pentru a interoga baza de date cu toate campurile din ea pentru a putea folosi la afisarea inregistrariilor in JTabel. Codurile sunt:
DB(String capture) throws ClassNotFoundException{
this.capture=capture;
Conectare();
}
DB() throws ClassNotFoundException, SQLException{
Conectare();
rs=smt.executeQuery("select * from gest");
}
Inserare se face cu ajutorul metodei insert(). In această metodă se crează un string cu o instrucțiune de inserare SQL in care se va insera doar rezoluția si stringul luat ca parametru de constructor ce contine codificarea in 0 si 1 a careurilor. După ce se crează șirul cu instrucțiunea, se apelează funcția prepareStatement din clasa Connect și caruia I se dă ca parametru șirul cu instrucțiunea SQL. După setarea intrucțiunii trebue introduse valoriile, care se realizeaza cu instricțiunea setString() din clasa PreparedStatement care va primii ca si parametru numarul coloanei unde va fii setată si valoarea setata in format string. Actualizarea se face cu instrucțiunea executeUpdate() și dupa aceea se afisează pe consolă un mesaj anuntand că inregistrarea sa finalizat cu succes.
void insert() throws SQLException{
String insertTableSQL = "INSERT INTO gest"
+ "(Rows,Cols,capture) VALUES"
+ "(?,?,?)";
pst = con.prepareStatement(insertTableSQL);
pst.setString(1, "20");
pst.setString(2, "20");
pst.setString(3, capture);
pst.executeUpdate();
System.out.println("Inserted records into the table…");
}
Tabelul bazei de date are 5 campuri dar primul camp este id care este auto-increment si ultimul este data si ora care se va seta automat la introducerea unei inregistrari. In figura 5.7 este prezentată baza de date.
Figura 5.7 Structura bazei de date
Dupa functia de inserare urmeaza functia query() care va interoga baza de date si va lua linie cu linie fiecare inregistrare cu toate campurile lui. Trebue specificat neaparat tipul campului.
void query() throws SQLException{
String query = "select * from gest";
rs = smt.executeQuery(query);
while (rs.next()) {
id=rs.getInt("Id");
row = rs.getString("Rows");
col = rs.getString("Cols");
time = rs.getTimestamp("Time");
}
}
Urmatoarele funcții apartin de clasa AbstractTableModel, prima funcție care se numește getRowCount() va returna numarul de inregistrări din tabel urmată de funcția getColumnCount() care returnează numarul de coloane și o functie numita getColumnName (int m) care va returna numele fiecarei coloane. Codul celor 3 funcți sunt prezentate mai jos.
@Override
public int getRowCount() {
try {
rs.last();
return rs.getRow();
} catch (SQLException ex) {
Logger.getLogger(DB.class.getName()).log(Level.SEVERE, null, ex);
}
return 0;
}
@Override
public int getColumnCount() {
return numeColoane.length;
}
@Override
public String getColumnName(int m) {
return numeColoane[m];
}
Funcția cea mai importantă pentru afisarea in JTabel este funcția getValueAt care este o funcție ce va returna un obiect și care are 2 parametrii: randul curent și coloana curentă. Prima dată se atribue inceputul înregistrariilor, din cauză ca SQL începe numararea randurilor de la 1 si nu de la 0 va trebuii sa se adauge un 1 la randul curet. După ce avem primul rândul trebue sa ii indicam și unde vor venii aranjate fiecare camp, acest lucru se face cu un switch in care parametrul este coloana curetă. Dacă coloana curentă este 0 atunci primul camp va fii introdus in prima coloana din tabel, daca e 1 atuci din prima inregisrare se va pune pe a doua coloana s.a.m.d. Codul funcției se gasește mai jos:
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
try {
rs.absolute(rowIndex+1);
switch(columnIndex){
case 0: return rs.getString("Id");
case 1: return rs.getString("Rows");
case 2: return rs.getString("Cols");
case 3: return rs.getTimestamp("Time");
default:return 0;
}
} catch (SQLException ex) {
Logger.getLogger(DB.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
Testare și Validare
Primul lucru pe care l-am testat a fost camera web. La aceasta am testat claritatea imaginii, culoriile utilizate de camera și numărul de pixeli. După care am testat setăriile camerei folosite în biblioteca OpenCV.
După realizarea aplicației și a setăriilor camerei am constatat că rezoluția camerei este prea mare, iar pentru că memoria calculatorului nu are nevoie de o imagine cu o rezoluție așa mare, am redimensionat imaginea, testând diferite rezoluți care să fie clare și să ocupe puțin spațiu în memorie pentru a nu îngreuna aplicația.
După redimensionare am testat filtrarea imaginii. În imaginea binară va apărea imaginea captată dar doar culoriile care ne interesează. Prima testare a filtrului a fost modificarea valoriilor culori pe care o urmărește.
Aplicația va insera datele obținute în baza de date. Am testat conexiunea, inserarea, interogarea și redesenare în baza de date cu ajutorul afișarii la consolă a fiecărei etape de conectare, inserare și interogare. În figura 6.1 este exemplificată o inserare a unei imagini în baza de date unde, în momentul inserării se va anunța pe consola acest lucru.
Figura 6.1 Inserarea în baza de date
După inserare se va putea interoga baza de date și redesena gestul introdus în baza de date. Redesenarea am testat-o prin afisarea înregistrarii pe consola și în acelaș timp și redesenarea gestului în careurile din spațiul de desenare.
Manual de Instalare si Utilizare
Instalarea componentei Microsoft Visual C++
Cum am mai specificat, biblioteca OpenCV este scris și proiectat în limbajul C și C++. Si deci trebue sa instalam o aplicatie care se gaseste in dosarul proiectului numit Microsoft Vision C++ 2010. Microsoft Vision C++ este un mediu de dezvoltare integrat (IDE) creat de Microsoft pentru limbajele de programare C, C ++. Acesta dispune de instrumente pentru dezvoltarea și depanarea codului C + +, mai ales cod scris pentru API-ul Microsoft Windows, API-ul DirectX, și Microsoft. NET Framework.
Multe aplicații necesită pachetele Visual C + + pentru a funcționa corect. Aceste pachete sunt de multe ori instalate în mod independent de aplicații, permițând mai multe aplicații să utilizeze pachetului fiind nevoie să fie instalat o singură dată. Aceste pachete Visual C + + sunt în mare parte instalate pentru bibliotecile standard care utilizează mai multe aplicații.
Se poate instala versiune pentru sistem de operare pe 32 de biți sau pentru 64 de biți. În dosarul proiectului se gasește fișierele Microsoft Vision C++ 2010_x64.exe pentru instalarea programului pe 64 de biți și Microsoft Vision C++ 2010_x86 pentru 32 de biți.
Dupa lansarea in executie a fișierului corespunzator sistemului de operare, se va incepe instalarea.
Figura 7.9 Acceptarea licentei
În prima fereastră este nevoie sa bifaarea partatelului in dreptul caruia scrie “I have read and accept the license terms.”. Dupa bifarea patratelului va aparea butonul “Install”, pe care se va apasa și va începe instalarea.
Figura 7.10 Finalizare instalarii
La aparitia acestei ferestre se apasa pe butonu “Finish” pentru a incheia instalarea.
Setarea mediului de dezvoltare
Pentru a putea folosii și rula aplicații cu ajutorul bibliotecii JavaCV și OpenCV trebue sa fie setat Classpath-ul, și fișierele .jar. Pentru ca mediul de dezvoltare să recunoasca fisierele DLL, care apartin bibliotecii OpenCV. Fișierele dll (Dynamic-link library) este implementarea Microsoft a conceptului bibliotecii partajate în sistemele de operare Microsoft Windows și OS / 2. Formatele de fișiere de tip DLL sunt aceleași ca și fișierele sisierele executabile EXE.
În contimuare voi prezenta setariile ce trebue aduse mediului de dezvoltare NetBeans.
Se dă click dreapta la un proiect care foloseste biblioteciile OpenCV sau JavaCV.
Figura 7.11 Proprietați
Se alege obțiunea “Properties” dupa care va aparea o fereastra in care se va alege obtiunea “Run”.
Figura 7.12 Setare Classpath
La aceasta obtiune in dreapta este un camp in dreptul caruia scrie “VM Options:”. În acest camp se va scrie urmatoarea setare: -Djava.library.path=lib\opencv.
Iar pentru a seta bilioteciile jar necesare rularii aplicației se va selecta obțiunea ”Libraries” după care în fereastra din dreapta în primul tab vor trebuii adăugate bilioteciile.
Figura 7.13 Setare Biblioteciilor
După care se va apăsa pe butonul ”Add JAR/Folder” pentru a alege locația fișierelor necesare. Fișierele necesare se găsest în folderul proiectului în folderul lib.
Concluzii
Contribuții personale
Am folosit o biliotecă numită OpenCV care m-a ajutat să capturez, să detectez doar culoriile care mă va ajua să obtin coordonatele unui obiect sau laser.
Cu ajutorul coordonatelor am realizat un spațiul de desenare cu careuri de rezoluție 20X20 care mă ajută să desenez gestul, după care introduc gestul în baza de date după care se poate interoga baza de date și redesena înregistrarea selectată.
Analiza critică a rezultatelor obținute
Într-un mediu intunecat aplicația va fucționa la parametrii normali pentru că lumina exterioară nu va influența filtrarea. În figura 8.1 se arată o filtrare optimă.
În figura 6.8 este testarea conturului mâinii dar lumina prea puternică influențează foarte tare imaginea filtrată.
Figura 6.8 Conturul mainii filtrate
Dezvoltări ulteriare
Bibliografie
[1] ***, Motion detection, http://en.wikipedia.org/wiki/Motion_sensing
[2] ***, Geture recognition,http://en.wikipedia.org/wiki/Gesture_recognition
[3] Gary Bradski and Adrian Kaehler,Learning OpenCV Computer Vision with a OpenCV Library.: O’Reilly Media, Inc.., 2008.
[4] ***, OpenCV Tutorial, http://docs.opencv.org
[5] Ganesh Tiwari, colored object tracking in java- javacv code, http://ganeshtiwaridotcomdotnp.blogspot.ro,
[6] Download NetBeans http://www.oracle.com/technetwork/java/javase/downloads/
[7] ***, Inteligent Video Analytics, http://www.ips-analytics.com
[8] Samuel Audet, javacv, https://code.google.com/p/javacv/
[9] ***, Java (programming language), http://en.wikipedia.org/wiki/
[10] Jan Ozer, The Basics – Codecs, Bandwidth, Data Rate and Resolution www.stream,inglearningcenter.com
[11] HD_Mouse, flip function, http://answers.opencv.org
[12] Shermal Fernando, Color Detection & Object Tracking, http://opencv-srf.blogspot.ro/
[13] Mike Bjorge, Billiards & Computer Vision: Part 4 – Object Detection, http://www.mbjorge.com/
[14] ***, Tracking colored objects in OpenCV, http://www.globlib4u.wordpress.com
Bibliografie
[1] ***, Motion detection, http://en.wikipedia.org/wiki/Motion_sensing
[2] ***, Geture recognition,http://en.wikipedia.org/wiki/Gesture_recognition
[3] Gary Bradski and Adrian Kaehler,Learning OpenCV Computer Vision with a OpenCV Library.: O’Reilly Media, Inc.., 2008.
[4] ***, OpenCV Tutorial, http://docs.opencv.org
[5] Ganesh Tiwari, colored object tracking in java- javacv code, http://ganeshtiwaridotcomdotnp.blogspot.ro,
[6] Download NetBeans http://www.oracle.com/technetwork/java/javase/downloads/
[7] ***, Inteligent Video Analytics, http://www.ips-analytics.com
[8] Samuel Audet, javacv, https://code.google.com/p/javacv/
[9] ***, Java (programming language), http://en.wikipedia.org/wiki/
[10] Jan Ozer, The Basics – Codecs, Bandwidth, Data Rate and Resolution www.stream,inglearningcenter.com
[11] HD_Mouse, flip function, http://answers.opencv.org
[12] Shermal Fernando, Color Detection & Object Tracking, http://opencv-srf.blogspot.ro/
[13] Mike Bjorge, Billiards & Computer Vision: Part 4 – Object Detection, http://www.mbjorge.com/
[14] ***, Tracking colored objects in OpenCV, http://www.globlib4u.wordpress.com
Copyright Notice
© Licențiada.org respectă drepturile de proprietate intelectuală și așteaptă ca toți utilizatorii să facă același lucru. Dacă consideri că un conținut de pe site încalcă drepturile tale de autor, te rugăm să trimiți o notificare DMCA.
Acest articol: Aplicatie Pentru Studiul Gesturilor (ID: 149470)
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.
