Documente Academic
Documente Profesional
Documente Cultură
PROIECT DE DIPLOMĂ
Suceava 2016
Cuprins
Capitolul 1 – Introducere .............................................................................................................................. 3
1.1 Scopul acestei lucrări ...................................................................................................................... 5
1.2 Structura documentului .................................................................................................................. 6
Capitolul 2 - Senzorul Microsoft Kinect......................................................................................................... 7
2.1 Componentele hardware a senzorului Kinect................................................................................. 8
2.2 Cum funcționează senzorul Kinect .................................................................................................. 9
2.3 Camera RGB .................................................................................................................................. 12
2.4 Senzorul de adâncime ................................................................................................................... 13
2.5 Skeleton tracking........................................................................................................................... 14
2.6 Matricea de microfoane................................................................................................................ 15
2.7 Instalarea și configurarea echipamentului ................................................................................... 16
2.8 Microsoft Kinect SDK..................................................................................................................... 17
2.9 Motorul de înclinație al senzorului Kinect .................................................................................... 21
2.10 Controlul butoanelor................................................................................................................... 22
Capitolul 3 - Platforma de viziune artificială AForge.NET ........................................................................... 23
3.1 AForge.Imaging ............................................................................................................................. 24
3.2 AForge.Vision ................................................................................................................................ 26
Capitolul 4 - Detecția mișcării în secvențe video preluate de la senzorul Kinect ....................................... 30
4.1 Algoritmul SimpleBackgroundModelingDetector de detecție a mișcării (Pseudocod) ................. 31
4.2 Implementarea algoritmului de detecție a mișcării umane (C#) .................................................. 37
4.3 Pregătirea formatului imaginii necesar platformei Aforge.NET ................................................... 40
Capitolul 5 - Detecția mișcării în secvențe Skeleton preluate de la senzorul Kinect .................................. 42
Capitolul 6 - Concluzii.................................................................................................................................. 44
Referințe ..................................................................................................................................................... 46
2
Capitolul 1 – Introducere
1
Reverse engineering sau Inginerie inversă se referă la un proces care constă în analiza detaliată a funcționării,
proiectării și dezvoltării unui obiect (dispozitiv, component electric, mecanism, software, etc) cu scopul de a
produce un nou dispozitiv sau aplicație care să aibă noi funcționalități sau similare, îmbunătățind eficiența sa, fără
a copia nimic din cel original.
3
Această lucrare se inspiră din ambiția AmI de a îmbunătăți viața și confortul omului și de
a crea o lume virtuală în care acesta să fie transpus, având în vedere și evoluția tehnologică din
ziua de azi și a percepției realității. Urmând tendințele actuale, mi-am propus dezvoltarea unui
sistem de monitorizare a omului într-un mediu închis care să achiziționeze și să proceseze
mișcarea umană. Lucrarea de față se bazează pe un algoritm de detecție a mișcării important în
sistemul de securitate deoarece detectează mișcarea într-o anumită zonă. Această aplicație, însă,
poate avea aplicabilitate și în alte domenii precum cel al graficii computerizate. Grafica
computerizată 2D și 3D are multe aplicații în industria de divertisment, în jocurile video și în
producția de film. Datele achiziționate cu tehnologii actuale precum Kinect pot fi procesate și
preluate de alte aplicații în scopul creării de imagini și efecte vizuale dinamice care se mișcă și se
modelează în timp real pe baza mișcării oamenilor din cadru.
În ultimii ani, s-au revoluționat mult și reprezentările TV și cinematografice. Putem lua
ca exemplu scena de la Eurovision Song Contest. Scenografii au folosit luminile ca și
componentă puternică pentru a crea profunzime, s-au focalizat pe expresii mai delicate fără
pixeli și proiecții și au creat iluzii optice folosindu-se de sală și de lumini. Fiecare efect în parte
este unic și oferă ceva nou. Într-un anumit sens scena oferă posibilități nelimitate, dar în același
timp ne obligă să gândim într-un mod diferit. Ea ne transpune într-o altă lume. Creativitatea ne și
provoacă, ne și inspiră. Un proverb chinezesc spune că “O imagine valorează cât o mie de
cuvinte” dar acesta poate fi transpus pentru această eră a computerului astfel “O imagine
valorează mai mult decât câțiva kilobytes de date”. Este firesc să ne așteptăm ca comunicarea
grafică să fie mult mai rezonabilă cât timp computerul este folosit și pentru aceste scopuri, să
reprezinte obiecte în spațiul 2D și 3D. Datele achiziționate cu senzorul Kinect pot fi folosite și în
astfel de reprezentări grafice. Așadar, scenele nu vor mai fi statice și lipsite de creativitate ci vor
transpune publicul într-o nouă dimensiune, în cea virtuală. Interpreții muzicali și trupele vor
putea comunica cu publicul mult mai ușor, iar versurile melodiei vor avea un alt impact.
Interpretarea muzicală va fi una augmentată.
Senzorul Kinect a deschis noi orizonturi nu doar în domeniul jocurilor, dar în general
revoluționează întreaga lume a interacțiunii dintre om-tehnologie, permițând oamenilor să se
raporteze la mașină într-un mod cât mai natural, prin cuvinte și mișcări. Datele achiziționate cu
acest senzor vor putea fi utilizate pe viitor și pentru a îmbunătăți confortul domestic (probabil
prin reglarea automată a luminilor din casă), pentru supravegherea persoanelor cu vulnerabilități
(alertă în caz de comportament neobișnuit sau chiar suport pas cu pas pentru persoanele cu
probleme de memorie care să îi asiste cât timp aceștia se deplasează dintr-o cameră în alta),
pentru monitorizarea siguranței pacienților dintr-un spital (detecție dacă aceștia cad pe jos), în
jocuri video, pentru a controla roboți, în educație, etc.
4
Figura 1.1 Componentele hardware a senzorului Kinect
(http://buildsmartrobots.ning.com/profiles/blogs/building-a-kinect-based-robot-for-under-500-00)
Scopul acestei lucrări de diplomă este de a achiziționa date video cu privire la mișcarea
umană, cu ajutorul senzorului Kinect și de a le procesa prin algoritmi de detecție cu scopul de a
le folosi ulterior pentru crearea de efecte grafice proiectate pe ecrane de dimensiuni mari la
concerte muzicale. Cu ajutorul unui algoritm de detecție a mișcării am identificat prezența
mișcării apreciată prin zonele de mișcare din cadru și intensitatea mișcării. Intensitatea mișcării
este apreciată cu o valoare din intervalul [0,1], 0 nefiind mișcare (No motion) iar 1 gradul cel
mai mare de mișcare. În cadrul aplicației, algoritmul detectează mișcare când intensitatea este
mai mare de valoarea 0.02. Cu cât intensitatea mișcării este mai mare, cu atât efectul se
mișcă/modelează mai repede. Cu ajutorul coordonatelor zonelor de mișcare transmise, efectul va
apărea în zona aferentă din cadrul canvas-ului efectului. Numărul zonelor de mișcare reprezintă,
în schimb, numărul de obiecte create.
5
Figura 1.2 Poziționarea echipamentelor în sală
6
Capitolul 2 - Senzorul Microsoft Kinect
Această tehnologie a fost creată, inițial, pentru lumea jocurilor dar poate fi conectat cu un
adaptor și la PC. Există două modele de Kinect: versiunea pentru consola Xbox360 (sau Xbox
One) și versiunea dotată cu SDK (Software Development Kit). Odată instalat driver-ul Microsoft,
acesta oferă accesul la funcțiile audio, video și la senzorii de adâncime ale senzorului. Windows
SDK permite dezvoltatorilor de software să creeze aplicații care suportă recunoașterea vocii și a
gesturilor. Computerul conectat la Kinect cu SDK v1.8 trebuie să aibă un procesor care rulează
pe 32-bit (x86) sau 64-bit (x64) și care are două sau mai multe nuclee fizice cu viteză de
procesare de minim 2.66 GHz, un controller USB 2.0 sau 3.0 dedicat, minim 2GB de memorie
RAM și să fie dotat cu un sistem de operare Windows 7, Windows 8, Windows 8.1 sau Windows
Embedded Standard 7.
7
Caracteristici Microsoft Kinect Kinect One
Senzorul Kinect, deci, deduce poziția corpului printr-un proces (Figura 2.2.1) care este format
din următoarele două etape:
Etapa 1: se construiește o hartă de adâncime folosind analiza luminii structurate creată prin
emitorul de infraroșu
Etapa 2: se deduce poziția folosind algoritmi de tracking implementat în softul dezvoltat de
Microsoft.
9
Fluxul de date este manevrat ca o succesiune de cadre unice. La momentul inițializării,
dezvoltatorul trebuie să definească ce tipologii de imagini dorește să primească de la dispozitiv.
În particular, există următoarele opțiuni:
Color: Aplicația necesită accesul la imaginile color (Fig. 2.2.2a)
Aceste imagini color sunt disponibile în două formate: RGB și YUV. Pentru aceste
formate, informațiile vin codate la 32 bit pentru RGB, respectiv la 16 bit pentru YUV.
Rezultă că imaginile YUV ocupă mai puțină memorie, dar sunt disponibile doar cu
rezoluția de 640x480 pixeli și cu o frecvență de 15 cadre pe secundă. Formatul RGB
permite în schimb aceeași frecvență la o rezoluție de 1280x1024, sau 30 FPS pentru o
rezoluție de 640x480.
Adâncime: Aplicația necesită accesul la imaginile de adâncime (Fig. 2.2.2b).
Senzorul de adâncime întoarce un cadru în care fiecare pixel reprezintă distanța
carteziană, în milimetri, între planul camerei video și obiectul cel mai apropiat de la
coordonatele x și y a pixelului din interiorul Field of View (FOV) a senzorului (figura
2.2.3). O valoare egală cu 0 indică faptul că senzorul nu a găsit nimic în acel punct,
pentru că obiectele în acea zonă sunt prea depărtate sau prea apropiate pentru a putea fi
detectate de senzor. În alte cuvinte, senzorul este “orb” în afara unui interval de distanțe
determinat. Pentru imaginile de adâncime sunt disponibile rezoluțiile 640x480 pixeli,
320x240 pixeli sau 80x60 pixeli.
Adâncime și indicele persoanelor: Aplicația necesită accesul la imaginile de adâncime
și are nevoie de indicele persoanelor din cadru generat de motorul de tracking (fig.
2.2.2c). Deci motorul de tracking se activează iar pentru fiecare pixel a imaginii de
adâncime sistemul va întoarce, pe lângă distanța măsurată în acel punct, o valoare
întreagă i care indică că acel pixel face parte din silueta persoanei cu indicele i (dacă în
acel punct nu s-a identificat nici o persoană, atunci i=0). În figura 2.2.4 se prezintă un
exemplu de imagine de adâncime în care s-au evidențiat cu culori diferite pixelii pentru
care indicele persoanei este diferită de zero, semn că sistemul a recunoscut în acel punct o
persoană. La persoane diferite vor exista diferiți indici (reprezentați cu culori diferite în
figură).
Kinect poate procesa date input de la senzorul de adâncime pentru a identifica până la
patru figuri umane ce se află în fața senzorului și să creeze ceea ce se numește player
segmentation map. Această hartă este un bitmap în care fiecărui pixel îi este asociat o
valoare ce reprezintă indicele persoanei asignat ei, ce se găsește în câmpul vizual, cel mai
aproape de camera video în acel determinat pixel.
Diferit de ceea ce se întâmplă cu imaginile de adâncime simple, în acest caz este
suportată o rezoluție de 320x240 pixeli.
Skeleton: Aplicația necesită accesul la informațiile cu privire la poziția încheieturilor
scheletului persoanei din cadru (Fig. 2.2.2d).
Primele două cadre (Color și adâncime) se pot activa și pe doi senzori Kinect în simultan,
conectați la același computer, în timp ce celelalte două doar pentru un Kinect la un
10
moment dat, având în vedere faptul că SDK-ul permite inițializarea unui singur motor de
tracking.
Figura 2.2.2 Cadre preluate de la Kinect: a) color; b) adâncime; c) adâncime și indicele persoanelor; d) skeleton
11
2.3 Camera RGB
2
CMOS – acronimul lui Complementary metal-oxide semiconductor, este o tehnologie utilizată în producerea de
circuite integrate. La senzorul CMOS, fiecare pixel citit are o ieșire individuală pentru a furniza direct un semnal
video de tip digital (diferit de cel CCD – Charge Coupled Device – în care pixelii se citesc în grupuri, prin noduri de
ieșire, pentru a genera semnal video analog în tensiune, care eventual vine apoi transformat în semnal digital de
videocameră). Senzorul CCD este folosit mai mult pentru videocamerele de tip analogic, iar cel CMOS este mai
adecvat pentru videocamerele IP/de supraveghere.
3
Bayer pattern este un model de așezare a filtrelor roșii, verzi și albastre (RGB) peste fotositurile captatorului
camerei digitale. Deoarece ochiul uman este mai sensibil la verde, raportul R:G:B în modelul Bayer este 1:2:1.
Având în vedere că fiecare pixel, în aproape toate camerele/videocamerele cu un senzor, poate primi doar o
singură informație cu privire la cantitatea de lumină, i se pune în față un filtru pentru a capta doar o singură
culoare primară (RGB). Celelalte componente le obține prin interpolare, adică culoarea fiecărui pixel este calculată
folosind valorile pixelilor învecinați .
4
Filtrul Bayer oferă informații despre intensitatea luminii în regiunile de lungimi de undă roși, verzi și albastre
(RGB). Datele brute ale imaginii captate de senzor sunt apoi convertite într-o imagine complet color (cu
reprezentări ale tuturor celor trei culori primare reprezentate la fiecare pixel) de către un algoritm de demozaicare
ce este croit pentru fiecare tip de filtru de culoare.
12
Figura 2.3.2 Dispunerea filtrelor de culoare pe matricea Bayer
(http://www.hatiandskoll.com/2013/04/11/building-a-digital-camera-
sensor-from-a-charge-coupled-device/)
Senzorul de adâncime are o rezoluție de 640x480 pixeli. Fiecare pixel deține 11 biți de
informație de adâncime, prin urmare, sunt posibile 2048 (211) valori diferite pentru
reprezentarea distanțelor. Librăriile de acces la imaginea de adâncime permit conversia celor 11
biți de valori în milimetri, în sistemul de coordonate.
13
Figura 2.4.1 Diagrama flux a senzorului de adâncime
Informațiile despre skeleton joint sunt disponibile până la maxim două persoane (fig.
2.5.2). Pot fi detectate însă și până la un maxim de patru persoane, dar va fi posibil doar un
tracking „pasiv”, adică se va crea și pentru ei un index a persoanelor dar va întoarce doar poziția
centrului de masă calculat pentru persoană în loc de cea a tuturor celor 20 de articulații normal
identificate. Astfel nu se va știi poziția omului, ci doar poziția sa în spațiu.
14
Figura 2.5.1 Poziția încheieturilor, oferite de motorul de tracking, în raport cu corpul uman
(https://blogs.msdn.microsoft.com/msroboticsstudio/2011/11/29/kinect-for-robotics/)
5
Convertor analog-digital (din engleza Analog-Digital Converter)
6
Frecvența de tăiere este un parametru definitoriu a filtrelor electrice trece-jos și trece-sus [13].
15
prezența gălăgiei sau al ecoului și pot capta sunetul de la mai multe persoane care vorbesc din
mai multe direcții și poziții. Microfoanele sunt plasate în poziții diferite pentru a putea
recunoaște de unde vine sunetul și distanța de la sursă. Dat fiind faptul că microfoanele se află în
locuri diferite, sunetul va ajunge la fiecare microfon la diferite intervale de timp. Odată ce sursa
și poziția sunetului sunt calculate, toate părțile audio de la cele patru microfoane se unesc și
produc un semnal cu un sunet de înaltă calitate. Unghiul de captare a sunetului se află în
domeniul [-50°, +50°] (fig. 2.6.1). Calculul unghiului se bazează pe coordonatele camerei
Kinect, unde x și y definesc planul orizontal. Un număr negativ indică faptul că sursa audio se
află în partea dreaptă a senzorului, o valoare pozitivă înseamnă că este în partea stângă iar zero
indică că sursa este în față senzorului, central.
16
- senzorul de recunoaștere tridimensională a senzorului folosește o combinație de laser și
infraroșu, tehnologii care nu depind de lumina vizibilă, deci se pot utiliza și în întuneric. În
schimb, camera RGB necesită o luminozitate bună a cadrului; nu funcționează corect într-un
mediu afectat direct de lumina soarelui, o suprafață reflectorizantă, sau o interferență cu lumina
cu o lungime de undă similară (aproximativ 830 nm).
După cum am menționat și mai sus, Microsoft Kinect este un dispozitiv utilizabil și în
combinație cu computerul, nu doar cu consola de jocuri. SDK-ul oficial oferit de Microsoft
permite folosirea sa și dezvoltarea de aplicații bazate pe Kinect exclusiv pentru computerele
dotate cu sistemul de operare Windows. SDK-ul oficial a fost publicat de Microsoft în 2011 și
cuprinde o librărie care poate prelua și gestiona fluxul de date ce provine de la senzorii
dispozitivului și poate fi folosit atât în C++ cât și în unul din limbajele Managed din platforma
.NET. Mediul de dezvoltare necesar pentru folosirea acestui SDK este Microsoft Visual Studio.
NUI (Natural User Interface) library este o librărie de bază a senzorului Kinect pentru Windows
API. Aceasta permite preluarea datelor de la senzorii de imagine și de la microfoane și
controlează dispozitivul (de exemplu inclinația echipamentului). Aplicațiile oferite de Microsoft,
în schimb, folosesc librăriile grafice DirectX, folosite exclusiv în sistemele de operare Windows,
ceea ce limitează portabilitatea aplicațiilor dezvoltate.
Aplicația prezentată în această lucrare a fost dezvoltată în mediul de dezvoltare Microsoft
Visual Studio 2015, în platforma .NET cu versiunea 4.5, în aplicația WPF (Windows
Presentation Foundation).
În cadrul proiectului am integrat librăria Microsoft.Kinect.dll din cadrul SDK-ului de la
Microsoft pentru a putea accesa secvențele video de la senzor, astfel:
using Microsoft.Kinect;
17
Variabila senzorului este globală și ne permite să activăm senzorul Kinect oriunde în program:
private KinectSensor sensor;
și de un Bitmap care va reține informația culorii:
private WriteableBitmap colorBitmap;
WriteableBitmap este o imagine sursă de tip bitmap care poate fi scrisă și actualizată. Bitmap-ul
reprezintă o mulțime de pixeli cu o anumită dimensiune și rezoluție. WriteableBitmap este adesea
folosit în loc de bitmap-urile normale deoarece este mai rentabil (din punct de vedere al costului
resurselor în memorie) și mai bune pentru streaming video. În alte cuvinte, WriteableBitmap este
o imagine care este actualizabilă, fără a fi nevoie creerea unei noi variabile la fiecare cadru.
Această imagine scrie noi octeți pentru a actualiza interfața utilizator.
{
if (potentialSensor.Status == KinectStatus.Connected)
{
this.sensor = potentialSensor;
break;
}
}
Primul lucru care trebuie făcut, după pornirea Kinectului este să se specifice care flux de date
(video color, de adâncime, date de tip skeleton, etc.) se dorește să se folosească, la ce rezoluție și
la câte cadre pe secundă:
this.sensor.ColorStream.Enable(ColorImageFormat.RgbResolution640x480Fps30);
În acest moment, camera video este pregătită pentru a furniza date imediat ce se pornește
senzorul:
this.sensor.Start();
În mod similar, se poate opri camera video a senzorului folosind metoda Stop().
Există două moduri de a prelua date de la senzor: modelul polling și cel bazat pe evenimente.
Metoda polling cere să se inspecteze o stare a flag-urilor, la intervale regulate, pentru ca datele să
fie gata pentru noi cadre. Această metodă este simplă dau nu prea eficientă și flexibilă. Cu
metoda bazată pe evenimente, fiecare senzor declanșează un eveniment când un nou cadru de
date este disponibil. Pentru a o folosi, trebuie să definim un event handler pentru
AllFramesReady. După cum sugerează și numele, acesta se apelează de fiecare dată când un
cadru video este gata pentru a fi procesat. Evenimentul poate fi utilizat astfel:
_sensor.AllFramesReady += Sensor_AllFramesReady;
18
Imaginea bitmap captată de sensor se află în argumentul evenimentului. Pentru a o folosi, se
poate trece prin două etape:
1. Să se folosească metoda OpenColorImageFrame pentru a prelua obiectul
ColorImageFrame
2. Să se folosească metoda CopyPixelDataTo pentru a prelua matricea de bytes a datelor
pixelilor.
Primul lucru în cadrul event handler-ului este să se obțină obiectul ColorImageFrame,
private void SensorColorFrameReady(object sender, ColorImageFrameReadyEventArgs e)
{
using (ColorImageFrame colorFrame = e.OpenColorImageFrame())
{
//...
}
}
Cât privește preluarea datelor de la schelet (Skeleton), pentru a permite skeletal tracking,
se va apela metoda SkeletonStream.Enable(). Se poate accesa proprietatea
KinectSensor.SkeletonStream din clasa KinectSensor. Pentru a primi informații despre
recunoașterea omului în cadru, se va folosi evenimentul KinectSensor.SkeletonFrameReady sau
KinectSensor.AllFramesReady din clasa KinectSensor.
private KinectSensor sensor;
void StartKinectST()
{
sensor = KinectSensor.KinectSensors.FirstOrDefault(s => s.Status ==
KinectStatus.Connected);
sensor.SkeletonStream.Enable();
skeletonData = new Skeleton[sensor.SkeletonStream.FrameSkeletonArrayLength];
sensor.SkeletonFrameReady += new
EventHandler<SkeletonFrameReadyEventArgs>(kinect_SkeletonFrameReady);
sensor.Start();
}
Pentr a accesa informațiile despre Skeleton se vor folosi următoarele linii de cod:
private void kinect_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
{
using (SkeletonFrame skeletonFrame = e.OpenSkeletonFrame())
{
if (skeletonFrame != null && this.skeletonData != null)
19
skeletonFrame.CopySkeletonDataTo(this.skeletonData);
}
}
}
Clasa Joint are un TrackingState care poate fi accesat pentru fiecare joncțiune a scheletului.
De exemplu, se pot prelua datele despre cap astfel:
private void DrawBonesAndJoints(Skeleton skeleton, DrawingContext drawingContext)
{
this.DrawBone(skeleton, drawingContext, JointType.Head, JointType.ShoulderCenter);
20
private static void RenderClippedEdges(Skeleton skeleton, DrawingContext
drawingContext)
{
if (skeleton.ClippedEdges.HasFlag(FrameEdges.Bottom))
{
drawingContext.DrawRectangle(
Brushes.Red, null,
new Rect(0, RenderHeight - ClipBoundsThickness, RenderWidth,
ClipBoundsThickness));
}
Dacă senzorul este deplasat astfel încât baza să fie la un unghi diferit față de gravitație, sau dacă
senzorul este înclinat manual, unghiul raportat de API se va schimba, chiar dacă unghiul de
ridicare nu a fost modificat în mod programatic.
21
Pentru a înclina în sus motorul, se va folosi următorul cod:
sensor.ElevationAngle += 4;
22
Capitolul 3 - Platforma de viziune artificială AForge.NET
AForge.NET este o platformă de inteligență artificială dezvoltată în 2012 de Andrew
Kirillov pentru .NET Framework. Librăria este open source, scrisă în C#, dezvoltată pentru
programatorii și cercetătorii din domeniul viziunii și inteligenței artificiale.
23
3.1 AForge.Imaging
Pentru a folosi această librărie trebuie adăugată în lista de referințe și în namespace-ul din cadrul
proiectului:
using AForge.Imaging;
Această librărie conține clase și interfețe pentru diferite implementări ale procesării de imagini
printre care Image (metode de bază legate de imagine), BlobCounter (calculează obiectele din
imagine, care sunt separate de fundal negru), Drawing (tratează primitivele grafice), RGB
(componentele RGB), UnmanagedImage (imagini din resursele unmanaged), etc.
Aplicația demonstrativă Filters Demo prezintă diferite filtre de imagine și cum pot ele fi aplicate
pe o imagine. În figura 3.1.2 se poate vedea o listă cu aceste filtre din spațiul de nume
AForge.Imaging.Filters. Filtrele sunt din diferite domenii, cum ar fi filtrarea culorilor, corecția
nivelelor culorilor, filtre de convoluție, filtre de detecție a frontierelor, filtre de binarizare, etc.
24
Figura 3.1.3 Imaginea originală în stânga, respectiv filtrul Invert aplicat în dreapta
Aplicația Blobs Explorer (figura 3.1.4) prezintă clasa BlobCounter care permite găsirea
tuturor obiectelor separate dintr-o anumită imagine. Aceasta găsește fiecare obiect în parte, îi
oferă proprietăți și cu ajutorul altor clase ale platformei i se poate da imaginii un tip de
evidențiere: convex hull, marginile stânga/dreapta, marginile sus/jos sau marginile de tip
patrulatere (dacă obiectul este într-adevăr un patrulater, atunci marginile sale ar trebui să fie
găsite cu bună precizie).
Mai sunt și alte aplicații demonstrative în cadrul acestei librării, de exemplu Texture
Demo care prezintă utilizarea diferitelor generatoare de textură din spațiul de nume
AForge.Imaging.Textures cum ar fi lemn, marmură, nori, Hough Transformation care poate fi
aplicat pentru detectarea liniilor drepte și a cercurilor cu o anumită rază sau Shape Checker care
permite detectarea unor forme geometrice simple (triunghi, pătrat, dreptunghi, cerc sau alte
patrulatere).
25
3.2 AForge.Vision
Dezvoltatorii platformei AForge.NET au oferit și un exemplu de aplicația Motion
Detector care experimentează diferiți algoritmi pentru detectarea mișcării. Algoritmii sunt
implementați în spațiul de nume AForge.Vision.Motion.
26
mișcării, este de preferat să fie folosită în combinație cu clasa MotionDetector, care oferă
caracteristici suplimentare și permite folosirea algoritmilor de post-procesare a mișcării.
Acest algoritm nu este prea adecvat pentru acele operații care cer o evidențiere precisă a
obiectelor în mișcare. Este însă recomandat pentru acele operații care doar solicită
detecția mișcării.
Figura 3.2.4 Evidențierea zonelor de mișcare detectate cu ajutorul algoritmului SimpleBackgroundModelingDetector. Evidențiere
de tip: a) Motion Border Highlighting; b) Blob Counting Processing; c) Motion Area Highlighting; d) Grid Motion Area
Processing
27
Algoritmul CustomFrameDifferentDetector se bazează pe diferența dintre un cadru
video curent și fundal unui cadru predefinit. Diferitele cadre se segmentează
(thresholded) și se calculează cantitatea de pixeli diferență. Proprietatea SuppressNoise
suprimă imaginile zgomotoase și aplică operatorul morfologic de eroziune. Proprietatea
KeepObjectsEdges poate fi utilizată pentru a restabili marginile după suprimarea
imaginii. Dacă nu se specifică cadru de fundal predefinit cu metoda
SetBackgroundFrame(Bitmap), algoritmul va lua primul cadru video ca și fundal și va
calcula diferența altor cadre video cu acesta. Diferit de algoritmul
TwoFramesDifferenceDetector, CustomFrameDifferentDetector identifică obiectele care
nu fac parte din fundal (scenă) mult mai clar. Pe de o parte, acest algoritm este rapid
pentru ca se bazează pe o diferențiere simplă ca și cel care detectează diferența dintre
două cadre diferite. Pe de altă parte, însă, diferențiază cadrul video curent cu cadrul de
fundal, care ar putea permite identificarea obiectelor în mișcare dar nu și zonele de
schimbare (ca în algoritmul SimpleBackgroundModelingDetector). Cu toate acestea,
utilizatorul trebuie să specifice cadrul de fundal (sau algoritmul va lua primul cadru video
ca și cadru de fundal) iar algoritmul nu va încerca niciodată să se actualizeze pe diferite
cadre, ceea ce înseamnă că nu există adaptare la schimbări de scene.
28
doar acele obiecte care satisfac dimensiunile limită a proprietăților MinObjectWidth și
MinObjectHeight.
Toate aceste clase pun în aplicare o interfață destul de simplă și comună, independent de
fluxul video sau format. Clasele doar analizează cadre video consecutive oferite de utilizator.
Clase diferite de detecție a mișcării pot folosi diferiți algoritmi pentru a detecta mișcarea. Dar
toate sunt similare în modul în care preiau cadrele video. Toate clasele conțin proprietăți despre
nivelul mișcării, care se află în domeniul [0,1]. De exemplu, dacă proprietatea este setată la 0.05
înseamnă că clasa a detectat 5% din nivelul total de mișcare. Analizând această proprietate și
comparând-o cu praguri predefinite, se poate da o alarmă, când nivelul mișcării detectate este
mai mare decât nivelul considerat în siguranță.
Pentru a extinde funcționalitățile acestei platforme, s-a creat proiectul Accord.NET. Mai
există și alte platforme open source de viziune artificială, cum ar fi OpenCV sau EmguCV. Deși
amândouă (AForge.NET și OpenCV) au cam aceleași funcționalități, AForge.NET conține mai
multe filtre și este adecvată pentru diferite transformări și manipulări de imagine, dar pare a fi
săracă în celelalte domenii (de exemplu operații cu matrice folosite mult în viziunea artificială).
OpenCV în schimb, are mai multe funcționalități dar este puțin mai complicat de programat cu
ea. EmguCV pare să aibă cele mai bune actualizări dar documentația nu este așa bogată.
29
Capitolul 4 - Detecția mișcării în secvențe video preluate de la senzorul
Kinect
Primul lucru realizat în procesarea imaginii capturate de către Kinect a fost alegerea
algoritmului cel mai eficient necesar rezolvării problemei mele, și anume algoritmul
SimpleBackgroundModelingDetector care face parte din librăria AForge.NET.
public class SimpleBackgroundModelingDetector : IMotionDetector
Pentru a putea folosi acest algoritm am calculat obiectele separate din cadrul de mișcare.
Am reușit să implementez acest lucru folosindu-mă de un alt algoritm, tot din aceeași librărie,
BlobCountingObjectsProcessing. Acesta este folosit doar cu algoritmii care se bazează pe
diferențele dintre cadrele curente și cele ale fundalului și permite extragerea clară a obiectelor în
mișcare.
differenceThreshold ← 15
differenceThresholdNeg ← -15
proprietate DifferenceThreshold
differenceThreshold ← max( 1, min( 255, value ));
differenceThresholdNeg ← -differenceThreshold;
întoarce differenceThreshold
31
proprietate MotionFrame
întoarce motionFrame
proprietate MotionLevel
întoarce pixelsChanged / ( width * height )
suppressNoise ← ADEVĂRAT
proprietate SuppressNoise
*) alocare cadru temporar (dacă este necesar)
dacă ((suppressNoise ) ȘI (tempFrame := NULL) ȘI (motionFrame != NULL)) atunci
tempFrame ← alocăMemorie (width, height, Format8bppIndexed )
sf. dacă
*) verificare dacă este necesar cadrul temporar
dacă ( (!suppressNoise ) ȘI (tempFrame != NULL ) )
*) dispunere tempFrame pe ecran
tempFrame ← NULL
sf. dacă
întoarce suppressNoise
keepObjectEdges ← FALS
proprietate keepObjectEdges
keepObjectEdges = value
întoarce keepObjectEdges
32
Proprietatea are efect doar dacă proprietatea MillisecondsPerBackgroundUpdate este setată la 0.
Altfel, nu are efect iar actualizarea fundalului se va lua după valoarea proprietății
MillisecondsPerBackgroundUpdate.
proprietate FramesPerBackgroundUpdate
framesPerBackgroundUpdate ← max ( 1, min ( 50, value ) )
întoarce framesPerBackgroundUpdate
33
sau
procedură SimpleBackgroundModelingDetector(suppressNoise, keepObjectEdges)
this.suppressNoise ← suppressNoise
this.keepObjectEdges ← keepObjectEdges
sf. procedură
*) buffer temporar
*) tempFrame – buffer-ul temporar folosit pentru suprimarea zgomotului
dacă ( suppressNoise ) atunci
tempFrame ← alocăMemorie ( width, height, Format8bppIndexed )
sf. dacă
*) conversia cadrului sursă (color) în grayscale
*) metoda ConvertToGrayscale din clasa Tools (Aforge.NET)
ConvertToGrayscale( videoFrame, backgroundFrame )
sf. dacă
34
*) *backFrame, *currFrame, diff
35
diff = *currFrame - *backFrame
dacă ( diff > 0 ) atunci
dacă *backFrame += ( diff < updateAmount ) atunci
*backFrame ← diff
altfel *backFrame ← updateAmount
sf. dacă
altfel dacă ( diff < 0 ) atunci
dacă *backFrame += ( -diff < updateAmount ) atunci
*backFrame ← diff
altfel *backFrame ← -updateAmount
sf. dacă
sf. dacă
sf. dacă
sf. pentru
sf. dacă
pixelsChanged ← 0
*) calcul cantitatea pixelilor în mișcare
36
pentru i ← 0, frameSize execută
*) & - reprezintă operatorul ȘI logic
pixelsChanged += ( *motion & 1 )
sf. pentru
sf. dacă
sf. procedură
sfârșit
Detectorul mișcării (starea mișcării, fundalul, cadrul temporar, numărul de cadre cât și
zona mișcării) trebuie resetat la valoarea inițială. Acest lucru trebuie făcut înainte de a procesa
un nou flux de date, dar se poate face mereu când se dorește resetarea algoritmului de detecție a
mișcării.
Această clasă (implementată tot în platforma Aforge.NET) numără obiectele care se mișcă în
cadru și le evidențiază cu un dreptunghi de o anumită culoare . Aceste obiecte sunt asigurate de
interfața IMotionDetector. Algoritmul calculează și evidențiază doar acele obiecte care satisfac
dimensiunile limită a proprietăților MinObjectWidth și MinObjectHeight. Se poate configura
acest algoritm astfel încât să se ignore obiectele mai mici de o anumită dimensiune. Aceste
proprietăți se setează din cod astfel:
mp.MinObjectsHeight = 15;
mp.MinObjectsWidth = 15;
37
Spre deosebire de interfețele de procesare și detecție a mișcării, clasa MotionDetector oferă și
alte metode adiționale necesare, astfel încât algoritmii pot fi aplicați nu doar imaginilor
UnmanagedImage, dar și claselor Bitmap din .NET. Cu ajutorul proprietății MotionZones se
poate specifica un set de zone cu dreptunghiuri pentru evidențiere a zonelor, astfel este luată în
calcul și post-procesată doar mișcarea în aceste zone. Mișcarea din afara zonei de mișcare este
ignorată. Dacă este setată această proprietate, metoda ProcessFrame(UnmanagedImage) va reda
toate mișcările detectate de algoritm, dar nu este localizată în acea determinată zonă.
Imaginea lastFrame este de tipul Bitmap și a fost creată din necesitatea de a reține
ultimul cadru de procesat pentru a ajuta la conversia din formatul ColorImageFrame.
lastFrame = ImageToBitmap(frame);
Funcția care face această conversie se numește ImageToBitmap() și ia ca dată de intrare o
imagine cu formatul ColorImageFrame și returnează un Bitmap. Pentru mai multe detalii vezi
4.3 Pregătirea formatului imaginii necesar platformei Aforge.NET.
38
// dispose old frame
if (lastFrame != null)
{
lastFrame.Dispose();
}
lastFrame = ImageToBitmap(frame);
int detectedObjectsCount = 0;
if (rectangles != null)
{
Console.WriteLine("left: {0} top: {1} right: {2} bottom: {3}",
rectangles[i].Left, rectangles[i].Top, rectangles[i].Right, rectangles[i].Bottom);
detectedObjectsCount = mp.ObjectsCount;
rectNr.Text = "Zones nr: " + detectedObjectsCount.ToString();
}
}
}
}
else
{
objectsCountLabel.Text = "Motion level: " +
(detector.ProcessFrame(lastFrame)).ToString("#.##");
txtInfo.Text = "No motion";
}
}
}
}
Zonele de mișcare le-am desenat pe canvas-ul unde este afișat fluxul color de date de la
senzorul Kinect. Acestea sunt reprezentate prin dreptunghiuri (în cazul de față laturile lor au
dimensiuni egale) de culoare albastră (vezi figura 3.2.1). Pentru fiecare zonă de mișcare se iau
coordonatele dreptunghiului (stânga, sus, dreapta, jos), se creează dreptunghiurile cu setările
corespunzătoare și se afișează pe zona de imagine.
System.Drawing.Rectangle[] rectangles = mp.ObjectRectangles;
39
{
System.Windows.Shapes.Rectangle rect = new System.Windows.Shapes.Rectangle ();
rect = new System.Windows.Shapes.Rectangle();
rect.Stroke = System.Windows.Media.Brushes.Blue;
rect.HorizontalAlignment = HorizontalAlignment.Left;
rect.VerticalAlignment = VerticalAlignment.Center;
rect.Height = 80; //rectangles[i].Top;
rect.Width = 80; //rectangles[i].Right;
canvas.Children.Add(rect);
Canvas.SetLeft(rect, rectangles[i].Left);
Canvas.SetTop(rect, rectangles[i].Top);
Canvas.SetRight(rect, rectangles[i].Right);
Canvas.SetBottom(rect, rectangles[i].Bottom);
}
Datele preluate cu senzorul Kinect trebuie pregătite pentru formatul cerut de librăria
Aforge.NET, pentru a fi procesate. Formatul imaginii captate de Kinect este de tipul
ColorImageFrame iar Aforge.NET (AForge.Imaging.UnmanagedImage) cere formatul Bitmap.
40
Bitmap ImageToBitmap(ColorImageFrame Image)
{//..}
Funcția preia formatul ColorImageFrame și returnează un Bitmap cu aceleași date ale pixelilor.
Metoda funcționează doar pentru ColorImageFrame care folosește 32 bit pentru formatul de date
RGBA (folosit și cu senzorul video a Kinectului).
Mai întâi se preia datele pixelilor ca un array de bytes:
byte[] pixeldata = new byte[Image.PixelDataLength];
Image.CopyPixelDataTo(pixeldata);
Obiectul Bitmap folosește o altă clasă (BitmapData) pentru a crea un buffer de memorie care să
stocheze datele biților. Metoda LockBits returnează un obiect de tip BitmapData care este blocat
în memoria buffer unde se află datele pixelilor. De obicei, această operație copiază datele
bitmap-ului din bitmap în buffer pentru a putea lucra cu ele. Se poate seta opțiunea WriteOnly
dacă se dorește ca memoria buffer să aloce dimensiunea corectă fără a transfera nimic din
obiectul Bitmap.
Deci, pentru a crea buffer-ul se face astfel:
Memoria buffer așteaptă ca biții să fie transferați. Pentru a face acest lucru, este nevoie să se
folosească un transfer de tip memory-to-memory, oferit de funcții InterOp. Trebuie deci, adăugat
la începutul proiectului:
using System.Runtime.InteropServices;
Este nevoie de un pointer către zona de început a memoriei buffer iar apoi se va folosi metoda
Copy() pentru a transfera datele:
Marshal.Copy(pixeldata, 0, ptr, Image.PixelDataLength);
pixeldata stochează adresa de început a imaginii din buffer în ptr. Metoda Copy() va copia
datele bits în buffer-ul către care ptr pointează. Al doilea parametru al metodei Copy() este un
offset, de obicei zero, iar ultimul parametru returnează numărul total de bytes ce trebuie copiați.
bmap.UnlockBits(bmapdata);
return bmap;
Bitmap-ul care este returnat poate fi utilizat în platforma de viziune artificială Aforge.NET.
41
Capitolul 5 - Detecția mișcării în secvențe Skeleton preluate de la
senzorul Kinect
Senzorul Kinect permite localizarea joncțiunilor care descriu poziția figurii umane
(skeleton tracking).
42
}
Amândouă mâini sunt ridicate dacă coordonata y a mâinii drepte și stângi este mai mare decât
cea a cotului drept, respectiv stâng.
Pentru a detecta dacă mâinile nu sunt ridicate, am luat ca punct de referință joncțiunea spinei,
astfel:
// Right and Left hand down
if (handRight.Position.Y < spine.Position.Y && handLeft.Position.Y < spine.Position.Y)
{
stanga_sus = false;
dreapta_sus = false;
maini_sus = false;
maini_jos = true;
this.gestureDetectionLabel.Text = "RIGHT and LEFT hands down!";
}
Fig. 5.2 Detecția ridicării mâinii stângi și drepte deasupra cotului stâng, respectiv drept
43
Capitolul 6 - Concluzii
În lucrarea de față s-a dorit dezvoltarea unei aplicații care să achiziționeze date de la
senzorul Microsoft Kinect și să le proceseze prin algoritmi de detecție a mișcării. Zonele de
mișcare de pe scenă, numărul de zone, intensitatea mișcării și scheletul cu articulațiile corpului
sunt transmise și folosite în vederea realizării de efecte digitale care să fie proiectate pe ecrane de
dimensiuni mari pe toată durata concertului muzical.
Proiectul în ansamblu a fost gândit astfel încât prezența mișcării din cadru și ridicarea mâinilor
să pornească anumite efecte iar zonele de mișcare să le modeleze pe tot ecranul. Numărul de
zone va determina câte obiecte se vor crea iar valoarea intensității mișcării de pe scenă va
schimba culorile, viteza de rotație sau de mișcare a elementelor din reprezentarea grafică. Astfel,
concertul muzical va primi o nouă dimensiune, muzica va fi acompaniată de efecte dinamice,
modelate în timp real pe baza mișcării trupei de pe scenă și interacțiunea cu publicul va fi una
mult mai creativă.
Se poate demonstra cum datele achiziționate cu senzorul Kinect din cadrul proiectului pot
fi utile și în alte direcții precum cel educațional. De exemplu, se pot comanda controale printr-o
simplă mișcare a mâinii drepte sau stângi (figura 6.2). Pentru aceasta m-am folosit de harta de
adâncime a senzorului Kinect și de componenta Microsoft.Kinect.Toolkit.Controls care
implementează interacțiunile Kinect bazate pe gesturi, concepute pentru controlul fără mâini a
aplicațiilor și a altor forme de interactivitate. Kinect calculează distanța mâinii față de senzor cu
senzorul de adâncime. Dacă mâna se apropie de senzor și dacă mâna interactivă controlată de pe
formular se află pe control, acesta se va apăsa și evenimentul corespundent se va declanșa.
De altfel, cu ajutorul coordonatelor xy ale încheieturilor (cap, mâna dreaptă și mâna stângă)
preluate cu secvențele Skeleton se poate derula un fișier Powerpoint ridicând mâna dreaptă sau
stângă (figura 6.1).
Figura 6.1 Control fișier Powerpoint prin ridicarea mâinii stângi, respectiv drepte
44
Interfața grafică realizată în mediul de dezvoltare Visual Studio 2015, în limbajul de
programare C# se poate vedea în figura 6.2. Aceasta conține fluxul de date color împreună cu
articulațiile din secvențele Skeleton, harta de adâncime (în partea de stânga-jos, cu albastru) și
cea care identificatorul persoanelor (diferite persoane sunt reprezentate cu diferite culori).
Zonele de mișcare sunt reprezentate în imagine prin pătrate albastre. În partea de sus, din
dreapta, sunt afișate datele achiziționate cu Kinect referitoare la prezența mișcării din cadru,
detecția cărei mâini este ridicată, intensitatea mișcării și numărul de zone de mișcare. De
asemenea, de pe interfață se poate regla și motorul de înclinație.
Cu siguranță, la acest proiect pot fi făcute multe îmbunătățiri. De exemplu, se poate face
un streaming în timpul concertului, pe pagina de Facebook a trupei și să se preia like-urile la
postare și anumite comentarii făcute de public, cu scopul de a le afișa pe ecran sub formă de
efecte. De asemenea, s-ar putea capta și sunetul cu ajutorul microfonului multidirecțional al
senzorului Kinect, zona și unghiul de unde vine acesta pentru a putea „jongla” mai mult cu
culorile în cadrul efectului digital.
45
Referințe
[1] Giorio C., Fascinari M., “Kinect in Motion - Audio and Visual Tracking by Example”,
ISBN-13: 978-1849697187, Packt Publishing, 2013
[2] Reas C., Fry B., “Processing: A Programming Handbook for Visual Designers and Artists”,
ISBN-13: 978-0262028288, Massachusetts Institute of Technology, 2014
[3] AFORGE.NET Framework http://www.aforgenet.com/framework/ (ultima accesare: 13 iulie
2016)
[4] Accord.NET Framework http://accord-framework.net/ (ultima accesare: 13 iulie 2016)
[5] AFORGE.NET Framework http://www.aforgenet.com/framework/docs/ (ultima accesare: 13
iulie 2016)
[6] Microsoft Kinect v1.8 https://it.wikipedia.org/wiki/Microsoft_Kinect (ultima accesare: 13
iulie 2016)
[7] Microsoft Kinect v2.0 https://en.wikipedia.org/wiki/Kinect (ultima accesare: 13 iulie 2016)
[8] Reverse Engineering https://it.wikipedia.org/wiki/Reverse_engineering (ultima accesare: 13
iulie 2016)
[9] Bayer filter https://en.wikipedia.org/wiki/Bayer_filter (ultima accesare: 13 iulie 2016)
[10] CCD e CMOS, il cuore della telecamera http://www.dseitalia.it/tut_tel_ccd.htm (ultima
accesare: 13 iulie 2016)
[11] Dispozitive de captare a imaginii http://vega.unitbv.ro/~nicolaeg/SCTRI%20-
ROBOTICA/Note%20de%20curs/StPPT%20C8%20Dispozitive%20de%20captare%20a%20
imaginii..pdf (ultima accesare: 13 iulie 2016)
[12] Dichroic prism https://en.wikipedia.org/wiki/Dichroic_prism (ultima accesare: 13 iulie
2016)
[13] Cuttoff frequency https://en.wikipedia.org/wiki/Cutoff_frequency (ultima accesare: 13
iulie 2016)
[14] Electret microphone https://en.wikipedia.org/wiki/Electret_microphone (ultima accesare:
13 iulie 2016)
[15] Kinect for Windows SDK v1.8 https://www.microsoft.com/en-
ca/download/details.aspx?id=40278 (ultima accesare: 13 iulie 2016)
[16] Kinectic vision looking deep into depth http://www.slideshare.net/ppd1961/kinectic-
vision-looking-deep-into-depth (ultima accesare: 13 iulie 2016)
[17] Motion detection https://en.wikipedia.org/wiki/Motion_detection (ultima accesare: 13
iulie 2016)
[18] Computer vision https://en.wikipedia.org/wiki/Computer_vision (ultima accesare: 13
iulie 2016)
[19] Kinect for Windows Architecture https://msdn.microsoft.com/en-us/library/jj131023.aspx
(ultima accesare: 13 iulie 2016)
[20] Readme for Kinect for Windows SDK - Beta 2 release https://www.microsoft.com/en-
us/kinectforwindows/develop/readme.htm (ultima accesare: 13 iulie 2016)
[21] Getting the Next Frame of Data by Polling or Using Events
https://msdn.microsoft.com/en-us/library/hh973076.aspx (ultima accesare: 13 iulie 2016)
[22] Thresholding (image processing)
https://en.wikipedia.org/wiki/Thresholding_(image_processing)
(ultima accesare: 13 iulie 2016)
46