BABE S¸ -B OLYAI U NIVERSITY C LUJ –NAPOCA FACULTY OF M ATHEMATICS AND I NFORMATICS S PECIALIZATION : C OMPUTER S CIENCE License Thesis
Embedded vision – Command recognition Abstract
This thesis is about creating a library that can be used in different applications for command recognition. Alongside the library I also made an application that gives a good example about the potential of this library. The whole code was written in C++.The most important technologies used was openCV for the image processing, openGL and QtFramework for the example application. The library consists of five main parts: retrieving a depth image from an arbitrary device, processing this image, filtering out the processed image, interpreting the filtered image and communicate with the application. For the depth image retrieval I used the kinect device and the libfreenect library to communicate with this device. For image processing I mainly used some basic algorithms provided by the openCV library. For filtering and recognizing the processed image i used my own methods. At the end of interpretation I simply signal the application if the command it was waiting for has occurred. The application that uses this library makes it possible to do basic transformations (translation and rotation) on a figure displayed with hand commands. To display the figure and apply transformations on it I used openGL and QtFramework. This work is the result of my own activity. I have neither given nor received unauthorized assistance on this work.
J ULY 2016 A DVISOR : A SSIST PROF. DR . C SATÓ L EHEL
G RIEB DANIEL ROBERT
BABE S¸ -B OLYAI U NIVERSITY C LUJ –NAPOCA FACULTY OF M ATHEMATICS AND I NFORMATICS S PECIALIZATION : C OMPUTER S CIENCE
License Thesis
Embedded vision – Command recognition
S CIENTIFIC SUPERVISOR :
S TUDENT:
A SSIST PROF. DR . C SATÓ L EHEL
J ULY 2016
G RIEB DANIEL ROBERT
U NIVERSITATEA BABE S¸ -B OLYAI , C LUJ –NAPOCA ˘ FACULTATEA DE M ATEMATIC A˘ SI ¸ I NFORMATIC A S PECIALIZAREA I NFORMATIC A˘
Lucrare de licent¸a˘
Viziunea calculatorului – Recunoas, terea comenzilor
˘ C ONDUC ATOR STIIN ¸ TIFIC ¸ :
A BSOLVENT:
L ECTOR DR . C SATÓ L EHEL
I ULIE 2016
G RIEB DANIEL ROBERT
BABE S¸ -B OLYAI T UDOMÁNYEGYETEM KOLOZSVÁR M ATEMATIKA ÉS I NFORMATIKA K AR I NFORMATIKA S ZAK
´ Allamvizsga-dolgozat
´ ıtog ´ epes ´ ´ as ´ – Szam´ lat ´ Parancsfelismeres
T ÉMAVEZET O˝ :
S ZERZ O˝ :
DR . C SATÓ L EHEL , EGYETEMI ADJUNKTUS
G RIEB DANIEL ROBERT
2016 J ÚLIUS
´ Tartalomjegyzek 1. Bevezeto˝ 1.1. Fejezet leírás . . . 1.2. . . . . . . . . . . 1.3. Számítógépes látás 1.4. Képfeldolgozás . . 1.5. Parancsfelismerés . 1.6. Fejezet összefoglaló
. . . . . .
4 4 4 5 6 9 10
. . . . . . . . . . .
12 12 12 13 13 15 18 18 19 20 21 22
. . . . . . . . . . .
23 23 23 23 23 23 23 23 23 23 23 23
4. A program meg´ır´asakor felmerul ¨ o˝ neh´ezs´egek 4.1. Fejezet leírás . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2. C++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
24 24 24
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
¨ 2. Parancsfelismero˝ konyvt´ ar 2.1. Fejezet leírás . . . . . . . . . . . . . . . . . . 2.2. A könyvtár felépítése . . . . . . . . . . . . . . 2.3. A komponensek részletes leírása . . . . . . . . 2.3.1. A képkinyer˝o komponens . . . . . . . 2.3.2. A képfeldolgozó komponens . . . . . . 2.3.3. A sz˝ur˝o komponens . . . . . . . . . . . 2.3.4. Az értelmez˝o komponens . . . . . . . . 2.3.5. Az felhasználó alkalmazás komponens . 2.4. A könyvtarra épül˝o alkalmazás . . . . . . . . . 2.5. A könyvtár korlátai . . . . . . . . . . . . . . . 2.6. Fejezet összefoglaló . . . . . . . . . . . . . . . ´ ak 3. Felhaszn´alt technologi´ 3.1. Fejezet leírás . . . 3.2. C++ . . . . . . . . 3.3. QtCreator . . . . . 3.4. Qmake . . . . . . . 3.5. A kinect ezköz . . 3.6. Libfreenect . . . . 3.7. OpenCV . . . . . . 3.8. OpenGL . . . . . . 3.9. QtFramework . . . 3.10. Git . . . . . . . . . 3.11. Fejezet összefoglaló
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
2
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . .
TARTALOMJEGYZÉK 4.3. 4.4. 4.5. 4.6.
A képfeldolgozás . . . . A könyvtár megtervezése A könyvtár általánossága Fejezet összefoglaló . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
˝ egei 5. A program tov´abbfejleszt´esi lehetos´ 5.1. Fejezet leírás . . . . . . . . . . . . . . . . . . 5.2. Kib˝ovíthet˝oség . . . . . . . . . . . . . . . . . 5.3. Komponensek lecserélése . . . . . . . . . . . . 5.4. Néhány fejlettebb funkcionalitás megvalósítása 5.5. Fejezet összefoglaló . . . . . . . . . . . . . . . ¨ 6. Osszefoglal o´
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . .
24 25 25 25
. . . . .
26 26 26 27 27 27 28
3
1. fejezet
Bevezeto˝
1.1. Fejezet leírás Ebben a fejezetben összefoglalom röviden hogy mit valósítottam meg a dolgozatomban, valamint néhány általános tudományos területet szeretnék bevezetni melyek általános ismerete szükséges az alkalmazás megértésese. Ezen területek valamint ezekben megjelen˝o fogalmak képzik az alapját az alkalmazásnak. Ezekr˝ol egy általános leírást szeretnék adni.
1.2. A dolgozatom f˝o része egy C++ segítségével íródott könyvtár, egy másik része pedig ennek a könyvtárnak a felhasználásával megírt alkalmazás. A könyvtár célja hogy egy olyan funkcionalitást biztosítson a felhasználó alkalmazásnak mely segítségével f˝oleg kézzel(viszont lehet˝oség van másra is), végzett parancsokat tud felismerni és ezt tetsz˝olegesen letudja kezelni. Igyekeztem úgy megírni ezt a könyvtárat hogy ezt minél általánosabban fel lehessen használni es nagy hangsúlyt fektettem ennek kib˝ovíthet˝oségének érdekeben. F˝o célok amiket figyelembe vettem ennek megírásakor: több különböz˝o eszköz lekezelésére való lehet˝oség, ne csak kéz parancsok felismerésre legyen lehet˝oség hanem például kar, láb vagy fej által végzett parancsok felismerése valamint hogy az alkalmazás minél egyszer˝ubben felhasználhassa ezt a könyvtárat. A könyvtárat sokféleképpen fellehet használni, például egy alkalmazás mely kapcsolatban van különböz˝o eszközökkel és ezekkel tud kommunikálni, felhasználva a megírt könyvtárat könnyen megtudná valósítani, hogy például kézzel(viszont fej, kar vagy tetsz˝oleges tárgy segítségével is megvalósítható) vezérelje ezeket az eszközöket. Konkrétan ha a kezem ökölbe szorítom ezt lekezelheti úgy, hogy lekapcsolja a villanyt valamint ha a kezem ökölbe szorítom és ezt elkezdem mozgatni akkor az ajtót ki es bezárja a mozgatás irányának megfelel˝oen. A konkrét alkalmazás amit megírtam ezen könyvtár segítségével transzformációkat tesz lehet˝ové egy tetsz˝olegesen megjelenített alakzaton. A kéz mozgatása jelenti a forgatást valamint az eltolást, attól függ˝oen hogy milyen parancsot adtam meg.
4
1. FEJEZET: B EVEZET O˝
1.3. Számítógépes látás A számítógépes látás azt jelenti, hogy a számítógép képes megérteni hogy mi történik a környezetében. Ez úgy történik, hogy a különböz˝o képeket külön értelmezve vannak es ezekb˝ol következtetéseket vonunk le. Az ember képes egyszer˝uen megkülönböztetni a különböz˝o tárgyakat, alakzatokat amiket a környezetben lát. Viszont a számítógép, hogy megértse ezeket bonyolult képfeldolgozásra valamint ezen folyamat végén kinyert információhoz, hogy értelmezni tudjuk erre különböz˝o algoritmusokra van szükség. Az egyik nehézség abból adódik hogy a különböz˝o tárgyakról meghatározott információ nem elégséges ahhoz, hogy a rengeteg formájú és ezeknek deformált akár transzformált állapotban való felismerésére lehet˝oség legyen. Számítógépes látásnak tekinthetjük egyetlen kép feldolgozását is es ennek az értelmezését. Egy képet többféleképpen tudunk értelmezni és ebb˝ol kifolyólag a számítógépes látásnak több különböz˝o ágazatait különíthetjük el. Ilyen például a tárgy felismerés, esemény felismerés valamint ezekb˝ol a különböz˝o képekb˝ol való automatikus tanulás. B˝ovebben a tárgy felismerésr˝ol valamint az esemény felismerésr˝ol fogok beszélni mivel f˝oleg ezeket használtam fel a könyvtár megírásában viszont el˝oször a számítógépes látás kialakulásáról valamint ennek a fejl˝odésér˝ol fogok írni [4]. A legels˝o próbálkozás mely szerette volna megoldani a számítógépes látás problémát az a The summer vision project néven ismert Seymour Papert-t˝ol. A projekt végs˝o célja tárgyfelismerés lett volna. Ez a projekt természetesen nem volt sikeres mivel a számítógépes látás nem olyan egyszer˝u probléma mint azt els˝ore gondolnánk. Mivel embereknek nem okoz gondot megkülönböztetni a különböz˝o tárgyakat valamit kapcsolatot teremteni ezek között es értelmezni ezek mozgását azt gondolhatnánk hogy a számítógép is képes egyszer˝uen megvalósítani ezt. Viszont a gyakorlatban absztrakt matematikai fogalmakra valamint komplex algoritmusokra van szükség egy viszonylag egyszer˝u tárgyfelismerésre is. Egy kutatás szerint az agy egy bizonyos része körülbelül 40-70%-ban a vizuálisan bejöv˝o jelek feldolgozásával tölti. Tehát nekünk egyszer˝unek t˝unik értelmezni mi zajlik a környezetünkben viszont az agyuk valójában sokat dolgozik ahhoz hogy értelmezze a vizuálisan beérkez˝o jeleket. Miért olyan nehéz a számítógépes látás? Talán az egyik oka az hogy az emberi agyban látásért felel˝os rendszer nagyon komplex es rengetek különböz˝o dologban nagyon jó mint például a arcfelismerés. Képesek vagyunk felismerni valakit egy olyan képr˝ol ami esetleg évekkel ezel˝ott készült róla, különböz˝o megvilágítások és elhelyezkedést˝ol függetlenül és mindezt egy nagyon rövid id˝o alatt er˝ofeszítés nélkül tesszük amire a számítógépek nem képesek minden csak bizonyos esetekben. Valamint úgy t˝unik az agyunk képes korlátlan mennyiség˝u arcot felismerni. Ha szeretnénk a számítógépeket is ilyen szintre emelni olyan problémákat kell megoldanunk mint például: – Hogyan tároljuk azt a rengetek információt ami az agy tárol egy olyan módon, hogy ezekhez könnyen es hatékonyan hozzáférjünk. – Hogyan valósítunk meg olyan technológiát úgy hardver mint szoftver szemszögb˝ol mely képes arra a rengeteg számításra amire az agyunk képes. – Hogyan írunk olyan algoritmusokat amelyek nem csak egy bizonyos feladat megoldását teszik lehet˝ové hanem általánosak, m˝uködnek bármilyen körülmények között, képesek fejl˝odni és ezt 5
1. FEJEZET: B EVEZET O˝ mind valós id˝oben képesek biztosítani. Az els˝o ötlet mely számítógépes látás problémát szerette volna megoldani az agy funkcionalitásának a tanulmányozásából született. 1958-ban Frank Rosenblatt egy új algoritmust mutatott be, a perceptron modellt ami a neurális hálók egy egyszer˝usített változata. Ezt kezdetben arra szerette volna használni hogy képek között tegyen különbséget. Bizonyos képeken csak egy erd˝o volt, más képeken pedig ugyancsak erd˝o viszont álcázott tankok is voltak rajta. Ezek között szeretett volna különbséget tenni. Ez tulajdonképpen egy bináris osztályozásnak felel meg. Habár a teszteken úgy t˝unt, hogy helyesen osztályozza a képeket a valós teszten helytelen adatokat adott. Ennek az oka az volt hogy a képek különböz˝o körülmények között voltak készítve és ebb˝ol adódott a hiba. Ezt a kudarcot egy hosszú szünet követte melyben a számítógépes látásban nem voltak jelent˝os fejl˝odések. Ebben az id˝oszakban a kutatók f˝oleg képfeldolgozással foglalkoztak mely a képek pixel szint˝u feldolgozását jelentette. Ezzel jó eredmények születtek mint például egy képben megjelen˝o tárgyak széleinek a behatárolása, képek sz˝urése mellyel látványos hatásokat érhetünk el, képek s˝urítése anélkül hogy a lényeges információkat elvesztenénk. Ezek ugyan segítik a számítógépes látást nem születtek olyan eredmények melyek fellendítették volna ezt a területet egészen a korai 90-es évekig amikor megjelentek a konvolúciós neurális hálók melyek képesek voltak számjegyfelismerésre ami nagy haladásnak számított abban az id˝oszakban. Viszont komplexebb feladatok megoldására nem voltak alkalmasak. Ezt követ˝oen rengetek új algoritmus született melyek fellendítették a számítógépes látás-ban végzett kutatásokat. Ezeket az algoritmusoknak a felhasználásával olyan problémákra született megoldás mint például az arcfelismerés, vagy tárgyfelismerés. Napjainkban is nagy kutatások folynak ezen a területen es nagy fejl˝odéseket figyelhetünk meg. Ilyen például a deep learning networks melyek a neurális hálók egy modern változata. Ezzel a kép tartalmát nagyon pontosan tudjuk osztályozni. Napjainkban sok felhasználását figyelhetjük meg a számítógépes látás fejl˝odése tett lehet˝ové. Ilyen például a automatikusan irányított robotok melyek általános feladatok elvégzésére ugyan nem képesek viszont több speciális feladat elvégzését teszik lehet˝ové, automatikusan vezérelt járm˝uvek melyek fejl˝odése lehet˝oséget adna az emberi hibákból származó balesetek elkerülésére, esemény felismerés melyeket fellehet használni biztonsági rendszerekben vagy statisztikai adatok készítésére automatikusan, fejlettebb kommunikációs lehet˝oség a számítógéppel amir˝ol b˝ovebben fogok beszélni a következ˝o fejezetekben. Még valószín˝uleg sok munkába es id˝obe fog telni amíg számítógépek képesek lesznek megközelítik az ember értelmezési funkcionalitását de az eredmények azt mutatják hogy ez lehetséges.
1.4. Képfeldolgozás A képfeldolgozás [1] szorosan kapcsolatban van a számítógépes látással és a jel feldolgozásnak egy al ága. A digitális kép átalakítását vagy esetleg ebb˝ol valamilyen információ kinyerését jelenti. Bemenetként egy képet (ez leggyakrabban egy intenzitás kép) kapunk, ezt feldolgozzuk hatékony algoritmusok segítségével és kimenetként vagy az eredeti kép egy feldolgozott változatát kapjuk vagy ennek valamilyen jellemz˝oit. Több különböz˝o kép típust különböztetünk meg. Ezek közül a három legfontosabbat
6
1. FEJEZET: B EVEZET O˝ szeretném megemlíteni [7]. – Indexelt kép. Ebben az esetben a képet két mátrixra bontjuk fel egy adatmátrixra melynek m sora es n n n oszlopa van es indexeket tartalmaz és egy szín információkat tároló mátrixra melynek m sora es 3 oszlopa van, ahol a sor minden eleme tartalmazza piros, zöld illetve kék intenzitásokat. Az adatmátrixban minden egyes indexnek megfelel egy-egy érték a színmátrixból. Egy adatmátrix felhasználhat különböz˝o szín mátrixokat. – Intenzitás kép. Itt egyetlen mátrix elegend˝o hogy eltároljuk az információt. A mátrix minden egyes eleme megadja az adott képpixel intenzitását. Az intenzitásnak különböz˝o intervallumokat adhatunk meg, melyek lehetnek valós 0 és 1 közötti értékek vagy akár egész számok például 0 és 255 között ha 1 byte-on szeretnénk éltáróni az egyes pixelek intenzitását. – RGB(Truecolor) Képek. Ezt egy m×n×3 dimenziójú mátrixszal tudjuk ábrázolni. Hasonlóan mint az indexelt kép esetében a piros, zöld es kék intenzitásokat tároljuk viszont egyetlen mátrixban. A grafikus fájlok az RGB képeket 24 bit-es képként tárolják ahol minden egyes komponensnek 8 bit felel meg. Ízzel a tárolási formával akár 16 millió különböz˝o színt eltudunk tárolni, ebb˝ol adódik a "Truecolor image" elnevezés. Egy metódus mely segítségével információkat tudunk kinyerni egy képb˝ol az a különböz˝o tárgyak széleinek a behatárolása. Ez egy alapvet˝o eszköz melyet felhasználunk képfeldolgozásban és számítógépes látásban. Ezt sokféleképpen fel tudjuk használni mint például kép szegmentálása mely segítségével a kép különböz˝o részeit széjjeltudjuk választani. Ez abban áll, hogy a kép azon pontjait szeretnénk behatárolni ahol egy éles átmenetet figyelhetünk meg a képpontok között. A folytonosság változása egy képben, ami alatt tulajdonképpen a képpontok hirtelen váltakozást jelenti, több különböz˝o oka lehet amelyek közül a legfoltosabbak a következ˝ok: mélységbeli különbségek mely alatt a távolságot értjük a képpont és a kamera között, a tárgyak anyagi jellemz˝oi közötti különbség valamint fénybeli különbségek. Egy egyszer˝u szélbehatároló algoritmus esetén bizonyos helyzetekben sikeresen betudjuk határolni a kép határait. Ezen határ menti görbék tanulmányozása segítségével meghatározhatjuk hogy milyen tárgyat látunk viszont ezt csak nagyon általánosan tehetjük meg mivel a határok belsejében lév˝o részleteket nem tudjuk meghatározni így ezzel a módszerrel csak következtetéseket tudunk levonni viszont bizonyos esetekben ahol egy képen a bizonyos tárgyak csak egy általános struktúráját szeretnénk behatárolni arra elegend˝o. Viszont ett˝ol fejlettebb szél behatároló algoritmusok is léteznek melyeknek az lenne a motivációja, hogy olyan összekapcsolt görbéket határoljunk be, mely a lényeges változásokat hordoznák az eredeti képb˝ol. Ennek segítségével lényegesen letudjuk csökkenteni a feldolgozandó adatmennyiséget viszont a lényeges információk megmaradnának. A továbbiakban egy egyszer˝u képfeldolgozó algoritmust mutatok be melynek az lenne a célja, hogy egy intenzitás képben behatároljuk a széleket. Ez a Sobel [6] határfelismer˝o metódus lenne mely még Sobel–Feldman metódusként is ismert. A nevét Irwin Sobel valamint Gary Feldman-r˝ol kapta. Az ötlet 1968-ban volt bemutatva a Stanfordi mesterséges intelligencia laboratóriumban. El˝oször szeretném 7
1. FEJEZET: B EVEZET O˝ bevezetni a kép gradiens [5] fogalmát mivel ezek szoros kapcsolatban állnak. A kép gradiens a kép intenzitásának vagy színének az irányított változását határozza meg. Matematikailag ez egy deriválást jelent a függ˝oleges illetve a vízszintes irányba. Minden pontban a deriválás során kapott gradiens vektorpontok abba az irányba mutatnak amelybe az intenzitásváltozás a legnagyobb. Ezt elképzelhetjük úgy mintha a kép egy felület lenne es ezt parciálisan deriválva az irányok szerint megkapunk vektorokat melyek a lokális minimum felé mutatnak. Ezeknek a vektoroknak a hossza pedig megadja azt hogy milyen mértékben változnak ezen irányokban. A gond azzal van hogy a digitális képeket csak diszkrét pontokban ismerjük így a deriváltat nem tudjuk meghatározni. Ezert el˝oször egy folytonos függvényt kell meghatároznunk mely áthalad ezeken a képpontokon es ennek a függvény deriváljuk a kép gradiens meghatározása érdekében. Ha ezt a folytonos függvény jelöljük f-el akkor egy x y pontban a gradiens értékét a következ˝o képlettel határozhatjuk meg: " ∇f =
gradx
#
grady
"
∂f ∂x ∂f ∂y
=
#
A gradiens irányának a meghatározására a következ˝o összefüggést használjuk: −1
α = tan
gx gy
A metódus egy úgynevezett Sobel operatoron alapszik mely segítségével közelíteni tudjuk a intenzitás kép gradiensét. A kép minden egyes pontjában ennek az operának a segítségével megkapjuk a megfelel˝o gradiens vektor vagy vesszük ennek a normáját. A Sobel operátor felhasznál két 3x3-as kernelt. Képfeldolgozásban kernel alatt melyet még konvolúciós mátrixnak vagy maszknak is szoktak nevezni egy mátrixot értünk melyet felhasználhatunk a képen lev˝o tárgyak határainak detektálására, élesíteni vagy esetleg homályosítani a képet. Ezt egy konvolúcióval határozzuk meg a kernel es a kép között. Ez hasonlít a matematikai konvolúcióhoz ami egy matematikai operátort jelent két függvény között, létrehozva egy harmadik új függvényt mely az el˝oz˝o kett˝o közül valamelynek egy módosított változata. Ebben az esetben a konvolúció a Sobel operátor alkalmazását jelenti a kép es a kernel között. A horizontális illetve vertikális deriváltakra az közelítést a következ˝oképpen kapjuk meg:
−1 0 1
Gradx = −2 0 2 ∗ Image −1 0 1
−1 −2 −1
Grady = 0
0
1
2
0 ∗ Image 1
Ezeket a gradiens értékeket egybekombinálva megkaphatjuk az abszolút gradiens nagyságát: q Grad = Grad2x + Grad2y
8
1. FEJEZET: B EVEZET O˝ Mivel ennek a kiszámolása költséges ezért gyakorlatban ennek egy másik alakját használjuk: Grad = |Gradx | + |Grady | Valamint a szélek orientációjának behatárolása érdekében ezt az összefüggést használhatjuk: β = arctan(Gradx /Grady )
1.5. Parancsfelismerés Parancsfelismerés alatt a különböz˝o gesztusok értelmezését értjük matematikai algoritmusok segítségével. A gesztusoknak nagyon sok formája lehet és minden egyes gesztust különböz˝o módon kell értelmeznünk. Ahhoz hogy az algoritmusok ne keverjék valamint ne tévesszék össze ezeket a gesztusokat részletes és nagyon pontos információra van szükség, tehát fejlett képeldolgozásra van szükség annak érdekében hogy helyesen tudjuk értelmezni ezeket a gesztusokat. Egy osztályozási lehet˝osége [6] a parancsfelismerésnek négy dichotómia(kett˝osség) segítségével tehetjük meg: – A cselekvés és a jel kett˝ossége. Ez alatt azt értjük hogy bizonyos gesztusok egy cselekvést fejeznek ki viszont más gesztusok viszont valamit jeleznek. Például ha valaki szalad ez egy cselekvés viszont ha valaki integet valakinek akkor az egy jel mivel ezzel közölni szeretne valakit valamivel ellenben a szaladással aminek nincs különösebb jelent˝osége. Ennek a két osztálynak az elkülönítése lehet˝oséget ad arra hogy csak azokat a gesztusokat értelmezzük amelyeknek valódi jelentése van. – Az átláthatóság es átláthatatlanság kett˝ossége. Ez arra utal hogy bizonyos gesztusokat könnyen képesek vagyunk értelmezni, átlátni viszont vannak olyanok melyeket nagyon nehezen. Az átlátható gesztusokat általános gesztusoknak is szoktak nevezni, ezek olyan standard gesztusok melyek kultúrától es más befolyásoló tényez˝okt˝ol függetlenül értelmezhet˝oek és azonos a jelentése mindenki számára. Viszont vannak más gesztusok melyek különböz˝o kultúrákban más-más dolgot jelentenek. Hogy ezeket is megtudjuk különböztetni parancsfelismeréssel nem csak magát a gesztust kell figyelembe vennünk hanem a kontextust is amelyben ez történt. – Centrifugális es centripetális kett˝osség arra utal hogy mennyire volt szándékos a végzett gesztus. A centrifugális gesztusok egy bizonyos tárgy irányába mutatnak, a centripetális gesztusok viszont nem. Általában a centrifugális gesztusokkal foglalkozunk mivel ezek utalnak például egy tárgy vezérlésére. – Az utolsó kategória ebben a típusú osztályozásban a egy jelentéssel rendelkezés˝u gesztus rendszerek es a több jelentéssel rendelkezés˝u gesztus rendszerek. Ebben az a különbség hogy bizonyos
9
1. FEJEZET: B EVEZET O˝ gesztusok több jelentéssel rendelkeznek mint például a beszéd mivel maga a gesztus nem határozza meg mit akartunk elérni ezzel, ellenben a jel beszéd nem több jelentés˝u mivel maga a gesztus önmaga határozza meg az értelmét és hogy mit szerettünk volna ezzel közölni. A könyvtáram megírása során tapasztaltam hogy a legkiesebb eltérés esetén olyan parancsok melyek viszonylag könnyen értelmezhet˝oek, összekeverhet˝oek más teljesen más jelleg˝u esemény bekövetkezésével. Például ha a kéz mozgását szeretnénk parancsként tekinteni akkor ki kell sz˝urünk bármilyen más tárgyat ami nem kéz különben nem tudjuk eldönteni, hogy most mely tárgy mozgását tekintsük parancsnak ezért elég sok információt be kell gy˝ujtenünk képfeldolgozás útján ahhoz hogy egyértelm˝uen behatároljuk a kéz mozgását es ezt valamilyen parancsnak tekinthetjük. A gesztusok sokféle forrásból jöhetnek. F˝oleg a kéz illetve arc által végzett gesztusokat szoktunk tanulmányozni viszont lehet rá eset hogy például a kar vagy a láb által végzett utasításokat szeretnénk felismerni viszont ezeket teljesen másképp kell értelmeznünk. A parancsfelismerés segítségével egy teljesen újféle kommunikáció valósítható meg az ember es a számítógép között. Számos próbálkozás volt annak érdekében hogy a jelnyelvet parancsfelismerés útján értelmezni lehessen. Jelenleg a számítógéppel történ˝o kommunikáció f˝oleg az egér illetve a billenty˝uzet segítségével a különböz˝o grafikus felületeken keresztül valósítható meg, viszont a parancsfelismerés illetve hangfelismerés fejl˝odésével egy újfajta kommunikáció valósítható meg az ember es a számítógép között. Például a parancsfelismerés segítségével lehet˝oségünk az egér helyettesítésére mivel ha pontosan tudnánk követni a kéz, pontosabban egy bizonyos új mozgását ez lehet˝ové tenne az egér mozgatását egyszer˝uen az ujj mozgatásával. Attól függ˝oen hogy milyen bemeneti adatunk van a gesztusok értelmezésére különböz˝o algoritmusokat kell végeznünk. Az hogy mennyire pontosan vagyunk képesek egy parancsot értelmezni legf˝oképpen a bemeneti adat min˝osége valamint algoritmus helyességét˝ol függ. Az hogy a test es a végtagok mozgását értelmezzük ezeket különböz˝o csoportokba kell osztanunk es minden csoportot másként kell értelmeznünk. Fontos figyelembe venni az ezek közötti kapcsolatot is mivel például lehet hogy a kéz és a kar együttes mozgása írja le azt a parancsot amit nekünk értelmeznünk kell viszont általában elegend˝o ezeket külön vizsgálnunk. Rengeteg probléma merül fel a gesztusok pontos felismerésének során. Ilyen például az eszköz mellyel a bemeneti adatot megkapjuk, ez pontatlan adatokat adhat, es a kép zaj ami olyan információkat jelent ami valójában nincs jelen viszont ezek kisz˝urése problémát okozhat. A különböz˝o fényhatásokat is befolyásolhatják a parancs értelmezését mivel megtörténhet hogy a képfeldolgozás során a váltakozó fényhatások miatt másképp dolgozzuk fel a képet ami megváltoztathatja a gesztus jelentését.
1.6. Fejezet összefoglaló Ez egy általános leírás volt a különböz˝o felhasznált területekr˝ol viszont ezeknek csak bizonyos ágazatait használtam fel melyek szükségesek voltak a program funkcionalitásának biztosításához. A következ˝o fejezetben ezeknek a területek es fogalmaknak a konkrét felhasználásáról a különböz˝o technológiák se-
10
1. FEJEZET: B EVEZET O˝ gítségével fogok írni.
11
2. fejezet
¨ ´ Parancsfelismero˝ konyvt ar
2.1. Fejezet leírás Ebben a fejezetben a parancsfelismer˝o könyvtárról fogok írni aminek a teljes egészet én írtam, valamint ennek felhasználásáról amire külön megvalósítottam egy alkalmazást. Részletesen leírom a megvalósítás lépéseit, milyen akadályokba ütköztem és milyen ötleteket találtam ezek megoldására. A legtöbb munkát a könyvtár felépítésének a megvalósítása valamint a különböz˝o komponensek összehangolása okozta. A könyvtár lényege hogy olyan funkcionalitást biztosít a felhasználó alkalmazásnak mely segítségével gesztusokat lehet felismerni és ezt tetsz˝oleges módon lekezelni.
2.2. A könyvtár felépítése A könyvtárt próbáltam minél több komponensre felbontani az átláthatóság és a kiegészíthet˝oség megvalósítása érdekében. minden komponensr˝ol külön részletes leírást fogok adni viszont most leírom nagy vonalakban miért választottam ki ezeket a komponenseket. Abból indultam ki hogy bemenetként kapok egy mélységi képeket es ezeket nekem valahogy értelmeznem kell és közölnöm kell a felhasználó alkalmazással, hogy hogy a parancs amire vár az megtörtént. Az els˝o komponens melyre egyértelm˝uen szükségem volt az a kép kinyerésért felel˝os rész. Mivel én csak mélységi képeket dolgoztam fel nekem elegend˝o volt úgy megírnom ezt a komponenst hogy csak annyi funkcionalitást tegyen publikussá hogy lekérjem t˝ole ezt a képet. Az így megkapott mélységi képekb˝ol nekem viszont hasznos információkat kell kinyernem. Szerettem volna a kép feldolgozását teljesen különválasztani ennek az értelmezését˝ol ezért a következ˝o komponensnek feladata csak a kép pixelszint˝u feldolgozása. Mivel a képfeldolgozó komponens nem tud semmit arról hogy milyen parancsokat szeretnék felismerni, pontosabban hogy ezek a parancsok milyen alakzattól jönnek ezért bevezettem egy sz˝ur˝o mechanizmust. Ennek a feladata az lenne hogy csak azokat az alakzatokat tartsa meg melyekre nekem szükségem van így lényegesen leegyszer˝usítve az felismerést. A felismer˝o komponensnek lenne a feladata hogy értelmezze a parancsokat es ha egy parancs bekövetkezett akkor értesítse a feliratkozott alkalmazást err˝ol. Az utolsó komponens az alkalmazás lenne ami egy jól meghatározott módon használja fel ezt a könyvtárat. A könyvtár félépítése érdekeben figyeljük meg a következ˝o architektúra diagramot: 12
2. FEJEZET: PARANCSFELISMERO˝ KÖNYVTÁR
Ezen komponensek részletes leírását tárgyalom a következ˝o fejezetben. Minden komponenst probátam úgy megírni hogy ezek könnyen kib˝ovíthet˝oek legyenek és lecserélésük se okozzon különös gondot.
2.3. A komponensek részletes leírása 2.3.1. A képkinyer˝o komponens A funkcionalitása hogy egy bizonyos eszközt˝ol lekérje a kívánt típusú képet és ennek a képnek az információit mint például a kép szélessége, magassága és maga a mátrix ami tartalmazza a megfelel˝o pixelekhez társított információt elérhet˝ové tegye a felhasználó komponensnek. Annak érdekében hogy a komponens mely szeretne egy lekérni egy bizonyos típusú képet ne függjön az eszközt˝ol melyt˝ol kinyerem ezt, létrehoztam egy osztály melynek az lenne a feladata hogy ezt megvalósítsa így ha kiszeretném cserélni az eddig használt eszközt ez könnyen megtehet˝o. Mivel ezeket a képeket általában nagyon gyorsan egymás után kell lekérnem, célszer˝u úgy csak a megfelel˝o típusú képet lekérni hatékonyság szempontjából. Mivel nekem csak egy mélységi képre van szükségem, jó volna biztosítani hogy a többit blokkoljam. Egy másik fontos szempont amit figyelembe vettem, hogy eszközzel több különböz˝o API segítségével is tudok kommunikálni ezeket is szétválasszam es a felhasználó komponens ezekr˝ol ne tudjon es automatikusan a megfelel˝o eszközt˝ol a megfelel˝o API segítségével kérjem le. Mivel én konkrétan egy kinect eszközzel dolgoztam amivel a libfreenect2 API [2] segítségével kommunikáltam ezért az ennek megfelel˝o osztályt hoztam létre. Most vázlatosan leírom annak lépéseit mely segítségével a libfreenect2 API-t felhasználva lehet˝oség van a kinect eszközt˝ol lekérni a különböz˝o típusú képeket.
13
2. FEJEZET: PARANCSFELISMERO˝ KÖNYVTÁR – Az els˝o lépés az eszközök felismerése. Miel˝ott bármit is csinálnánk, a csatlakozott kinect eszközöket kell megtaláljuk. Ahhoz hogy a számítógéphez csatlakozott eszközöket feltudjuk ismeri az API biztosít egy libfreenect2::Freenect2 típusút. Ebb˝o az osztályból kell példányosítanunk es miel˝ott barmit is csinálnánk el˝oször ennek az osztalynak az enumerateDevices() metódusát kell meghívnunk. Ugyancsak ez az osztály teszi leht˝ové a az szériaszámanak a meghatározását a getDefaultDeviceSerialNumber() metódus használatával valamint ugyancsak ennek az osztálynak a statikus metódsai teszik lehet˝ove a különböz˝o cs˝ovezetékek lekérését (CpuPacketPipeline, DumpPacketPipeline, OpenCLPacketPipeline, OpenGLPacketPipeline). Ezek szükségesek hogy egy bizonyos ezközzel kommunikálni tudjunk. – A második lépés egy eszköz kiválasztása és ehhez egy figyel˝ot rendelni. Az eszköz kiválasztása széria szám alapján történik es egy cs˝ovezetéket kell megadnunk ha az alapértelmezett˝ol különböz˝ot szeretnénk használni. Ezt az el˝oz˝o lépésben leírt osztály openDevice() metódusával érhetjük el. Ezt különböz˝o paraméterekre hívhatjuk meg mint például egy karakterlánc ami a szériaszámnak felel meg valamint egy cs˝ovezeték. Miután ezt megtettük ha sikeres volt a kapcsolatteremtés egy Freenect2Device* típust kapunk vissza mely az általunk meghatározott eszközt jelenti. Ehhez hozzá kell rendelnünk figyel˝oket melyeknek az a szerepe hogy a különböz˝o típusú képekre várakoznak. Azt hogy ezek a figyel˝ok milyen fajtájú képre várakoznak egy egész típusú változóval tehetjük meg melyben az egyes bitek jelölik a kép típusokat. Például ha azt szeretnénk hogy az infravörös és a mélységi képre várakozzon akkor ezt a libfreenect2::Frame::Color, libfreenect2::Frame::Ir, libfreenect2::Frame::Depth statikus adattagokkal valósíthatjuk meg. Ezeket bitenkénti vagy m˝uvelettel tetsz˝olegesen kombinálhatjuk. Az eszköznek a setColorFrameListener vagy a setIrAndDepthFrameListener metódusa segítségével állíthatunk be a figyel˝oket. – A harmadik lépés az elköz elindítása es a képek fogadása. Miután elindítottuk aztán mar nincs lehet˝oség a konfigurációs paraméterek módosítására. Ugyan a figyel˝oknél már bekellet állítanunk a különböz˝o képtípusokat amire várakozzanak ismét meg kell adnunk mivel egy eszközhöz több figyel˝o is hozzárendelhet˝o. Ha minden típusú képre szükségünk van akkor egyszer˝uen az lekért eszközre kapott objektum start() metódusát hívhatjuk meg. Ha viszont nincs szükségünk minden képre hatékonyság szempontjából mindenképp érdemes a startStreams() metódust használni mely vár két logikai típusú paramétert mellyel azt állíthatjuk be hogy milyen szenzorokat aktiváljunk az eszközön. A képek fogadását a figyel˝o waitForNewFrame() metódusa teszi lehet˝ové mely egy frmémeket tartalmaz˝o tömböt és egy milliszekundumban meghatározott id˝ot vár. A figyel˝o addig várakozik a megadott frémekre amíg az id˝o amit megadtunk lejár. A frémeket tartalmazó tömbb˝ol letudjuk kérdezni a különböz˝o képtípusokat. Három ilyen típus van: színes kép mely 1920x1080as BGRX vagy RGBX, infravörös mely 512x424 lebeg˝opontos típus es értékeit a [0.0,65535.0] intervallumból veszi valamint mélységi kép mely ugyancsak 512x424 lebeg˝opontos típus és a távolságot milliméterben adja vissza. – Miután már nincs szükségünk több képre az eszközt meg kell állítanunk valamint le kell zárnunk
14
2. FEJEZET: PARANCSFELISMERO˝ KÖNYVTÁR amint az eszközre mutató objektumunk stop() illetve close() metódusával tehetjük meg.
2.3.2. A képfeldolgozó komponens A második komponens a kép feldolgozásáról szól [3]. Ezt a komponenst úgy írtam meg hogy esetleges újabb képfeldolgozók ezt kitudják egészíteni. Ennek érdekében létrehoztam egy olyan osztályt mely egy tárgyról eltárol különböz˝o információkat. A képfeldolgozás végén egy egy listát térítek vissza amely ennek az osztálynak az objektumait tartalmazza. Tehát ha egy új képfeldogozó osztályt definiálok akkor lehet˝oség adódik arra hogy több ilyen osztály is feldolgozza ugyanazt a mélységi képet, vagy akár különböz˝o osztályok feldolgozhatnának más típusú képeket a jobb átláthatóság érdekében, csak annyi lenne a teend˝o hogy minden osztály kiegészíteni a tárgyakról eltárolt információt es ezen m˝uveletek végén kapott tárgyakról felépített lista továbbító a fels˝obb komponensekhez. Én egyetlen osztály írtam mellyel a kontúrokat tanulmányozom és ez alapján tárolok el információkat. Nagyon fontos hogy a tárgyakról eltárolt információ pontos legyen es minél részletesebb hogy a fels˝obb komponensek használható következtetéseket tudjanak levonni. Itt még nem foglalkozom azzal hogy milyen tárgyat akarok felismerni csupán tárgyakról általános információkat tárolok el. Majd a következ˝o komponensek fogják eldönteni hogy mit kezdenek ezzel az információval. Ez azért is jó mivel ha több tárgyat szeretnék felismerni akkor ebben a komponensben nem kell módosításokat végeznem. A képkinyer˝o komponenst˝ol csupán egy mutatót kapok arra a memóriaterületre ahol a kép elvan tárolva valamint, a kép szélességét és hosszúságát valamint arra is szükségem van hogy egy bizonyos pont a képben hány byte-on van eltárolva. Én a mélységi képpel dolgoztam mivel ebb˝ol tudtam a legtöbb információt kinyerni a parancsok felismeréséhez. Ez csak annyiban különbözik egy szürkeárnyalatos képt˝ol hogy itt a pixelek nem a szín intenzitását hanem azt reprezentáljak hogy minden egyes pixel milyen távolságra helyezkedik el a szenzortól. A mélységi kép megértése érdekében tekintsük a következ˝o képet:
15
2. FEJEZET: PARANCSFELISMERO˝ KÖNYVTÁR Ebben a képben minél sötétebb a pixel annál távolabb helyezkedik el a szenzortól, valamint minél világosabb annál inkább közelebb. Ezt a megszerzett képet OpenCV függvénykönyvtár segítségével dolgozom fel, viszont a függvények amikre szükségem van nem m˝uködnek mélységi képre ezért egy els˝odleges átalakításokra van szükség. Több metódussal próbálkoztam ezt átalakítani mivel a megszokott módszerek nem váltak be. Az els˝o metódus amivel próbálkoztam az egyszer˝uen átalakítani miden egyes pixelt a [0,255] intervallumba. Ezt a következ˝o egyszer˝u képlettel valósítottam meg: tp = [p/maxT a ´vols´ ag ∗ 255] Ahol p a pont amit áttranszformálok, tp a transzformált pont maxTávolság a pontok közül a legtávolabbi a szenzortól. Azért szorzom 255-el mivel a p/maxTávolság egy [0,1] közötti számot adna viszont nekem a [0,255] intervallumból kellenek a számok és mivel egész számok kellenek veszem a kifejezés egész részét. Ez a metódus adná valószín˝uleg a legjobb eredmény ha a mélységi kép pontos lenne, viszont mivel nem teljesen pontos ez a metódus nem m˝uködött a meghatározott kontúrok teljesen használhatatlanok voltak. Egy másik metódus mellyel próbálkoztam az küszöbértékek meghatározása majd minden egyes képpont ami e küszöbérték alá esik ahhoz 0 értéket társítottam es minden ami e fölött van 255-öt. Erre a következ˝o képletet tekinthetjük: 0 tp = 255
p < t´ avols´ agHat´ ar k¨ ul¨ onben
Ahol a maxTávolság a küszöbértéknek felelne meg. Ennek helyes megválasztásával és a figyelt tárgy helyes elhelyezkedésével bizonyos helyzetekben képes voltam helyes információkat kinyerni viszont nagyon inkonzisztens volt az eredmény. Ez az inkonzisztencia abból fakadt hogy a megfigyelt tárgyak határain a mélységi kép pontatlan volt. Ezt a pontatlanságot próbáltam ellensúlyozni egy fejlettebb küszöbérték mechanizmussal melyben intervallumonként választottam meg a küszöbértékeket. Ez a metódus adta a legjobb eredményt. Ennek az a hátránya hogy a tárgyat csak egy bizonyos mélységi intervallumban tudom felismerni de ez elegend˝o. Az átalakítás után meghatározom a kontúrokat. Hogy ezeket a kontúrokat tudjuk csoportosítani. Egy hierarchiát építhetünk fel melyben lehet˝oség van a szomszédos kontúrok, a gyerek és szül˝okontúrok beazonosítása. A kontúr meghatározására többféle módozat lehetséges melyek f˝oként ennek a hierarchiának a felépítését befolyásolják. Lehet˝oség van hogy hierarchia nélkül építsük fel, hogy meghatározzuk csak a küls˝o kontúrokat, ekkor a szül˝o és gyerek nem lesz beállítva, vagy egy teljes hierarchia felépítésére is. Ha nem szeretnénk minden egyes pontot eltárolni akkor többféle metódus létezik ennek befolyásolására. Például ha a kontúrok egy négyzetet alkotnak akkor elegend˝o négy pontot eltárolnunk es a köztes függ˝oleges illetve vízszintes pontokat nem kell eltárolnunk, viszont lehet˝oség van arra is hogy minden egyes pontot eltároljunk.
16
2. FEJEZET: PARANCSFELISMERO˝ KÖNYVTÁR A kontúrpontok segítségével megtudom határozni a tárgy néhány alakjára vonatkozó tulajdonságát. Ezek a következ˝oek: a kontúr középpontja, területe, konvex hálójának a területe, a konvex háló pontjai valamint a középpont közötti távolságokat, valamint a konvex hibákat. A középpont meghatározására a momentumokat használtam. A térbeli momentumok meghatározására a következ˝o képletet alkalmazhatjuk: mi,j =
X
c(x, y) ∗ xj ∗ y i
x,y
Majd ezekb˝ol a momentumokból a középpontot a következ˝o képletek segítségével határozhatjuk meg: k¨ ozeppontx =
m1,0 m0,0
k¨ ozepponty =
m0,1 m0,0
A konvex hibák megértése érdekében figyeljük meg az alábbi képet. Ezen egy kéz kontúrját, konvex hálójának kontúrját valamint a konvex hibákat figyelhetjük meg.
Ezek az információk elegend˝oek ahhoz hogy néhány tárgyat egyértelm˝uen betudjak azonosítani.
17
2. FEJEZET: PARANCSFELISMERO˝ KÖNYVTÁR
2.3.3. A szur˝ ˝ o komponens Itt a képfeldolgozás által felhalmozott információkból próbálom kisz˝urni az általam meghatározott tárgyat. Mivel nekem kéz parancsok felismerésére van szükségem ezért a kezet sz˝uröm ki. Úgy írtam meg ezt a komponenst hogy ha egy új tárgyat szeretnék sz˝urni akkor ezt egyszer˝uen egy új osztály hozzáadásával teszem lehet˝ové és a többi komponens változatlan marad. Meglep˝oen sok minden figyelembe kell venni ahhoz hogy a képfeldolgozás során felépített tárgyakból egyértelm˝uen beazonosítani tudjak. A kezdeti elgondolásom az volt hogy elegend˝o a kontúr terület es a konvex háló területének az arányát vennem. Azért fontos az arányát vennem és nem csupán az értékeit hogy ez általános legyen, mivel felépített kéz mérete függ attól hogy ez milyen távolságra helyezkedik el a szenzortól. Ez az arány viszont nagyon sok tárgy esetében megegyezik ezért újabb feltételeket kellett szabjak. Az egyik ilyen feltétel a konvex halópontok es a középpont közötti távolság. A kéz esetén megfigyelhetjük hogy a konvex hálónak a pontja nagyjából egyenl˝o távolságra helyezkednek el a középponttól. Ez már kevesebb tárgyra igaz. Ezzel tovább sikerült sz˝ukítenem a tárgyak listáját viszont meg mindig volt hiba. A végs˝o feltétel amit tennem kellett hogy csak a kezet ismerjem fel és ezt ne tévesszem össze könnyen semmivel konvex hibák es a középpont közötti távolságot. Ez a feltétel elegend˝o volt ahhoz hogy csak a kéz legyen felismerve és semmi hozzá hasonló tulajdonságokkal rendelkez˝o tárgy. Ugyancsak a sz˝ur˝o komponenshez tartoznak a követ˝ok. Ezt egy speciális sz˝ur˝onek is tekinthetjük. Ennek a bevezetése azért kellett mivel miután sikerült felismernem a kezet akkor ennek a mozgását szerettem volna követni viszont ha ennek megváltoztatom az alakját a már megírt kéz sz˝ur˝o nem képes felismerni. Ezért az ötlet az hogy miután beazonosítottam egy kezet a kéz sz˝ur˝o osztályban akkor utána átváltok a követ˝ore és ameddig ez képes követni a kéz sz˝urést helyettesítem a követ˝ovel. Ha a követ˝o elvesztette a kezet(esetleg a kéz elhagyta a szenzor hatáskörét) akkor visszaváltok automatikusan a kézfelismer˝ore így a fels˝obb komponensnek nem kell tudni semmiféle követésr˝ol egyszer˝ubbé téve a kódot. Az egyszer˝uség kedvéért csak egyetlen kezet sz˝urök ki. Viszont megoldható hogy egy listát térítek vissza az összes felismert kézzel viszont ez elbonyolítana a követés mechanizmust. Azt is ellen˝orzöm ha több kezet ismerek fel es ekkor a komponens úgy viselkedik mintha nem ismert volna fel semmit annak érdekében hogy ne legyen kavarodás hogy mely kezet ismertem fel.
2.3.4. Az értelmez˝o komponens Ennek a komponensnek a feladata hogy felismerje a parancsokat és sikeres felismerés esetén ezt jelezze az alkalmazásnak. A felépítése hasonlít a sz˝ur˝okéhez viszont itt egy tárgy felismerése helyett parancsokat ismerek fel. Ezt is úgy írtam meg hogy könnyen kiegészíthet˝o legyen más parancsok felismerésével, ez csak egy új osztály hozzáadását jelentené. Én két parancsot implementáltam. Az egyik a mozgás felismerés amit ugyancsak parancsnak tekintek a konzisztencia érdekében, valamint a kéz összehúzódását ökölbe és a kinyújtását. A mozgás felismerése egyszer˝u, csak azt kell ellen˝oriznem hogy mennyit változott az el˝oz˝o kéz helyzete a mostanival. Ezt a kéz középpontjának helyzete segítségével határozom meg. Négy mozgásirány 18
2. FEJEZET: PARANCSFELISMERO˝ KÖNYVTÁR különítettem el: le, fel, jobbra és balra. Az applikációt csak akkor értesítem ha ez meghaladt egy bizonyos küszöbértéket mivel egy nagyon kis változás szinte mindig van és nincs értelme mindig jeleznem az alkalmazásnak. A másik parancs amit feltudok ismerni az a kéz összehúzása valamint ennek kinyújtása. Ezt a kontúr és a konvex háló arányával határozom meg. Ha ez az érték nagyobb mint egy küszöbérték akkor úgy tekintem hogy kéz kinyújtás történt, ha kisebb akkor összehúzás. Viszont természetesen nem elegend˝o csupán az arányt vizsgálni különben minden alkalommal kellene jeleznem az alkalmazásnak amikor a kéz valamely állapotba van. Azt csináltam hogy eltároltam a legutolsó állapotot és csak akkor jelzek az alkalmazásnak hogyha ez különböz˝o az elmentett állapottól minden alkalommal frissítve ezt. Itt csak arra kell figyelnem hogy a küszöbértékek pontosan be legyenek állítva mivel megfigyeltem hogy a kéz és a kamera által bezárt szög is befolyásolja ezt az értéket. Például a szenzor jobb oldalán ugyanazon mozgás esetén ez a kéz kinyújtott állapotában ez az érték kisebb mint mint a bal oldalon. Úgy kell megválasztanom ezeket az értékeket hogy m˝uködjön bármilyen pozícióban, ezt sok teszteléssel valósítható meg. Ahhoz hogy egy alkalmazás több értelmez˝ot is tudjon használni felhasználva az összetétel tervezési mintát egy speciális értelmez˝ot hoztam létre amely ugyancsak értelmez˝o az egységes kezelés megvalósítása érdekében. Ez tartalmazhat bármennyi értelmez˝ot. Mikor egy ilyen értelmez˝ot használ az alkalmazás az összes ehhez társított felismer˝o aktiválva lesz, erre adok példát amikor külön írok az felhasználó alkalmazásról. Ugyancsak ehhez a komponenshez társítottam azokat az interfészeket amelyeket a felhasználó alkalmazásnak implementálnia kell ahhoz hogy kapcsolatot tudjak vele teremteni. Minden egyes értelmez˝ohöz társítottam egy ilyen interfészt. És végül szükségem van egy olyan osztályra is mely megteremti a komponensek közötti kapcsolatot. A lényeg hogy ez teljesen generikus, nem függ semmilyen konkrét értelmez˝ot˝ol, sz˝ur˝ot˝ol, alkalmazástól vagy képfeldolgozótól, ezeknek a beállításáért a felhasználó alkalmazás felel˝os. Itt indítom el az egész folyamatot, valamint lehet˝oséget adok ennek a folyamatnak a leállítására is.
2.3.5. Az felhasználó alkalmazás komponens Általánosan hogyan lehetne használni ezt a könyvtárat egy alkalmazásban a következ˝o kódrészlet szemlélteti: 1
// The class using the library class CompositeTestApp : ConcreteRecognizer1App, ConcreteRecognizer2App { ...
6
GenericCommandRecognizer* genericCommandRecognizer; ... // pure virtual methods in the base class void concreteCommand1Recognized(); void concreteCommand2Recognized();
11
} 16
// Initializeing and starting the recognizer CompositeRecognizer* compositeRecognizer = new CompositeRecognizer();
19
2. FEJEZET: PARANCSFELISMERO˝ KÖNYVTÁR
compositeRecognizer->addRecognizer(new HandGrabRecognizer(this)); compositeRecognizer->addRecognizer(new HandMovementRecognizer(this)); 21
26
genericCommandRecognizer = new GenericCommandRecognizer( new ContourImageProcessor(), new HandFilter(), compositeRecognizer ); // starting the recognition genericCommandRecognizer->startRecognition();
31
...
36
// Handling the different commands void CompositeTestApp::concreteCommand1Recognized() { // handle concreteCommand1 } void CompositeTestApp::concreteCommand2Recognized() { // handle concreteCommand }
Az els˝o lépés implementálni azon interfészeket amilyen típusú parancsok felismerését szeretném használni. Ez azért szükséges mivel az értelmezés során nekem tudnom kell milyen metódusokat kell meghívnom. A f˝o osztály amire szükség van az a GenericCommandRecognizer osztály ami lehet˝ové teszi a komponensek tetsz˝oleges beállítását, az értelmezés elindítását vagy leállítását vagy a folyamat állapotának lekérdezésére. Feltétlenül implementálni kell néhány tiszta virtuális metódust melyek az interfészhez tartoznak. Ezek a metódusok fognak meghívódna egy parancs bekövetkezte esetén. Egy fontos megjegyzés hogy a komponensek amiket társítok a GenericCommandRecognizer-hez automatikusan fel lesznek szabadítva. Ezek applikációban történ˝o felszabadítása helytelen viselkedést eredményezhet. Az parancsok felismerése egy külön szálon fut ami startRecognition() metódushívás eredményeként lesz végrehajtva. Ez visszatéríti a létrehozott szálat annak érdekében ha az alkalmazás szeretné külön befolyásolni ennek m˝uködését, viszont erre viszonylag ritkán lehet szükség. Az alkalmazás helyes m˝uködése érdekében szükség lehet szinkronizáció megvalósítására, ez teljes egészében az felhasználó alkalmazás feladata.
2.4. A könyvtarra épül˝o alkalmazás Ahhoz hogy bemutassam mire is lehetne felhasználni ezt a könyvtárat egy olyan alkalmazást írtam mely egy megjelenített alakzat forgatására es eltolására képes. A felületet a Qt keretrendszer segítségével hoztam létre. Az alakzatot OpenGL segítségével jelenítettem meg, a keretrendszer segítségével ez egyszer˝uen megvalósítható. A felület lehet˝ové teszi az alakzat transzformációját kontrollok segítségével is de a lényeg hogy ez lehetséges kézi parancsokkal is. Mivel a parancsok nem teljesen pontosak és néha az elvárttól eltér˝o viselkedést produkálnak ezért információkat is megjelenítek hogy egyszer˝ubb legyen követni hogy mi volt értelmezve. Mivel nekem több parancsot kell felismernem, a mozgásokat és a kéz összehúzását valamint kinyújtását ezért a megfelel˝o interfészeket implementálom. Hat esemény felismerését tudom lekezelni, ezek a következ˝ok: kéz felfele, lefele, balra illetve jobbra való mozgatása es a kéz összehúzódása es kinyújtása. Ebb˝ol kell nekem felépítenem a forgatást és az eltolást. Mivel csak két m˝uveletet kell megvalósítanom ezért azt találtam ki hogy a kéz teljes összehúzódása 20
2. FEJEZET: PARANCSFELISMERO˝ KÖNYVTÁR es kinyújtása jelentse a m˝uveletek közötti váltakozást. Mivel a mozgatásban is felhasználom ezeket azért hogy ne történjen véletlenszer˝u m˝uveletváltás, a kéz kinyújtása csak akkor fogja ezt váltást generálni ha a két m˝uvelet között nem történt egy küszöbértékt˝ol több mozgás parancs. Ezzel a metódussal tudom felhasználni ezt a két parancsot a transzformációhoz is ez az ezek közti váltáshoz is. A mozgások felelnek meg a transzformációnak, a kéz lefele való mozgatása jelenti a lefele való eltolást vagy az x tengely körüli óramutató járásával megegyez˝o irányú forgatást vagy a a kéz jobbra mozgatása jelenti a jobbra való eltolást es hasonló módon az y tengely körüli óramutató járásával megegyez˝o irányú forgatást attól függ˝oen hogy milyen módban vagyok. Hasonlóan történik a balra es felfele történ˝o mozgások lekezelést. A mozgást csak akkor fogom lekezelni hogyha mozgatási módban vagyok. Ez akkor aktiválódik ha a kezem összehúzott állapotban van, miután a kezem kinyújtom letiltom a mozgás lekezelését. Ez olyan hatást kelt mintha megfognám az alakzatot eltolnám vagy forgatnám aztán elengedném. Az alkalmazás szinkronizációját is megkellet oldanom. El˝oször is a két értelmez˝o ugyanazon a szálon fut de arra is lehet˝oség van hogy külön szálon futtassam ezeket viszont ekkor a szinkronizáció bonyolultabbá válik. Miután egy parancs végrehajtódik ennek az applikációban való lekezelését már nem az a szál fogja végezni amely a parancsokat is értelmezi hanem átadom a vezérlest a felületnek így a parancsok felismerése folytatódhat tovább a parancs kezelésével egyidej˝uleg. Mivel csak egy szálon értelmez˝odnek a parancsok ezért a konkurencia csak abból adódhat ha kiadok egy parancsot a f˝o szálon, lekezelem ezt a parancsot és aztán érkezik egy újabb parancs viszont az el˝oz˝o parancs lekezelése nem fejez˝odött be. A keretrendszer segítségével ez könnyen megvalósítható mivel a parancsfelismer˝o szálat a felületért felel˝os szálon hoztam létre így ha a felületen frissítés történik, biztos hogy ez a szál nem fog konkurencia problémát okozni.
2.5. A könyvtár korlátai Jelenleg a könyvtár csak kevés funkcionalitást biztosít viszont ezek elegend˝oen ahhoz hogy egy egyszer˝u alkalmazásban fel lehessen használni. Most csak felszeretném sorolni a legfontosabbakat viszont egy másik fejezetben fogok írni arról hogy ezekre a korlátokra milyen megoldások lehetségesek. – Mivel én kinecttel dolgozom és ezen belül a libfreenect2 segítségével kommunikálok más eszközt nem kezeltem le, csak ett˝ol az eszközt˝ol ezzel az API segítségével lehet lekérni a különböz˝o típusú képeket. – Csak kéz felismerés lehetséges más tárgyat nem tudok felismerni. – A tárgyakról felépített lista csak néhány információt tartalmaz es ezeket is úgy építettem fel hogy a kezet tudjam felismerni. Más tárgyak esetén több információra lehet szükség. – Sz˝urés esetén nem biztosítom hogy több tárgyat is lessen egyszerre sz˝urni ez csak akkor m˝uködik ha egyetlen olyan tárgy van a képen amit szeretnék kisz˝urni.
21
2. FEJEZET: PARANCSFELISMERO˝ KÖNYVTÁR – Csak két egyesz˝u parancs felismerése lehetséges és ezek a parancsok is sokszor pontatlanok viszont ezt nagyban befolyásolja a mélységi kép pontatlansága. – A felismert tárgynak a szenzortól egy bizonyos távolságra kell elhelyezkednie és csak meghatározott korlátok között mozoghat hogy a parancsfelismerés sikeres legyen.
2.6. Fejezet összefoglaló A könyvtár megírásával az volt a célom hogy egy általános mechanizmust biztosítsak annak érdekében hogy parancsokat lehessen felismerni és ezt könnyen fellehessen használni alkalmazásokban. A f˝o komponenseket szerettem volna megírni és magát az alapm˝uködést. Még rengeteg részlet van amiket meg kell írni viszont maga a felépítés viszonylag teljes.
22
3. fejezet
´ technologi ´ ak ´ Felhasznalt
3.1. Fejezet leírás Ebben a fejezetben azon technológiaiakról szeretnék írni melyeket felhasználtam a parancsfelismer˝o könyvtár, valamint ennek a könyvtárnak a felhasználásával készült kézi parancsokkal végzett transzformációkat (eltolás és forgatás) megvalósító alkalmazásnak. Ezekb˝ol a legfontosabbak az OpenCV, OpenGL es libfreenect viszont másakat is megemlítek melyek szükségesek voltak például a könyvtár automatikus kigenerálása, valamint a program megírásának megkönnyítését szolgálják.
3.2. C++ 3.3. QtCreator 3.4. Qmake 3.5. A kinect ezköz 3.6. Libfreenect 3.7. OpenCV 3.8. OpenGL 3.9. QtFramework 3.10. Git 3.11. Fejezet összefoglaló Következ˝o két fejezetben arról szeretnék írni, hogy ezeket a különböz˝o technológiákat hogyan használtam fel a parancsfelismer˝o könyvtár es az alkalmazás megírásában. 23
4. fejezet
´ ´ egek ´ A program meg´ırasakor felmerul ¨ o˝ nehezs
4.1. Fejezet leírás A program megírása során sok nehézséggel és kihívással szembesültem, úgy a könyvtár mint az alkalmazás megvalósításában. Sokszor a funkcionalitásokat kellet korlátolnom egy nehézség felmerülésekor. Ezek több forrásból származtak, ezek közül a legfontosabbakat szeretném megemlíteni.
4.2. C++ Itt csak annyit szeretnék megemlíteni hogy C++ esetén azt tapasztaltam nehézségnek hogy a hibák sok forrásból származhatnak melyek beazonosítsa sok munkát igényel. Az olyan hibák beazonosítása okozott gondot melyben az alkalmazás néha helyesen m˝uködött viszont bizonyos helyzetekben valamilyen hiba történt mely okáról semmiféle információm nem volt. Ennek egyik oka a memóriaterületek helytelen felszabadítása. Mivel interfészekkel dolgoztam legtöbb esetben dinamikusan kellet memóriaterületet foglalnom, és ezek felszabadításáért nem mindig azok a komponensek a felel˝osek melyekben ezeket megvalósítottam. Például az alkalmazás komponens felel˝os azért hogy létrehozza a sz˝ur˝oket és értelmez˝oket viszont ezek felszabadításáért az értelmez˝o komponens felel˝os. Ezekre helyesen kell kezelnünk ahhoz hogy az alkalmazás az elvárt funkcionalitást biztosítsa.
4.3. A képfeldolgozás Ahhoz hogy egy pixel információkból használható információkat nyerjünk ki az nem könny˝u feladat. Csak egy mélységi képet használtam és ezt dolgoztam fel különböz˝o metódusokkal hogy elérjem a kívánt eredményt. Ahhoz hogy ilyen limitált mennyiség˝u információból parancsfelismeréshez érjünk el alapos tervezésre van szükség. Ilyen például mélységi kép pontatlansága, az eredmények tesztelése valamint a sok tárgy megkülönböztetése. Az egyik nehézség a mélységi kép pontatlansága. Ebb˝ol adódóan sokkal több alakzatot nyerünk ki a képfeldolgozás során mint amire számítanánk és ezeket ki kell sz˝urni. Én a kinekt eszközt használtam, ez bizonyos helyzetekben pontos viszont van néhány pontatlanság amire megoldást kell találunk. Ilyen például hogy a felismert alakzatok határainál bizonyos okok miatt a mélységet nullának érzékeli. Ezt ha nem vesszük figyelembe a kontúrok meghatározása során nem várt eredményeket kapunk. 24
4. FEJEZET: A PROGRAM MEGÍRÁSAKOR FELMERÜL O˝ NEHÉZSÉGEK Mivel rengetek felismert alakzatunk van ezért nagyon specifikus megszorítások kell tennünk annak érdekében hogy a tárgyat amit felszeretnénk ismerni ne keverjük össze semmivel. A tárgyról viszont csak egy korlátozott mennyiség˝u információnk van. Mivel egyetlen hiba esetén az elvárttól teljesen más eredményeket kapnánk amit csak úgy tudunk kiküszöbölni ha teljesen pontos a felismerés. Egy másik nehézség abban is rejlik hogy az eredményeket nem könny˝u tesztelni, hogy következtetéseket tudjak levonni hogy helyes eredményeket kaptam ezt muszáj valahogyan vizuálisan megjelenítsek. Kezdetben konzol kiírással próbálkoztam viszont rájöttem, hogy ez nem megoldás. Sok egymásutáni m˝uveletet el kell végezni a képen ahhoz hogy információt nyerjünk ki bel˝ole viszont ha egyetlen m˝uvelet pontatlan ez teljesen rossz eredményhez vezet aminek a beazonosítása nem mindég egyszer˝u.
4.4. A könyvtár megtervezése Hogy eljussunk addig hogy egy parancsot felismerjünk és err˝ol értesítsük az alkalmazást több folyat szükséges melyek helyes szétválasztása elengedhetetlen ahhoz hogy egy átlátható és m˝uköd˝o alkalmazást valósítsunk meg. Ahhoz hogy helyesen tervezzük meg a komponenseket szükség van arra el˝orelássuk az esetleges felmerül˝o problémákat. Véleményem szerint a könyvtár alapfelépítésének a megtervezése volt az egyik legfontosabb feladat mivel ez kihat a teljes fejlesztési folyamatra. Ha helytelenül tervezzük az alkalmazást kezdetben akkor ennek kijavítása vagy nagyon sok munkát igény vagy egyáltalán nem lehetséges. Ezt figyelembe véve nagy hangsúlyt fektettem arra hogy úgy tervezzem meg ezt a könyvtárat hogy figyelembe vettem a legfontosabb problémákat melyek felmerülhetnek, ilyen például a komponensek kiegészítése vagy a komponensek lecserélése. Így például ha egy új tárgyat szeretnénk felismerni ennek megvalósítása csak néhány új osztály megírását igényli.
4.5. A könyvtár általánossága Az hogy egy olyan könyvtárat írjak mely lehet˝oséget ad tetsz˝oleges tárgy tetsz˝oleges parancsának a felismerésére nem volt könny˝u feladat. Nekem csak kéz felismerésre volt szükségem viszont szerettem volna bármilyen tárgy felismerése lehetséges lenne. Ezért úgy írtam meg a komponenseket hogy ezek általános tárgy felismerését valósítsák meg. A parancsfelismerés során is nekem elegend˝o volt két parancsot felismernek az alkalmazás funkcionalitásának a biztosításra viszont lehet˝oség van általános parancsok felismerésére. Az alkalmazásnak sem kell semmiféle feltételt teljesítsen ahhoz hogy felhasználja ezt a könyvtárat, tetsz˝oleges alkalmazásban felhasználható.
4.6. Fejezet összefoglaló A felsorolt nehézségeket próbáltam úgy megoldani hogy az eltervezett funkcionalitásokat meg˝orizzem. Bizonyos funkcionalitások kivétele nélkülözhetetlen volt mint például az egyidej˝uleg több különböz˝o tárgyak kisz˝urése melyek megvalósítása nem csak a sz˝ur˝o hanem a felismer˝o komponenst is túl bonyolulttá tették volna. A nehézségek ellenére úgy érzem hogy a f˝obb funkcionalitásokat sikerült biztosítanom. 25
5. fejezet
´ ´ lehetos ˝ egei ´ A program tovabbfejleszt esi
5.1. Fejezet leírás Ebben a fejezetben arról fogok írni hogyan lehetne kib˝ovíteni a könyvtárt a következ˝o szempontokat figyelembe véve: – Más parancsokat is felismerjen – A képfeldolgozó komponens lecserélés, vagy több képfeldolgozó komponens együttes használatára egy lehet˝oség – Néhány új funkcionalitás megvalósítása.
5.2. Kib˝ovíthet˝oség A könyvtár kib˝ovíthet˝osége alatt f˝oleg azt értem hogy ez kiegészíthet˝o viszonylag egyszer˝uen újjabb parancsok felismerésével. Ahhoz hogy ezt megvalósítsam az alábbi dolgokat kellett megoldanom: – A képfeldolgozás során olyan információkat kellett eltárolnom a tárgyról melyek nem tárgy specifikusak. Nekem kézfelismerésre volt szükségem es ezért el˝otérbe helyeztem azt hogy ennek a felismeréséhez szükséges információkat tároljam el, viszont ezeket próbáltam általánosan megoldani. Az információk amiket kinyerek általános tárgyakra jellemz˝oek és nem csupán a kézre. – A tárgyak sz˝uréséért felel˝os komponens esetén arra kellett figyelnem hogy könnyedén tudjam megvalósítani új tárgyak sz˝urését. Ez egyszer˝uen egy új osztály hozzáadásával lehetséges mely implementálja a megfelel˝o interfészt. – A parancsfelismerésnél hasonló a helyzet viszont egy kicsit komplikáltabb mivel lehet˝oséget kell adom több felismer˝o egységes kezelésére. Ezt viszonylag egyszer˝uen megoldottam a összetétel tervezési mintát használva melyet részletesen leírtam mikor ezt a komponenst tárgyaltam. Összefoglalva ezeket a problémákat megoldva egy új parancs hozzáadása a könyvtárhoz a következ˝o lépéseket igényelné: – Egy sz˝ur˝o osztály megírása meg egy tetsz˝oleges tárgy sz˝uréséért felel˝os. 26
˝ 5. FEJEZET: A PROGRAM TOVÁBBFEJLESZTÉSI LEHET OSÉGEI
– Abban az esetben ha a képfeldogozás során szerzett információk nem elegend˝oek erre szükség van ennek a kib˝ovítésére is, ami ugyancsak megvalósítható habár ennek megvalósítása további képfeldolgozó algoritmuska lehet szükség. – Egy felismer˝o osztály létrehozására mely az illet˝o tárgy által végzett parancsot felismerését tenné lehet˝ové. Ezekkel a lépésekkel az egy parancs felismerése lehet˝ové válna a felhasználó alkalmazásokban.
5.3. Komponensek lecserélése Ezt f˝oleg a képfeldolgozó komponens lecserélésére értem viszont elképzelhet˝o a többi lecserélése is. A jelenlegi képfeldolgozásom viszonylag korlátolt. Csak alakra vonatkozó információkat dolgozok fel ami bizonyos esetekben lehet hogy nem elégséges. Viszont én ezekb˝ol az információkból általam létrehozott objektumokat építek fel és a továbbiakban ezekkel dolgozom. Ezért ha nekem nem elegend˝oek csupán ezek az információk egy új képfeldolgozó mechanizmus segítségével hasonló objektumokat felépítve a további komponensek változatlanok maradnának. Az is elképzelhet˝o hogy a lecserélés helyett több típusú értelmez˝o együttesen építse fel ezeket az objektumokat viszont ezzel van néhány probléma amit a következ˝o alfejezetben tárgyalok.
5.4. Néhány fejlettebb funkcionalitás megvalósítása 5.5. Fejezet összefoglaló
27
6. fejezet
¨ Osszefoglal o´
28
´ Irodalomjegyzek [1] Acharya, T. és Ray, A. K. Image processing - principles and applications. Technical report, Wiley InterScience, 2006. URL https://books.google.ro/books?id=smBw4-xvfrIC& lpg=PP1&dq=image+processing+ajoy+ray&pg=PP1&redir_esc=y#v=onepage& q&f=false. [2] community, O. libfreenect2: Api reference. Technical report, Openkinect, 2016. URL https: //openkinect.github.io. [3] documentation, O. . Structural analysis and shape descriptors. Technical report, OpenCV, 2016. URL http://docs.opencv.org/. [4] Gavves, E. A brief history of computer vision. Technical report, University of Amsterdam, 2014. URL http://www.egavves.com/. [5] Gonzalez, R. R. W. Digital image processing. Technical report, Upper Saddle River, New Jersey: Pearson Education, Inc, 2002. URL http://www.imageprocessingplace.com/. [6] R. Fisher, A. W., S. Perkins és Wolfart, E. Sobel edge detector. Technical report, University of Edinburgh, 2003. URL http://homepages.inf.ed.ac.uk/. [7] Simulink, M. . Image types. mathworks.com/.
Technical report, MathWorks, 2016.
29
URL http://www.