Documente Academic
Documente Profesional
Documente Cultură
Îndrumar de Laborator
http://rovis.unitbv.ro
Control
robotic
Imagine
Segmentarea
A Estimarea Estimarea Estimare
Achizi܊ie ܈i
Geometriei Mi܈cării Volumetrică
Imagini Imagine Clasificarea
Scenei Camerei 3D
Obiectelor
B
Informa܊ie de reac܊ie
2 Manipularea imaginilor 15
2.1 Baze teoretice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.1.1 Reprezentarea imaginilor . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.1.2 Filtrarea imaginilor . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2.2 Cerinţe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.3 Codul sursă al aplicaţiei . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
2.4 Descrierea funcţiilor principale . . . . . . . . . . . . . . . . . . . . . . . . . . 19
4 Detectarea cantelor 29
4.1 Baze teoretice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
4.1.1 Calculul gradientului ı̂ntr-o imagine . . . . . . . . . . . . . . . . . . . 29
4.1.2 Detectorul de cante Canny . . . . . . . . . . . . . . . . . . . . . . . . 30
4.1.3 Transformata Hough . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
4.2 Cerint, e . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
4.3 Codul sursă al aplicat, iei . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
4.4 Descrierea funct, iilor principale . . . . . . . . . . . . . . . . . . . . . . . . . . 34
10 Urmărirea formelor 69
10.1 Baze teoretice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
10.1.1 Estimatori de stare şi urmărirea formelor . . . . . . . . . . . . . . . . 69
10.1.2 Filtrul Kalman . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
10.2 Cerinţe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
10.3 Codul sursă al aplicat, iei . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
10.4 Descrierea funct, iilor principale . . . . . . . . . . . . . . . . . . . . . . . . . . 75
Bibliografie 77
2 CUPRINS
1. Proiectarea unei aplicaţii de vedere
artificială
Scopul acestui laborator este acela de a se introduce principalele elementele ale librăriei
OpenCV, dintre acestea amintind: citirea, afişarea sau salvarea imaginilor. Primii paşi ı̂n
dezvoltarea unei aplicaţii care are la bază librăria amintită sunt aceia de instalare a librăriei
şi de configurare a unui proiect ı̂ntr-un mediu de dezvoltare software (IDE) (de ex. MS
Visual Studio, Eclipse). Pe parcursul laboratoarelor prezentate ı̂n acest ı̂ndrumar se va
folosi sistemul Microsoft Visual C++ 2010.
opencv calib3d, dezvoltat pentru calibrarea camerelor şi estimarea geometriei scenelor,
prin utilizarea de camere stereo;
opencv video, utilizat pentru estimarea mişcării şi urmărirea formelor;
opencv objdetect, care conţine funcţii pentru detectarea obiectelor, precum şi re-
cunoaşterea persoanelor, respectiv a feţelor;
opencv ml, ı̂n acest modul se găsesc algoritmii de inteligenţă artificială;
opencv flann, este utilizat pentru implementarea metodelor de calcul geometric (ex.
determinarea celui mai apropiat vecin ı̂n spaţiul 3D);
opencv gpu, necesar stocării funcţiilor implementate pe structuri de calcul paralel 2 ;
opencv legacy, utilizat pentru a se realiza o compatibilizare a noilor versiuni cu vechile
variante ale librăriei OpenCV.
Fiecare dintre modulele menţionate anterior au câte un fişier header asociat, localizat
ı̂n directorul include. În mod tipic, un program ı̂n OpenCV va ı̂ncepe prin includerea
modulelor necesare aplicaţiei, spre exemplu:
1 #include <opencv2 / core / core . hpp>
2 #include <opencv2 / imgproc / imgproc . hpp>
3 #include <opencv2 / highgui / highgui . hpp>
Un program OpenCV ce ı̂ncepe cu header-ul:
1 #include "cv.h"
reprezintă o aplicaţie dezvoltată cu o versiune veche a librăriei.
Versiunea cea mai recentă a codului librăriei OpenCV poate fi descărcată, utilizându-
se sistemul de management al codului sursă GIT, de la adresa git://code.opencv.org/
opencv.git
2
Eng. Graphical Processing Unit
Mediul de programare MS Visual C++ 5
Fig. 1.2 Crearea unui proiect nou ı̂n MS Visual Studio C++ 2010.
foii de proprietăţi şi a se selecta opţiunea VC++ Directories, după cum este exemplificat
ı̂n Fig. 1.6.
Se editează câmpul Include Directories, accesibil din nodul VC++ Directories (v.
Fig. 1.7), prin adăugarea căilor către fişierele include din librăria OpenCV (v. Fig. 1.8).
Este necesară efectuarea aceleiaşi operaţii şi pentru câmpul Library Directories, prin
adăugarea căilor către fişierele de tip librărie din OpenCV (v. Fig. 1.9).
Este important de remarcat faptul că ı̂n foaia de proprietăţi setarea locaţiilor fişierelor
OpenCV a fost realizată prin căi explicite. În general, este cel mai indicat să se utilizeze vari-
abile de sistem 4 pentru a se desemna locaţia librăriei OpenCV. În acest fel, ı̂n cazul ı̂n care
se doreşte schimbarea versiunii librăriei (spre exemplu de la OpenCV 2.4 la OpenCV 2.5), nu
trebuie decât să setaţi variabilele care pointează către locaţia dorită. De asemenea, ı̂n cazul
dezvoltării de software ı̂n echipă, diferiţi utilizatori ı̂şi pot instala OpenCV ı̂n locaţii diferite.
Utilizându-se o variabilă de sistem, este evitată editarea foii de proprietăţi de către fiecare
utilizator ı̂n parte. În consecinţă, dacă este definită o variabila de sistem OPENCV DIR care
pointează către locaţia C:\OpenCV 2.4, atunci cele două directoare care trebuiesc specificate
ı̂n foaia de proprietăţi vor fi (OPENCV DIR)\include şi (OPENCV DIR)\lib.
Următorul pas este de a se specifica care fişiere ale librăriei OpenCV vor fi necesare
link-editării, ı̂mpreună cu codul sursă, pentru a se putea crea aplicaţia executabilă. Astfel,
vor fi necesare diferite module din OpenCV, ı̂n funcţie de aplicaţia de vedere artificială care
urmează a fi creată. Deoarece se doreşte utilizarea aceleiaşi foi de proprietăţi pentru toate
4
Eng. Environment Variables
8 PROIECTAREA UNEI APLICAŢII DE VEDERE ARTIFICIALĂ
proiectele, se vor adăuga acele librarii care vor fi utilizate de-a lungul lucrărilor din acest
ı̂ndrumar. După cum se poate vedea ı̂n Fig. 1.10, acest lucru este posibil din opţiunea Input
a nodului Linker.
Este necesară editarea câmpului Additional Dependencies (v. Fig. 1.11), prin adăugarea
modulelor opencv core, opencv imgproc, opencv highgui, opencv features2d şi opencv c
alib3d.
Se poate observa că la finalul numelor librăriilor este adăugată litera ”d”. Acestea
reprezintă librăriile pentru modul Debug. În situaţia ı̂n care este utilizat modul Release,
este necesară crearea unei noi foi de proprietăţi, aproape identică cu aceea de Debug (este uti-
lizată aceeaşi procedură), dar adăugată la nodul Release|Win32. În modul Release numele
librăriilor nu se mai termină cu litera ”d”.
În acest moment au fost introduse toate noţiunile necesare pentru a se crea, compila şi rula
prima aplicaţie de vedere artificială. Adăugarea unui nou fişier sursă poate fi realizată prin
utilizarea modulului Solution Explorer şi efectuarea unui click-dreapta pe nodul Source
Files. Este selectată opţiunea Add New Item, unde se specifică noul fişier sursă C++, cu
numele main.cpp, aşa cum este ilustrat ı̂n Fig. 1.12. Un nou fişier poate fi, de asemenea,
adăugat prin alegerea opţiunii File|New|File.
În Fig. 1.13 este prezentat codul sursă al unei aplicaţii care ı̂ncarcă şi afişează o imagine
de pe disc. Rezultatul execuţiei programului este afişat ı̂n Fig. 1.14.
Configurarea unui proiect ı̂n MS Visual C++ 9
Fig. 1.8 Adăugarea căilor către fişierele include din libraria OpenCV.
Fig.
g 1.10 Selectarea opţiunii
p¸ p al nodului Linker.
Input
Fig. 1.11 Adăugarea modulelor OpenCV necesare lucrărilor din prezentul ı̂ndrumar.
12 PROIECTAREA UNEI APLICAŢII DE VEDERE ARTIFICIALĂ
1.4 Cerinţe
Să se realizeze citirea şi afişarea unei imagini de pe HDD.
Codul sursă pentru ı̂ncărcarea şi afişarea unei imagini 13
Fig. 1.14 Rezultatul executării aplicaţiei având codul sursă listat ı̂n Fig 1.13.
29 return 0 ;
30 }
1.6 Descrierea funcţiilor principale
Reprezentarea imaginilor
Accesarea pixelilor unei imagini
Conversia imaginilor şi spatii de culoare (Gri, RGB, HSV)
Filtrarea spatială a imaginilor (filtrul median, filtrul Gaussian)
În această aplicaţie se vor prezenta diferite forme de reprezentare a imaginilor, modalităţi
de reprezentare a culorilor, cât şi două metode de filtrare spat, ială a imaginilor, mai exact
filtrul median şi filtrul Gaussian.
0 ≤ f (x, y) ≤ L − 1. (2.2)
Valoarea lui L este, ı̂n general, 256 pentru imagini gri. Acest proces de reprezentare a
imaginilor, denumit eşantionare, este exemplificat ı̂n Fig. 2.2 pentru cazul unei imagini de
nivel gri definită pe 8 biţi.
În cazul imaginilor color, f (x, y) va conţine cele trei culori fundamentale (Roşu, Albastru
şi Verde), ea putând fi reprezentată matematic ı̂n două forme:
– prin intercalarea pixelilor, unde fiecare linie este o matrice 2D, cu fiecare element
reprezentând o listă cu trei valori;
– prin intercalarea culorilor, unde pe fiecare linie datele sunt separate ı̂n matrici 2D, câte
una pentru fiecare canal de culoare:
fRGB (x, y) = fr (x, y), fg (x, y), fb (x, y) . (2.3)
Originea imaginii
0 1 2 3 N-1
0 Y
{
1
2
3
Pixelii
imaginii
M-1
f (x,y)
X
utilizat model al culorilor, din categoria orientată spre hardware, este modelul RGB (Red,
Green, Blue). Acest model este utilizat ı̂n special la monitoarele color dar şi la o clasă largă
de camere video. Reprezentarea imaginilor se poate realiza şi prin alte modele de culori,
dintre care se pot aminti: HSV (Hue, Saturation, Value), CMY (Cyan, Magenta, Yellow ),
sau Lab. Dintre acestea, modelul HSV este un model de reprezentare ce se aseamănă cu
modul de vedere uman [6], iar modelul CMY este utilizat manipularea datelor ı̂n imprimante
color.
Fig. 2.3 Reprezentarea operat, iei de filtrare spat, ială a unei imagini.
Filtrul median este reprezentat de acea mască ı̂n care toţi coeficienţii sunt egali:
⎡ ⎤
1/9 1/9 1/9
⎢1/9 1/9 1/9⎥
w(x, y) = ⎣ ⎦. (2.5)
1/9 1/9 1/9
2.2 Cerinţe
1. Să se ı̂ncarce şi să se afişeze o imagine color;
2. Să se convertească imaginea color ı̂ntr-o imagine gri;
3. Să se convertească imaginea color ı̂n spaţiul de culoare HSV;
În acest laborator va fi prezentată o metodă de analiză a unei imagini gri, prin partiţionarea
histogramei. După ce operaţia de segmentare a fost aplicată, obiectele din imaginea binară
vor fi extrase folosindu-se analiza contururilor.
1, if f (x, y) ≥ TG ,
tG (x, y) = (3.1)
0, if f (x, y) < TG ,
unde tG (x, y) reprezintă imaginea binară de ieşire. În Fig. 3.1 sunt exemplificaţi paşii
operaţiei de partiţionare prin regiuni a unei imagini gri.
O cerinţă ı̂n segmentarea imaginilor folosind doar un singur threshold este ca imaginea
de intrare să conţină un singur obiect vizualizat, pe fondul unui fundal uniform. Această
1
Eng. Thresholding
22 SEGMENTAREA PRIN PARTIŢIONARE
Fig. 3.1 Segmentarea unei imagini gri. (a) Imaginea de intrare. (b) Histograma imaginii de intrare.
(c) Rezultatul partiţionării imaginii de intrare prin valoarea de threshold TG = 42.
Fig. 3.2 Partiţionarea unei histograme printr-un interval de segmentare T = [Tlow , Thigh ].
problemă poate fi soluţionată prin definirea unui interval de partiţionare T = [Tlow , Thigh ]:
1, if f (x, y) ∈ T ,
t(x, y) = (3.2)
0, if f (x, y) ∈
/ T,
unde f (x, y) reprezintă valoarea unui pixel la coordonatele (x, y) din imagine. Tlow şi Thigh
sunt valorile minime şi maxime ale intervalului de partiţionare aplicat histogramei imaginii
f (x, y). Un exemplu de partiţionare a unei histograme printr-un interval de partiţionare este
ilustrat ı̂n Fig. 3.2.
O metodă automată de partiţionare a histogramei este aşa numitul threshold adaptiv,
care partiţionează imaginea având ı̂n vedere o ferestră glisantă, sau mască [6]. Valoarea
optimală de threshold Topt este calculată ı̂n funcţie de media aritmetica a valorilor pixelilor
din mască.
O metoda des ı̂ntâlnită ı̂n procesele de extragere a contururilor este aşa numita metodă
de codare a lanţurilor 4 . Prin codarea lanţurilor marginea unui obiect este descrisă de o
secvenţă conectată de segmente de linii drepte care au o direcţie şi o lungime specifică. De
obicei, metoda are la bază conectivitatea segmentelor dintre pixelii cu 4 sau 8 vecini. În
această reprezentare, denumita şi codare a lanţurilor tip Freeman 5 , direcţia fiecărui segment
este codată sub forma unei secvenţe de numere direcţionale, de la un pixel la următorul [6].
Un exemplu de codare a direcţiei bazată pe 8 vecini a obiectului sintetic din Fig. 3.3 este:
000060667764566444444242222202202
0 0 0 0
0 2 6 0
2 6
0 2 6
7
2
7
2
2 6
2 5 4
2 6
4 2 6
4 4 4 4 4 4
Fig. 3.3 Codarea directiei bazata pe 8 vecini a marginii unui obiect segmentat.
O asemenea margine digitală poate fi ulterior aproximată printr-un poligon. Obiectivul
aproximării poligonale este acela de a se transforma marginea codată extrasă ı̂ntr-o formă
care să descrie esenţa marginii obiectului cu cel mai mic număr de segmente posibil. O
metodă utilizată cu precădere ı̂n aproximarea poligonală presupune descrierea marginilor
unui obiect prin poligonul de perimetru minim 6 [6]. Din poligonul obţinut, un număr de
atribute pot fi extrase, ca de exemplu aria, perimetrul, diametrul, axa majoră şi axa minoră
ı̂mpreună cu excentricitatea (raportul dintre axele majoră şi minoră), curbura, etc.
3.2 Cerinţe
1. Să se ı̂ncarce şi să se convertească o imagine color ı̂ntr-una gri;
2. Să se calculeze histograma imaginii;
3. Să se segmenteze imaginea utilizându-se datele din histogramă;
4. Să se extragă contururile din imaginea segmentată;
5. Să se calculeze aria şi perimetrul contururilor detectate.
57 // Imaginea de a f i s a r e a h i s t o g r a m e i i m a g i n i i
58 Mat matHistImg = Mat : : zeros ( 2 0 0 , 2 5 5 , CV_8UC1 ) ;
59
60 // Desenarea comp on en t e l or h i s t o g r a m e i
61 for ( int i = 0 ; i < vPixelsVector . size ( ) ; i++)
62 line ( matHistImg ,
63 Point ( i , matHistImg . rows ) ,
64 Point ( i , 200 − ( int ) ( vPixelsVector . at ( i ) ) / 1 0 0 ) ,
65 Scalar ( 2 5 5 , 1 0 0 , 1 0 ) ) ;
66
67 // A f i s a r e a h i s t o g r a m e i
68 imshow ( " HistImg " , matHistImg ) ;
69 waitKey ( ) ;
70
71 // A p l i c a r e t h r e s h o l d
72 Mat matThreshold = Mat : : zeros ( matImg_in . size ( ) , CV_8UC1 ) ;
73 threshold ( matImgGray , matThreshold , 4 2 , 2 5 5 , CV_THRESH_BINARY_INV ) ;
74
75 // A f i s a r e a i m a g i n i i s e g m e n t a t e
76 imshow ( " ThImage " , matThreshold ) ;
77 waitKey ( 0 ) ;
78
79 /*
80 * Cautare c o n t u r u r i .
81 * F i e c a r e c o n t u r va f i s a l v a t i n t r −un vecor , numit c o n t o u r s .
82 * F i e c a r e c o n t u r r e p e z i n t a , de f a p t , un v e c t o r de puncte .
83 */
84 findContours ( matThreshold , contours , hierarchy , CV_RETR_TREE , ←
CV_CHAIN_APPROX_SIMPLE , Point ( 0 , 0 ) ) ;
85
86 // Desenarea f i e c a r u i contur , f o l o s i n d o c u l o a r e g e n e r a t a a l e a t o r
87 for ( int i = 0 ; i< contours . size ( ) ; i++ )
88 {
89 Scalar color = Scalar ( 1 0 0 , 1 0 , 255 ) ;
90 drawContours ( matImg_in , contours , i , color , 2 , 8 , hierarchy ) ;
91 imshow ( " Contur " , matImg_in ) ;
92 waitKey ( ) ;
93 }
94
95 // C a l c u l u l a r i e i f i e c a r u i c o n t u r
96 for ( int i = 0 ; i< contours . size ( ) ; i++ )
97 {
98 double area = contourArea ( contours . at ( i ) ) ;
99 cout << "Aria conturului " << i << " = " << area << endl ;
100 }
101
102 // C a l c u l u l p e r i m e t r u l f i e c a r u i c o n t u r
103 for ( int i = 0 ; i< contours . size ( ) ; i++ )
104 {
105 double perimeter = arcLength ( contours . at ( i ) , true ) ;
106 cout << " Perimetrul conturului " << i << " = " << perimeter << ←
endl ;
26 SEGMENTAREA PRIN PARTIŢIONARE
107 }
108
109 imshow ( " Imagine Contur " , matImg_in ) ;
110 waitKey ( 0 ) ;
111 }
3.4 Descrierea funcţiilor principale
62 void line ( Mat& img , Point pt1 , Point pt2 , const Scalar& color , int ←
thickness =1)
Desenează o linie care conectează două puncte.
img: imaginea pe care va fi desenată linia;
pt1: punctul de start;
pt2: punctul de oprire;
color: culoarea liniei;
thickness: grosimea liniei.
73 double threshold ( InputArray src , OutputArray dst , double thresh , ←
double maxval , int type )
Aplică un threshold cu valoare fixă asupra tuturor pixelilor din imagine
src: imaginea de intrare;
dst: imaginea rezultată;
thresh: valoarea de threshold;
maxval: valoarea maximă care urmează a fi utilizată cu parametrul type de tipul
THRESH BINARY sau THRESH BINARY INV;
type: poate fi utilizat unul dintre următoarele tipuri de threshold:
– THRESH BINARY pentru:
În această lucrare vor fi studiate metode de detectare a cantelor prin evaluarea gradi-
entului intensităt, ii pixelilor dintr-o imagine s, i segmentarea muchiilor obiectelor. Liniile din
imagine vor fi determinate utilizându-se evaluarea proprietăt, ii de coliniaritate a pixelilor
obiect folosind transformata Hough.
Fig. 4.1 Detectarea tranzit, iilor brus, te ı̂ntr-o imagine gri (sursa [6]).
30 DETECTAREA CANTELOR
α(x, y) = tan−1 gx /gy , (4.4)
unde gx s, i gy sunt direct, iile orizontale s, i verticale ale imaginii gradient.
Cantele obt, inute sunt subt, iate folosind supresia non-maxima, adică patru ferestre filtru
sunt utilizate ı̂n specificarea unui număr de orientări discrete ale normalei cantei: orizontală,
verticală, +45◦ s, i −45◦ .
În final, imaginea gri obt, inută este binarizată folosind as, a numita tehnică de partit, ionare
prin histerezis, ce utilizează doua valori de partit, ionare: nivel jos TL s, i nivel sus TH . Pixelii cu
o valoare peste TH sunt considerat, i pixeli apart, inând cantelor ”puternici ”, iar cei cu o valoare
sub TL sunt considerat, i cante false. Acei pixeli ce apart, in intervalului [TL , TH ], denumit, i s, i
Baze teoretice 31
Fig. 4.2 Schema-bloc a operat, iei de segmentare a cantelor prin metoda Canny.
pixeli ”slabi ”, sunt considerat, i margini dacă sunt conectat, i deja la pixeli ”puternici”.
Potrivit [18], valoarea joasă de prag poate fi exprimată ca o funct, ie a valorii superioare:
TL = 0.4 · TH , (4.5)
Schema-bloc a metodei de segmentare a cantelor Canny este reprezentată ı̂n Fig. 4.2.
yi = axi + b, (4.6)
unde (xi , yi ) este un punct al liniei.
y b’ b
x a
(a) (b)
Fig. 4.3 Principiul transformatei Hough. (a) Planul xy al imaginii. (b) Spat, iul parametric ab.
Prin punctul (xi , yi ) trece un număr infinit de linii, toate satisfăcând ecuat, ia 4.6 cu
diferite valori ale coeficient, ilor a s, i b. Dacă ı̂n locul planului imaginii xy ecuat, ia liniei este
reprezentată ı̂n funct, ie de planul ab din Fig. 4.3(b), plan numit s, i spat, iu parametric, atunci
ecuat, ia unei singure linii pentru o pereche fixă (xi , yi ) poate fi descrisă după cum urmează:
b = −xi a + yi . (4.7)
32 DETECTAREA CANTELOR
Fig. 4.4 Schema-bloc a unui sistem de extragere a liniilor dintr-o imagine utilizând detectorul Canny
s, i transformata Hough.
După cum poate fi văzut ı̂n Fig. 4.3, dacă un al doilea punct (xj , yj ) este colinear cu
punctul (xi , yi ), atunci, ı̂n spat, iul parametric, cele doua linii corespunzătoare se intersectează
ı̂ntr-un anumit punct (a , b ).
Schema bloc completă a unui sistem de detectare a liniilor, bazat pe detectorul de cante
Canny s, i transformata Hough, poate fi văzută ı̂n Fig. 4.4.
4.2 Cerint, e
1. Să se ı̂ncarce şi să se convertească o imagine către o reprezentare cu niveluri de gri;
2. Să se calculeze gradientului imaginii utilizând filtrul SOBEL;
3. Să se detecteze cantele din imagine utilizând filtrul Laplace
4. Să se detecteze cantele din imagine utilizand filtrul Canny.
23 Mat img_filtrare_Laplace ;
24 Mat img_segmentare_Canny ;
25 string strCaleImagine ;
26
27 // I n c a r c a r e a i m a g i n i i de pe d i s k
28 if ( argc != 4 )
29 {
30 cout<<" Apelare : aplicatie <cale -imagine > <ordin -derivata > <←
dimensiune -fereastra -glisanta >"<<endl ;
31 exit ( 0 ) ;
32 }
33 else
34 {
35 strCaleImagine = argv [ 1 ] ;
36 }
37
38 img_in = imread ( strCaleImagine . c_str ( ) , CV_LOAD_IMAGE_UNCHANGED ) ;
39
40 // V e r i f i c a r e a i n c a r c a r i i c o r e c t e a i m a g i n i i
41 if ( ! img_in . data )
42 {
43 cout << " Imaginea " << strCaleImagine << " nu a putut fi ←
incarcata " << endl ;
44 return −1;
45 }
46
47 // C o n v e r s i a i m a g i n i i de i n t r a r e c o l o r i n i m a g i n e g r i
48 cvtColor ( img_in , img_out , CV_RGB2GRAY ) ;
49 imshow ( " Imagine Gri" , img_out ) ;
50 waitKey ( ) ;
51 destroyAllWindows ( ) ;
52
53 // S e l e c t i a o r d i n u l u i d e r i v a t e i
54 sscanf ( argv [ 2 ] , "%d" , &ordin_derivata ) ;
55
56 // S e l e c t i a m a r i m i i f i l t r u l u i
57 sscanf ( argv [ 3 ] , "%d" , &marime_filtru ) ;
58
59 // C a l c u l u l g r a d i e n t u l u i i m a g i n i i u t i l i z a n d f i l t r u l SOBEL
60 Sobel ( img_out , img_filtrare_Sobel , rezolutie_imagine , ←
ordin_derivata , ordin_derivata , marime_filtru ) ;
61
62 // C o n v e r s i e s c a l a
63 convertScaleAbs ( img_filtrare_Sobel , img_filtrare_Sobel ) ;
64 namedWindow ( " SOBEL " , CV_WINDOW_AUTOSIZE ) ;
65 imshow ( " SOBEL" , img_filtrare_Sobel ) ;
66 waitKey ( ) ;
67 destroyAllWindows ( ) ;
68
69 // D e t e c t a r e a c a n t e l o r u t i l i z a n d f i l t r u l L a p l a c e
70 Laplacian ( img_out , img_filtrare_Laplace , rezolutie_imagine , ←
marime_filtru , 1 , 0 , BORDER_DEFAULT ) ;
34 DETECTAREA CANTELOR
71
72 // C o n v e r s i e s c a l a
73 convertScaleAbs ( img_filtrare_Laplace , img_filtrare_Laplace ) ;
74 namedWindow ( " LAPLACE " , CV_WINDOW_AUTOSIZE ) ;
75 imshow ( " LAPLACE " , img_filtrare_Laplace ) ;
76 waitKey ( ) ;
77 destroyAllWindows ( ) ;
78
79 // D e t e c t a r e a c a n t e l o r u t i l i z a n d f i l t r u l Canny
80 Canny ( img_out , img_segmentare_Canny , threshold_canny_high * 0 . 7 , ←
threshold_canny_high , marime_filtru ) ;
81 namedWindow ( " Filtru Canny " , CV_WINDOW_AUTOSIZE ) ;
82 imshow ( " Filtru Canny" , img_segmentare_Canny ) ;
83 waitKey ( ) ;
84 destroyAllWindows ( ) ;
85
86 // C a l c u l u l l i n i i l o r p r i n t r a n s f o r m a t a Hough
87 HoughLinesP ( img_segmentare_Canny , linii_hough , 1 , CV_PI / 1 8 0 , ←
threshold_hough , 1 0 0 , 2 0 ) ;
88
89 // Desenarea l i n i i l o r Hough pe i m agi n e a de i n t r a r e
90 for ( size_t i = 0 ; i < linii_hough . size ( ) ; i++ )
91 {
92 Vec4i l = linii_hough [ i ] ;
93 line ( img_in , Point ( l [ 0 ] , l [ 1 ] ) , Point ( l [ 2 ] , l [ 3 ] ) , Scalar←
( 0 , 0 , 2 5 5 ) , 3 , CV_AA ) ;
94 }
95
96 // A f i s a r e a l i n i i l o r Hough
97 imshow ( "Linii Hough " , img_in ) ;
98 waitKey ( ) ;
99
100 return 0 ;
101 }
4.4 Descrierea funct, iilor principale
60 void Sobel ( InputArray src , OutputArray dst , int ddepth , int dx , int ←
dy , int ksize =3, double scale=1)
Calculează prima, a doua sau a treia derivată a unei imagini, utilizând operatorul Sobel.
src: imaginea de intrare;
dst: imaginea de ies, ire;
ddepth: adâncimea imaginii de ies, ire (CV 8U, CV 16U, CV 16S, CV 32F, CV 64F);
xorder: ordinul derivatei pe axa x;
yorder: ordinul derivatei pe axa y;
ksize: mărimea ferestrei Sobel (trebuie să fie un număr impar: 1, 3, 5 sau 7);
scale: factor de scalare opt, ional.
63 void convertScaleAbs ( InputArray src , OutputArray dst , double alpha=1)
Scalează, calculează valori absolute s, i convertes, te rezultatul pe o rezolut, ie de 8-bit, i.
src: imaginea de intrare;
dst: imaginea de ies, ire;
Descrierea funct, iilor principale 35
În acest laborator va fi prezentată o metodă de detect, ie a corespondent, elor ı̂n imagini
stereo precum s, i modul prin care aceasta poate fi utilizată pentru a reconstrui pozit, ia 3D a
punctelor vizualizate printr-o cameră stereo.
unde w reprezintă o mască de netezire de formă circulară. De obicei, w este o mască Gaus-
siană de forma:
1 x2 +y 2
w(x, y) = exp− 2σ2 (5.3)
2πσ
unde σ reprezintă deviat, ia standard sau scara de netezire.
În implementarea detectorului Harris se pot distinge două etape:
prima, ı̂n care sunt calculate valorile funct, iilor de autocorelaţie pentru fiecare pixel din
imagine;
a doua, unde este determinat un maxim local al funct, iei de autocorelaţie ı̂ntr-o vecinătate
definită de utilizator. Pixelii asociat, i acestor valori de maxim local sunt considerat, i ca
fiind colt, uri.
Variaţia intensităţii pixelilor din imagine poate fi calculată utilizând o mască ale cărei
dimensiuni sunt alese de către utilizator. Variaţia intensităţii pixelilor survine ı̂n urma
deplasării acestei măşti pe distanţe mici de-a lungul diferitelor direcţii. Considerând o astfel
de abordare, pot exista trei cazuri distincte:
dacă masca conţine pixeli al căror nivel este apropiat de nivelul intensităt, ii imaginii,
ı̂n urma deplasării măştii ı̂n orice direcţie va rezulta o variaţie mică a acesteia;
dacă masca conţine porţiuni dintr-o imagine, o deplasare a măştii de-a lungul marginii
va conduce la variaţii mici ale intensităţii. În schimb, o deplasare perpendiculară pe
margine va conduce la obţinerea unei variaţii mari a intensităţii pixelilor;
dacă ı̂n interiorul măştii se află un colţ atunci deplasarea măştii ı̂n orice direcţie va
conduce la obţinerea unei variaţii semnificative a intensităţii. În acest caz, un colţ
poate fi determinat găsind valoarea minimă a variaţiei intensităţii.
Variat, ia intensităt, ii pixelilor (gradient, ii imaginii) pot fi reprezentat, i astfel:
∂I(x, y)
Ix = I −1 0 1 = , (5.4)
∂x
T ∂I(x, y)
Iy = I −1 0 1 = . (5.5)
∂y
Pentru variaţii mici, rezultă:
Ix2 Ix Iy Δx
E(Δx, Δy) = Δx Δy . (5.6)
Iy Ix Iy2 Δy
5.1.2 Reconstruct, ia 3D
Principiile de bază ale reconstruct, iei stereo sunt ilustrate grafic ı̂n Fig. 5.2. Punctele
pL şi pR reprezintă proiecţia punctului 3D (P ) ı̂n planurile imaginilor celor două camere
(stângă s, i dreaptă), fiecare senzor având propriul punct de vizualizare. Reconstruct, ia stereo
a punctului tridimensional X este dată de proiecţia razelor, ilustrate prin linie punctată ı̂n
Fig. 5.2, ce pleacă din centrele optice cL şi cR ale camerelor şi trec prin punctele xL şi xR .
Matricea de proiecţie descrie configurat, ia unei camere ı̂n lumea reală. Aceasta este rezul-
Baze teoretice 39
pL=QL·P pR=QR·P
cR
cL
Camera Camera
stângă dreaptă
Fig. 5.2 Reconstrucţia unui punct 3D (P ) din punctele vizualizate 2D pL şi pR , achizit, ionate de la
o cameră stereo cu matricele de proiecţie QL şi QR cunoscute.
tatul unui proces de calibrare a camerei. În cazul unei camere stereo sunt folosite două
matrice de proiecţie, una pentru senzorul stâng QL şi una pentru cel drept QR . În funct, ie
de semnificat, ia lor, parametrii matricei de proiect, ie pot fi clasificat, i după cum urmează:
parametri intrinseci (Cint ), ce descriu caracteristicile interne ale camerei, precum distant, a
focală, intersect, ia axei optice cu planul imaginii şi aspectul pixelilor, etc.;
parametri extrinseci (Cext ), ce reprezintă o transformare omogenă ı̂ntre poziţia şi ori-
entarea camerei ı̂n raport cu un sistem de coordonate de referinţă.
Atunci când ambii parametri, intrinseci şi extrinseci, sunt cunoscuţi, matricea de proiecţie
a unei camere poate fi determinată cu următoarea relaţie:
b
X = xL · , (5.9)
d
b
Y = yL · , (5.10)
d
b
Z=f· , (5.11)
d
unde X, Y , Z sunt coordonatele 3D ale punctului P reprezentat ı̂n coordonate omogene, iar
d reprezintă disparitatea. În cazul de fat, ă, disparitatea reprezinta diferent, a dintre proiect, ia
punctului P ı̂n imaginea dreapta s, i proiact, ia sa ı̂n imaginea stângă, de-a lungul axei x. Cu
cât d este mai mare, cu atât punctul este mai aproape de cameră. Disparitatea poate fi
determină după cum urmează [7]:
d = xL − xR . (5.12)
Cu ajutorul relaţiilor (5.9) ÷ (5.11) se poate trage concluzia că distanţa Z este invers
proporţională cu disparitatea, iar coordonatele X şi Y ale sistemului de referinţă depind
doar de valoarea variabilei d şi de distanţa dintre cele două camere.
5.2 Cerint, e
1. Să se citească de pe HDD o pereche de imagini stereo;
2. Să se detecteze colt, urile din imaginea stângă;
3. Să se determine corespondent, ele dintre imaginea stânga s, i cea dreaptă;
4. Să se determine coordonatele 3D ale corespondent, elor determinate la punctul 3.
22 if ( argc != 3 )
23 {
24 std : : cout<<" Usage : aplicatie <cale - imagineStanga > <cale -←
imaginereapta >"<<std : : endl ;
25 exit ( 0 ) ;
26 }
27 else
28 {
29 strCaleImagineStanga = argv [ 1 ] ;
30 strCaleImagineDreapta = argv [ 2 ] ;
31 }
32 // I m a g i n i de i n t r a r e
33 Mat ImagineStanga = imread ( strCaleImagineStanga . c_str ( ) , ←
CV_LOAD_IMAGE_GRAYSCALE ) ;
34 Mat ImagineDreapta = imread ( strCaleImagineDreapta . c_str ( ) , ←
CV_LOAD_IMAGE_GRAYSCALE ) ;
35
36 // Corespondente s t e r e o
37 std : : vector<Point2f> CorespondenteStanga ;
38 std : : vector<Point2f> CorespondenteDreapta ;
39 std : : vector<uchar> nStatus ;
40
41 int nNoMaximCorespondente ( 1 ) ;
42 std : : vector<float> fFeatureErrors ;
43
44 // D e t e c t a r e a c o l t u r i l o r d i n i m a g i n e a s t a n g a
45 goodFeaturesToTrack ( ImagineStanga ,
46 CorespondenteStanga ,
47 nNoMaximCorespondente ,
48 0.01 ,
49 5.0) ;
50
51 // Determinarea c o r e s p o n d e n t e l o r d i n t r e i m a g i n e a s t a n g a s i c e a ←
dreapta
52 calcOpticalFlowPyrLK ( ImagineStanga ,
53 ImagineDreapta ,
54 CorespondenteStanga ,
55 CorespondenteDreapta ,
56 nStatus ,
57 fFeatureErrors ) ;
58
59 std : : cout << "No corespondente = " << CorespondenteStanga . size ( ) ←
<< std : : endl << std : : endl ;
60
61 // R e c o n s t r u c t i a 3D
62 for ( int i = 0 ; i < CorespondenteStanga . size ( ) ; i++)
63 {
64 float fDisparitate = CorespondenteStanga [ i ] . x − ←
CorespondenteDreapta [ i ] . x ;
65
66 X = CorespondenteStanga [ i ] . x * ( fLiniaDeBaza / fDisparitate ) ;
67 Y = CorespondenteStanga [ i ] . y * ( fLiniaDeBaza / fDisparitate ) ;
42 CORESPONDENŢE STEREO ŞI RECONSTRUCŢIA 3D A UNEI SCENEI
În acest laborator se vor analiza datele achiziţionate utilizându-se senzori cu lumină struc-
turată. Datele furnizate de astfel de senzori sunt compuse din informaţie vizuală, reprezen-
tată sub formă de imagini RGB, cât şi din distanţele cameră-suprafaţa vizualizată. Aceste
distanţe sunt codate sub forma unui canal adiţional D. Procesarea informat, iei vizuale 3D
se va efectua cu ajutorul librăriei Point Cloud Library (PCL) http://pointclouds.org/.
Instalarea ei se face ı̂n mod similar cu instalarea librăriei OpenCV, descrisă ı̂n aplicat, ia 1 a
acestui ı̂ndrumar.
(a)
(b)
Fig. 6.1 Exemple de nori de puncte 3D.
pi = [f0 , f1 , f2 , . . . , fn ], (6.2)
unde fj reprezintă o caracteristică ı̂ntr-un anumit spaţiu de caracteristici, spre exemplu
poziţie, culoare, clasa de apartenenţă, etc. Structura unui nor de puncte P poate fi stocată
Cerinţe 45
⎡ ⎤
x 1 y 1 z 1 r 1 g 1 b 1 n x1 n y 1 n z 1 e1 d1 ···
⎢ ⎥
⎢ x 2 y 2 z 2 r 2 g 2 b 2 n x2 n y 2 n z 2 e2 d2 ··· ⎥
P =⎢
⎢
⎥. (6.3)
⎣ ··· ⎥
⎦
x N p y N p z N p r N p g N p b N p n x N p n yN p n z N p e N p d Np ···
6.2 Cerinţe
1. Utilizându-se librăria PCL, să se ı̂ncarce de pe HDD un nor de puncte RGB-D;
2. Să se elimine din nor punctele care nu conţin informaţie de adâncime;
3. Să se vizualizeze norul de puncte ı̂ncărcat;
3. Să se identifice centrul de greutate al norului de puncte;
4. Să se translateze norul ı̂n originea sistemului de coordonate;
5. Să se vizualizeze norul de puncte translatat.
24 if ( argc != 2 )
25 {
26 cout<<" Usage: aplicatie <cale -fisier -RGBD >"<<endl ;
27 exit ( 0 ) ;
28 }
29 else
30 {
31 strCaleFisier = argv [ 1 ] ;
32 }
33
34 // I n c a r c a r e a unui nor de puncte 3D u t i l i z a n d l i b r a r i a PCL
35 if ( io : : loadPCDFile ( strCaleFisier . c_str ( ) , * nor_puncte ) )
36 cout << " Norul de puncte nu a putut fi citit." << endl ;
37 else
38 cout << " Norul de puncte contine : " << nor_puncte−>points . ←
size ( ) << " puncte 3D " << endl ;
39
40 // E l i m i n a r e a p u n c t e l o r cu v a l o a r e n u l a
41 vector <int> vIndex ;
42 removeNaNFromPointCloud ( * nor_puncte , * nor_puncte , vIndex ) ;
43 cout<<" Norul de puncte filtrat contine : " << nor_puncte−>points . ←
size ( ) << " puncte 3D " << endl ;
44
45 // V i z u a l i z a r e a n o r u l u i de puncte 3D
46 visualization : : CloudViewer viewer ( " Viualizarea grafica a norului←
de puncte " ) ;
47 viewer . showCloud ( nor_puncte ) ;
48 while ( ! viewer . wasStopped ( ) )
49 {}
50
51 // Determinarea c e n t r u l u i de g r e u t a t e a l s c e n e i
52 float fSumX = 0 . 0 f , fSumY = 0 . 0 f , fSumZ = 0 . 0 f ;
53
54 for ( unsigned int a = 0 ; a < nor_puncte−>points . size ( ) ; a ++)
55 {
56 fSumX += nor_puncte−>points [ a ] . x ;
57 fSumY += nor_puncte−>points [ a ] . y ;
58 fSumZ += nor_puncte−>points [ a ] . z ;
59 }
60 cout<<" Coordonate centru de greutate (X, Y, Z): " <<
61 fSumX / nor_puncte−>points . size ( ) << ", " <<
62 fSumY / nor_puncte−>points . size ( )<< " , "<<
63 fSumZ / nor_puncte−>points . size ( ) << endl ;
64
65 // S a l v a r e a c o o r d o n a t e l o r c e n t r u l u i de g r e u t a t e
66 ptCentruDeGreutate . x = fSumX / nor_puncte−>points . size ( ) ;
67 ptCentruDeGreutate . y = fSumY / nor_puncte−>points . size ( ) ;
68 ptCentruDeGreutate . z = fSumZ / nor_puncte−>points . size ( ) ;
69
70 // T r a n s l a t o a r e a n o r u l u i de puncte i n c o o r d o n a t e l e de o r i g i n e a l e ←
scenei
71 PointXYZ ptTranslation ;
Descrierea funcţiilor principale 47
72 ptTranslation . x = 0 − ptCentruDeGreutate . x ;
73 ptTranslation . y = 0 − ptCentruDeGreutate . y ;
74 ptTranslation . z = 0 − ptCentruDeGreutate . z ;
75
76 for ( unsigned int b = 0 ; b < nor_puncte−>points . size ( ) ; b++)
77 {
78 nor_puncte−>points [ b ] . x += ptTranslation . x ;
79 nor_puncte−>points [ b ] . y += ptTranslation . y ;
80 nor_puncte−>points [ b ] . z += ptTranslation . z ;
81 }
82
83 // V i z u a l i z a r e a n o r u l u i de puncte 3D
84 visualization : : CloudViewer viewer_2 ( " Viualizarea grafica a ←
norului de puncte " ) ;
85 viewer_2 . showCloud ( nor_puncte ) ;
86 while ( ! viewer_2 . wasStopped ( ) )
87 {}
88
89 return 0 ;
90 }
6.4 Descrierea funcţiilor principale
În lucrarea de fat, ă se vor studia metode de măsurare a distant, elor ı̂n interiorul norilor
de puncte 3D, estimarea rotat, iei s, i translat, iei dintre diferite densităt, i de puncte 3D, cât s, i
potrivirea a două densităt, i de puncte utilizându-se algoritmul Iterative Closest Point (ICP).
potrivire globală, ı̂n care alinierea se produce ı̂ntre două suprafet, e cu structură constructivă
similară, ca s, i dimensiune (de exemplu, două siluete ale aceleias, i căni). Principial, cele 6
grade de libertate necesare unui proces de potrivire, 3 pentru rotat, ie s, i 3 pentru translat, ie,
sunt determinate utilizându-se corespondent, e de tipul celui mai apropiat vecin.
Punctul din P care satisface condit, ia de cel mai apropiat vecin se notează cu y. Acesta
trebuie să respecte condiţia d(m, y) = d(m, P ), unde y ∈ P .
Din punctul de vedere al intervalului de calcul, identificarea lui y se realizează ı̂n maxim
O(Np ), iar timpul total (a tuturor punctelor din M ) este reprezentat de O(Nm Np ). Cu toate
acestea, timpul de calcul estimat este O(log(Np ) · log(Np )). Fie Y un vector care conţine cele
Baze teoretice 51
mai apropiate puncte s, i C operatorul de cel mai apropiat punct, atunci se poate considera:
Y = C(M, P ). (7.4)
Cunoscând vectorul celor mai apropiate puncte Y , alinierea celor două suprafet, e, uti-
lizând metoda celor mai mici pătrate, se calculează după cum urmează:
Vedere laterală
(b) (c)
Fig. 7.1 Alinierea a două suprafet, e cu siluete similare. (a) Model translatat (M ). (b) Model de
referint, ă (P ). (c) Modele aliniate utilizându-se metoda ICP.
suprafaţă rigidă şi o suprafaţă care descrie doar o anumită regiune a acesteia, este prezentat
ı̂n figura 7.2. Eroarea de potrivire pentru cazul considerat este egală cu 7.489 · e−8 .
7.2 Cerinţe
1. Să se ı̂ncarce doi nori de puncte de pe HDD;
2. Să se scrie utilizeze metoda ICP din librăria PCL pentru alinierea celor doi nori de
puncte;
3. Să se translateze s, i să se rotească un nor de puncte, fat, ă de celălalt, utilizându-se
matricea de transformare returnată de algoritmul ICP.
Vedere laterala
(b) (c)
Fig. 7.2 Alinierea unei regiuni la o suprafat, ă rigidă. (a) Model translatat (M ). (b) Model de
referint, ă (P ). (c) Modele aliniate utilizându-se metoda ICP.
16 double dConvergenta ;
17 Eigen : : Matrix4f transformare_ICP ;
18 float fDistMaxACorresp = 0 . 5 f ;
19 int nMaxIteratii = 1 0 0 0 ;
20
21 Eigen : : Matrix4f AliniereICP ( PclCloud : : Ptr cloud_model , PclCloud &←
cloud_aliniat , double &dConvergenta , int nMaxIteratii , float ←
fDistMaxACorresp )
22 {
23 Eigen : : Matrix4f transformare ;
24
25 PclCloud : : Ptr pCloud_aliniat ( new PclCloud ) ;
26 copyPointCloud ( cloud_aliniat , * pCloud_aliniat ) ;
27
28 // C l a s a a l g o r i t m u l u i ICP
29 IterativeClosestPoint<PclPointType , PclPointType> icp ;
30
31 // S t a b i l i r e a n o r u l u i de r e f e r i n t a
32 icp . setInputCloud ( cloud_model ) ;
33
34 // S t a b i l i r e a n o r u l u i t r a n s l a t a t ( a l i n i a t )
35 icp . setInputTarget ( pCloud_aliniat ) ;
36
37 // C o r e s p o n d e n t e l e cu d i s t a n t a mai mare d e c a t p r a g u l s t a b i l i t vor ←
fi rejectate
54 ALINIEREA ROBUSTĂ A DENSITĂŢILOR DE PUNCTE 3D
88 }
89
90 // C i t i r e a c e l u i de−a l d o i l e a nor de puncte
91 if ( io : : loadPCDFile ( strCaleCloudB . c_str ( ) , * cloud_aliniat ) )
92 cout<<"Norul de puncte nu a putut fi citit."<<endl ;
93
94 // C o l o r a r e nor de puncte i n rosu
95 for ( unsigned int b = 0 ; b < cloud_aliniat−>points . size ( ) ; b++)
96 {
97 cloud_aliniat−>points [ b ] . r = 255;
98 cloud_aliniat−>points [ b ] . g = 0;
99 cloud_aliniat−>points [ b ] . b = 0;
100 }
101
102 // A l i n i e r e ICP
103 transformare_ICP = AliniereICP ( cloud_model , * cloud_aliniat , ←
dConvergenta , 3 0 0 , 0 . 0 5 ) ;
104
105 // O p e r a t i a de t r a n s f o r m a r e c e a l i n i a z a c l o u d a l i n i a t l a ←
cloud model
106 transformPointCloud ( * cloud_aliniat , * cloud_aliniat , ←
transformare_ICP ) ;
107
108 // S a l v a r e a n o r i l o r c l o u d m o d e l s i c l o u d a l i n i a t i n t r −un s i n g u r nor←
de puncte
109 for ( unsigned int i = 0 ; i < cloud_model−>points . size ( ) ; i++)
110 cloud_rezultat . push_back ( cloud_model−>points [ i ] ) ;
111
112 for ( unsigned int j = 0 ; j < cloud_aliniat−>points . size ( ) ; j++)
113 cloud_rezultat . push_back ( cloud_aliniat−>points [ j ] ) ;
114
115 io : : savePCDFile ( strCaleSalvareRezultat . c_str ( ) , cloud_rezultat ) ;
116
117 return 0 ;
118 }
7.4 Descrierea funcţiilor principale
În această sect, iune se va prezenta o metodă de segmentare a norilor de puncte ı̂n funct, ie
de densităt, ile de puncte ce formează diferite obiecte ı̂n scena vizualizată prin senzori de
lumină structurată.
Etapele prezentate anterior sunt efectuate de k ori. Rezultatul unui proces de segmentare
a suprafeţelor plane este prezentat ı̂n Fig. 8.1. Cu lini roşi sunt definite laturile paralelogra-
mului care defineşte suprafaţa plană estimată, ı̂n timp ce cu albastru sunt colorate punctele
3D a căror distantă faţă de planul considerat respectă condiţiile impuse (inliers).
(a) (b)
Fig. 8.1 Identificarea suprafeţelor plane din scena de lucru. (a) Norul de puncte
iniţial. (b) Suprafaţa plană estimată.
verificarea procesării tuturor punctelor din Q. Dacă această operaţie a fost făcută
cu succes Q este adăugat ı̂n lista grupurilor compacte C. Se şterge Q pentru a se
ı̂ncepe o nouă iteraţie;
4. terminarea algoritmului presupune că toate punctele din Pi să fi fost procesate, cât s, i
includerea acestora ı̂n lista de grupuri compacte C.
În Fig. 8.2 se pot observa mai multe densităţi de puncte compacte, reprezentând diferite
obiecte de uz general, extrase cu ajutorul algoritmului de estimare a grupurilor compacte de
puncte. Conform premizelor expuse anterior, obiectele au fost situate pe o suprafaţă plană
(masă).
(a) (b)
Fig. 8.2 Segmentarea prin partiţionare a norilor de puncte. (a) Nor de puncte
iniţial. (b) Grupuri (clustere) de puncte segmentate.
8.2 Cerinţe
1. Să se ı̂ncarce un nor de puncte de pe HDD;
2. Să se segmenteze suprafet, ele plane din norul de puncte;
3. Să se grupeze densităt, iile de puncte ı̂n funct, ie de distant, a euclidiană dintre ele;
4. Să se salveze s, i să se vizualizeze scene segmentată.
18
19 using namespace pcl ;
20 using namespace std ;
21
22 typedef PointXYZRGBA PclPointType ;
23 typedef PointCloud<PclPointType> PclCloud ;
24
25 PclCloud : : Ptr cloud ( new PclCloud ) ;
26 PclCloud : : Ptr cluster_cloud ( new PclCloud ) ;
27
28 void extractClusters ( PclCloud : : Ptr cloud , float fGranularitate , ←
vector<PointIndices>& indecsi_clustere , PclCloud &cloud_filtrat , ←
bool bDownsample )
29 {
30 indecsi_clustere . clear ( ) ;
31 PclCloud : : Ptr pCloud_filtrat ( new PclCloud ) ;
32
33 if ( bDownsample == true )
34 {
35 // C r e a r e a s t r u c t u r i i de d a t e c e va c o n t i n e n o r u l de puncte ←
filtrat
36 VoxelGrid<PclPointType> vg ;
37
38 vg . setInputCloud ( cloud ) ;
39
40 // A p l i c a r e a u n e i g r a n u l a r i t a t i de 1 cm
41 vg . setLeafSize ( fGranularitate , fGranularitate , fGranularitate ) ;
42 vg . filter ( * pCloud_filtrat ) ;
43 }
44 else
45 {
46 vector< int > index ;
47 removeNaNFromPointCloud ( * cloud , * pCloud_filtrat , index ) ;
48 }
49
50 // C r e a r e a s t r u c t u r i i de d a t e n e c e s a r a s e g m e n t a r i i s u p r a f e t e l o r ←
plane
51 SACSegmentation<PclPointType> seg ;
52 PointIndices : : Ptr inliers ( new PointIndices ) ;
53 ModelCoefficients : : Ptr coeficienti ( new ModelCoefficients ) ;
54 PointCloud<PclPointType > : : Ptr cloud_suprafata_plana ( new PointCloud ←
<PclPointType> ( ) ) ;
55 seg . setOptimizeCoefficients ( true ) ;
56 seg . setModelType ( SACMODEL_PLANE ) ;
57 seg . setMethodType ( SAC_RANSAC ) ;
58 seg . setMaxIterations ( 1 0 0 ) ;
59 seg . setDistanceThreshold ( 0 . 0 2 ) ;
60
61 int i=0, nr_points = ( int ) pCloud_filtrat−>points . size ( ) ;
62 while ( pCloud_filtrat−>points . size ( ) > 0 . 3 * nr_points )
63 {
64 // Segmentarea c e l e i mai mari s u p r a f e t e p l a n e
Codul sursă al aplicaţiei 61
Metode de clasificare
Detectarea fet, elor utilizând clasificatori ı̂n cascadă
În acest laborator se va studia o metodă de detectare a fet, elor ı̂n imagini gri utilizându-se
algoritmi de clasificare a caracteristicilor vizuale.
Fig. 9.1 Caracteristici de tip Haar utilizate la detectarea de obiecte [2, 16].
66 DETECTAREA FEŢELOR ÎN IMAGINI
Caracteristicile utilizate pentru prima dată ı̂n [22] şi care pot fi folosite la detectarea
fizionomiei umane au suferit o serie de modificări. Acest lucru se datorează, ı̂n principal,
faptului că la prima apariţie a metodei au fost introduse doar caracteristici rectangulare,
având o reprezentare de la două până la patru module. Asupra acestei modalităţi de re-
prezentare iniţiale au apărut modificări ı̂n [16], lucrare ı̂n care s-a eliminat modelul rec-
tangular cu patru module şi a fost definită o nouă modalitate de reprezentare, sub forma
unor caracteristici Haar rotite. Introducerea acestei noi reprezentări conduce la o creştere a
performanţelor sistemului (şi anume la reducerea numărului de detectări incorecte) cu până
la 10%. Astfel, după cum se poate vedea şi ı̂n Fig. 9.1, se poate discuta despre 14 prototipuri
de caracteristici.
9.2 Cerinţe
1. Să se ı̂ncarce o imagine color;
2. Să se convertească imaginea color ı̂ntr-o imagine gri;
3. Să se instant, ieze s, i să se ı̂ncarce un clasificator Haar de detectare a fet, elor;
4. Să se detecteze fet, ele ı̂n imaginea gri utilizând clasificatorul Haar;
5. Să se afis, eze regiunile fet, elor detectate.
32 // C o n v e r s i a i m a g i n i i c o l o r de i n t r a r e i n i m a g i n e g r i
33 Mat img_gri ;
34 cvtColor ( img_in , img_gri , CV_BGR2GRAY ) ;
35
36 // I m b u n a t a t i r e a i m a g i n i i p r i n e g a l i z a r e a h i s t o g r a m e i
37 equalizeHist ( img_gri , img_gri ) ;
38
39 // D e f i n i t i a unui v e c t o r de s t o c a r e a r e g i u n i l o r f e t e i
40 vector<Rect> regiuni_fete ;
41
42 // D e t e c t a r e a f e t e l o r u t i l i z a n d c l a s i f i c a t o r u l Haar
43 clasificator_haar . detectMultiScale ( img_gri , regiuni_fete , 1 . 1 , 2 , ←
CV_HAAR_SCALE_IMAGE , Size ( 4 0 , 4 0 ) ) ;
44
45 // Desenarea r e g i u n i l o r f e t e i
46 for ( unsigned int i = 0 ; i < regiuni_fete . size ( ) ; i++ )
47 rectangle ( img_in , regiuni_fete . at ( i ) , Scalar ( 1 0 0 , 2 5 5 , 1 5 0 ) , 2 ) ;
48
49 // A f i s a r e r e z u l t a t e
50 imshow ( " Detectia fetelor " , img_in ) ;
51 waitKey ( ) ;
52
53 return true ;
54 }
9.4 Descriere codului sursă
24 CascadeClassifier
Definirea unui obiect de tipul CascadeClassifier.
26 bool CascadeClassifier : : load ( const string& filename )
Acest apel este utilizat pentru a se ı̂ncărca clasificatorul din fişierul *.xml.
43 void CascadeClassifier : : detectMultiScale ( const Mat& image , vector<←
Rect>& objects , double scaleFactor =1.1 , int minNeighbors =3, int ←
flags =0, Size minSize=Size ( ) , Size maxSize=Size ( ) )
Realizează detectarea ı̂n imaginea de intrare a tuturor obiectelor (având dimensiuni vari-
ate) pentru care a fost clasificatorul antrenat. Obiectele detectate sunt returnate sub forma
unui vector cu dreptunghiuri (Rect).
image: imaginea de intrare;
objects: vectorul unde vor fi salvate obiectele (dreptunghiurile) detectate;
scaleFactor: acest parametru specifică cât de mult este redusă dimensiunea imagini,
pentru fiecare etapă de scalare a imagini. Alegerea unei valori mai mari are drept
rezultat reducerea timpului de calcul şi scăderea numărului de ipoteze detectate (dacă
factorul de scalare nu se ı̂ncadrează cu anumite obiecte având o dimensiune precisă);
minNeighbors: indică numărul de vecini pe care trebuie să ı̂i aibă fiecare ipoteză pen-
tru a fi considerată obiectul căutat. Acest parametru este util pentru că pe parcursul
procesului de căutare pot apărea mai multe ipoteze ı̂ntr-o aceeaşi regiune (pentru fac-
tori de scalare diferiţi). Setarea acestui parametru reprezintă numărul de suprapuneri
posibile pentru ca o ipoteză să fie considerată obiect.
flags: poate avea patru combinaţii posibile, acestea putând fi combinate utilizând
operaţia de SAU logic:
68 DETECTAREA FEŢELOR ÎN IMAGINI
În această aplicaţie se va prezenta conceptul de urmărire a formelor ı̂ntr-o secvent, ă video
utilizându-se estimatori de stare. În mod particular, se va implementa o buclă de urmărire
a pozit, iei 2D a unui obiect cu ajutorul filtrului Kalman [15].
Corec܊ie
Predic܊ie
(măsurare)
Fig. 10.1 Estimator ı̂n buclă ı̂nchisă bazat pe o fază de predicţie urmată de corecţia modelului.
liniar, ı̂n care se exercită perturbaţii cu caracter aleatoriu, pe baza mărimilor măsurabile,
care sunt, de asemenea, afectate de zgomote aleatoare.
Dezvoltarea KF este nemijlocit legată de sistemele stohastice. În aceste condiţii se poate
considera că filtrul Kalman se poate baza pe ipoteza că sistemul care urmează să fie estimat
poate fi modelat ca un proces aleatoriu normal distribuit X(k), având valoarea medie x̄k (ı̂n
acest caz x̄k = x̂k ) şi matricea de covarianţă a erorii Pk , k reprezentând momentul de timp.
Mărimea x̂k este cunoscută sub numele de stare estimată a stării reale necunoscute xk a
sistemului la momentul de timp k. Starea sistemului poate fi reprezentată, ı̂n cazul general,
ca un vector n-dimensional:
T
x k = x k 1 x k 2 . . . xk n . (10.1)
Scopul urmărit este acela de a se obţine o stare estimată x̂k cât mai apropiată de starea
sistemului la momentul de timp considerat k sau, cu alte cuvinte, ca eroarea de estimare să
tindă la zero.
să fie utilizate ı̂n procesul de ı̂mbunătăţire a stării estimate. Vectorul wk mai este cunoscut
şi sub numele de vectorul zgomotului procesului şi este notat cu:
Sk = Hk Pk HkT . (10.8)
10.2 Cerinţe
1. Să se citească un fis, ier video de pe HDD;
2. Să se segmenteze un obiect de interes ı̂n funct, ie de culoarea sa;
3. Să se determine centrul de greutate al obiectului segmentat;
4. Să se calculeze predict, ia s, i corect, ia stării (pozit, iei 2D) obiectului utilizându-se filtrul
72 URMĂRIREA FORMELOR
Corec܊ie
(1) Calculul matricei de amplificare Kalman
T
Predic܊ie Pk H k
Kk .
(1) Estimarea stării T
H k Pk H k Rk
ˆ (2) Corectarea valorii estimate a priori a stării
xk Ak 1 xˆ k 1.
(2) Estimarea matricei de covarian܊ă a erorii
T
ˆ
xk
xˆ k K k z k H k xˆ k .
Pk Ak 1 Pk 1 Ak 1 Qk 1. (3) Corectarea valorii estimate a priori a matricei
de covarian܊ă a erorii
Pk I K k H k Pk .
Kalman;
5. Să se afis, eze traiectoriile pozit, iei măsurate s, i estimate a obiectului.
25 // I n i t i a l i z a r e a m a t r i c e i de s t a r e
26 randn ( Stare , Scalar : : all ( 0 ) , Scalar : : all ( 0 . 1 ) ) ;
27
28 // I n i t i a l i z a r e a m a t r i c e i de t r a n z i t i i i n t r e s t a r i
29 KF . transitionMatrix = * ( Mat_<float >(4 , 4 ) <<
30 1 , 0 , 1 , 0 , 0 , 1 , 0 , 1 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 1) ;
31
32 // I n i t i a l i z a r e a f i l t r u l u i Kalman
33 setIdentity ( KF . measurementMatrix ) ;
34 setIdentity ( KF . processNoiseCov , Scalar : : all ( 1 e−5) ) ;
35 setIdentity ( KF . measurementNoiseCov , Scalar : : all ( 1 e−1) ) ;
36 setIdentity ( KF . errorCovPost , Scalar : : all ( 1 ) ) ;
37 randn ( KF . statePost , Scalar : : all ( 0 ) , Scalar : : all ( 0 . 1 ) ) ;
38
39 // C l a s a u t i l i z a t a i n a c h i z i t i a de i m a g i n i de l a camera v i d e o a ←
calculatorului
40 VideoCapture cap ( 0 ) ;
41
42 // V e r i f i c a r e d e s c h i d e r e camera v i d e o
43 if ( ! cap . isOpened ( ) )
44 return −1;
45
46 // Bucla i n f i n i t a de a c h i z i t i e de i m a g i n i
47 for ( ; ; )
48 {
49 double AriaMaxima ( 0 . 0 ) ;
50
51 std : : vector< std : : vector<Point> > Contururi ;
52 std : : vector<Vec4i> Ierarhie ;
53 Point ptPozitiePredictionata ;
54 Point ptPozitieMasurata ;
55 Point ptPozitieEstimata ;
56
57 /*
58 * P r e d i c t i e p o z i t i e u t i l i z a n d f i l t r u l Kalman
59 */
60 Mat PredictieKalman = KF . predict ( ) ;
61 ptPozitiePredictionata . x = PredictieKalman . at<float >(0) ;
62 ptPozitiePredictionata . y = PredictieKalman . at<float >(1) ;
63
64 /*
65 * E f e c t u a r e a m a s u r a t o r i l o r ( d e t e r m i n a r e a p o z i t i e i i n i m a g i n e a ←
obiectului )
66 */
67 // A c h i z i t i e i m a g i n e de i n t r a r e
68 cap >> ImagineIntrare ;
69
70 // C o n v e r s i t a i m a g i n i i d i n s p a t i u l de c u l o a r e RGB i n s p a t i u l HSV
71 cvtColor ( ImagineIntrare , ImagineHSV , CV_BGR2HSV ) ;
72
73 // Segmentarea p l a n u r i l o r H, S s i V d i n i m a g i n e a HSV
74 inRange ( ImagineHSV ,
74 URMĂRIREA FORMELOR
75 Scalar ( 1 0 , 1 5 0 , 1 0 0 ) ,
76 Scalar ( 4 0 , 2 5 5 , 2 5 5 ) ,
77 ImagineSegmentata ) ;
78
79 // E x t r a g e r e a c o n t u r u r i l o r d i n i m a g i n e a segmentata
80 findContours ( ImagineSegmentata . clone ( ) ,
81 Contururi ,
82 Ierarhie ,
83 CV_RETR_TREE ,
84 CV_CHAIN_APPROX_SIMPLE ,
85 Point ( 0 , 0 ) ) ;
86
87 // E x t r a g e r e a c o n t u r u l u i cu c e a mai mare a r i e
88 for ( size_t i = 0 ; i < Contururi . size ( ) ; i++)
89 {
90 // C a l c u l u l a r i e i conturului curent
91 double Aria = contourArea ( Contururi [ i ] ) ;
92
93 // Comparatie a r i e
94 if ( Aria > AriaMaxima )
95 {
96 AriaMaxima = Aria ;
97
98 // Determinare c e n t r u de g r e u t a t e a l o b i e c t u l u i u t i l i z a n d ←
momentele s p a t i a l e
99 Moments MomenteSpatiale = moments ( Contururi [ i ] , false ) ;
100
101 ptPozitieMasurata = Point2f ( MomenteSpatiale . m10 / ←
MomenteSpatiale . m00 ,
102 MomenteSpatiale . m01 / MomenteSpatiale . m00 ) ;
103 }
104 }
105
106 // S a l v a r e a p o z i t i e i masurate i n i m a g i n e a o b i e c t u l u i
107 TraiectorieMasurata . push_back ( ptPozitieMasurata ) ;
108
109 /*
110 * C o r e c t i a s t a r i i o b i e c t u l u i ( p o z i t i e i ) u t i l i z a n d n o i l e ←
masuratori
111 */
112 Masuratori . at<float >(0) = ptPozitieMasurata . x ;
113 Masuratori . at<float >(1) = ptPozitieMasurata . y ;
114
115 Masuratori += KF . measurementMatrix * Stare ;
116
117 Mat PozitieEstimata = KF . correct ( Masuratori ) ;
118
119 Stare = KF . transitionMatrix * Stare + ZgomotProces ;
120
121 ptPozitieEstimata . x = PozitieEstimata . at<float >(0) ;
122 ptPozitieEstimata . y = PozitieEstimata . at<float >(1) ;
123
Descrierea funct, iilor principale 75
124 // S a l v a r e a p o z i t i e i e s t i m a t e a o b i e c t u l u i i n i m a g i n e
125 TraiectorieEstimata . push_back ( ptPozitieEstimata ) ;
126
127
128 /*
129 * Afisare rezultate tracking
130 */
131 ImagineTracking = ImagineIntrare . clone ( ) ;
132
133 // Desenarea t r a i e c t o r i e i masurate s i e s t i m a t e o b i e c t u l u i
134 for ( size_t i = 1 ; i < TraiectorieMasurata . size ( ) ; i++)
135 {
136 line ( ImagineTracking ,
137 TraiectorieMasurata [ i −1] ,
138 TraiectorieMasurata [ i ] ,
139 CV_RGB ( 2 5 5 , 2 5 5 , 0 ) ,
140 2) ;
141
142 line ( ImagineTracking ,
143 TraiectorieEstimata [ i −1] ,
144 TraiectorieEstimata [ i ] ,
145 CV_RGB ( 0 , 0 , 2 5 5 ) ,
146 2) ;
147 }
148
149 // A f i s a r e a m a r i m i i p r e d i c t i o n a t e a o b i e c t u l u i
150 circle ( ImagineTracking , ptPozitiePredictionata , 6 , CV_RGB ( 1 0 0 , ←
255 , 0) , 3) ;
151
152 // A f i s a r e a m a r i m i i masurate
153 circle ( ImagineTracking , ptPozitieMasurata , 6 , CV_RGB ( 2 5 5 , 2 5 5 , 0 ) ←
, 3) ;
154
155 // A f i s a r e a m a r i m i i d e t e r m i n a t a de f i l t r u l Kalman
156 circle ( ImagineTracking , ptPozitieEstimata , 6 , CV_RGB ( 0 , 0 , 2 5 5 ) , ←
3) ;
157
158 // A f i s a r e r e z u l t a t e
159 imshow ( " Segmentare " , ImagineSegmentata ) ;
160 imshow ( " Tracking " , ImagineTracking ) ;
161
162 if ( waitKey ( 3 0 ) >= 0 ) break ;
163 }
164
165 return EXIT_SUCCESS ;
166 }
[1] P. J. Besl and N. D. McKay, “A method for registration of 3-d shapes,” IEEE Trans.
Pattern Anal. Mach. Intell., Vol. 14, No. 2, pp. 239–256, Feb. 1992. [Online]. Available:
http://dx.doi.org/10.1109/34.121791
[2] G. Bradski and A. Kaehler, Learning OpenCV: Computer Vision with the OpenCV
Library. Sebastopol, Canada: O’Reilly Media, 2008.
[3] J. Canny, “A Computational Approach to Edge Detection,” IEEE Trans. on Pattern
Analysis and Machine Intelligence, Vol. 8, No. 6, pp. 679–698, 1986.
[4] B. Cyganek and J. Siebert, An Introduction to 3D Computer Vision Techniques and
Algorithms. West Sussex, Great Britain: John Wiley & Sons, 2009.
[5] Y. Freund and R. Schapire, “Experiments with a New Boosting Algorithm,” Proc. of
the Thirteenth Inter. Conf. on Machine Learning, San Francisco, Canada, 1996, pp.
148–156.
[6] R. C. Gonzalez and R. E. Woods, Digital Image Processing, 3rd Ed. New Jersay, USA:
Prentice-Hall, Inc., 2006.
[7] S. Grigorescu, T. Cociaş, G. Măceşanu and F. Moldoveanu, “Stereo Vision-based 3D
Camera Pose and Object Structure Estimation - An Application to Service Robotics,”
Proc. of the Inter. Joint Conf. on Computer Vision, Imaging and Computer Graphics
Theory and Applications, Rome, Italy, 2012, pp. 355–358.
[8] S. Grigorescu, G. Măceşanu, T. Cociaş and M. F., “On the Real-time Modelling of a
Robotic Scene Perception and Estimation System,” Proc. of the 15th Inter. Conf. on
System Theory, Control, and Computing, Sinaia, Romania, 2011, pp. 273–276.
[9] C. Harris and M. Stephens, “A Combined Corner and Edge Detection,” Proc. of the
Fourth Alvey Vision Conference, 1988, pp. 147–151.
[10] R. Hartley, “In Defense of the Eight-Point Algorithm,” IEEE Trans. on Pattern Analysis
and Machine Intelligence, Vol. 19, No. 6, pp. 580–593, 1997.
[11] D. Holz, S. Holzer and R. B. Rusu, “Real-Time Plane Segmentation using RGB-D
Cameras,” Proceedings of the RoboCup Symposium, 2011.
[12] B. K. P. Horn, “Closed-form solution of absolute orientation using unit quaternions,”
Journal of the Optical Society of America A, Vol. 4, No. 4, pp. 629–642, 1987.
[13] P. V. Hough, “Method and means for recognizing complex patterns,” US Patent
3969654, 1962.
[14] M. Isard and A. Blake, “Condensation - conditional density propagation for visual
tracking,” International Journal of Computer Vision, Vol. 29, pp. 5–28, 1998.
[15] R. E. Kalman, “A new approach to linear filtering and prediction problems,” Trans-
actions of the ASME-Journal of Basic Engineering, Vol. 82, No. Series D, pp. 35–45,
1960.
[16] R. Lienhart and J. Maydt, “An Extended Set of Haar-like Features for Rapid Object
Detection,” Proc. of the 2002 Inter. Conf. on In Image Processing ICIP, New York,
USA, 2002, pp. 900–903.
[17] G. Macesanu, T. Cociaş, F. Moldoveanu and M. Cernat, “Active Vision System for 3D
Scene Reconstruction,” Proc. of the Inter. Conf. on Interdisciplinarity in Education,
Athens, Greece, 2011, pp. 376–381.
78 BIBLIOGRAFIE