2024. április 25., csütörtök

Gyorskeresés

[SVS_17] Október 21-24.

Írta: | Kulcsszavak: SRV . surveyor . SVS

[ ÚJ BEJEGYZÉS ]

Október 21., még 49 nap

Hétfőn sikeresen félreértettem a konzulensemet. Nem azt mondta, hogy csináljam meg jobbra, majd balra a 3D-s ponthalmazt, majd abból szűrjek, hanem azt, hogy fogjam a két disparity mapot és abból szűrjek, majd a bal oldali képre csináljam meg a 3D-s ponthalmazt.

A jobb kép 3D-s ponthalmazával az a baj, hogy gyakorlatilag nem nyertem semmit azzal, hogy ki lett számolva. Látszódik persze minden ami kell, de nincs kapcsolat a bal és a jobb halmaz Z értékei között (ami a távolság), nem lehet felhasználni szűrésre. Ha mégis kézzel belövöm a szűrést, akkor bármilyen változtatásnál újra ki kéne kézzel számolni mindent és újra belőni.

Az a terv, hogy "megengedő" BM-t eresztek rá a jobb és a bal képre, majd a nem egyező disparity értékeket törlöm, így a fals adatok kiszóródnak.

Először is tartok egy kis oktatást :K.

Miért is csinálom ezt.

Ugye mi is így látunk, hogy a két szemből érkező képekből az agyunk rakja össze a 3D-t. Ha közelebb rakjuk az ujjunk a szemünkhöz és pislogunk felváltva, akkor látjuk, hogy jobban "mozog" az ujjunk két pislantás között, míg ha távol van, kevésbé. Magyarán minél nagyobb az elmozdulás, annál közelebb van a tárgy.

Erre van hát szükségem a feladat megoldására, két képen szereplő azonos pontok elmozdulásértékeire.

Két lehetőségem van:
Ritka illesztés: Azt jelenti, hogy a két képen meghatározok jellegzetes pontokat, ilyenek a sarkok. Veszek egy sarkot a bal oldalon, aztán megkeresem a párját a jobb oldalon, veszem a következő balt és így tovább. Ebből lesz egy elmozdulástérképem (disparity map), amivel tudok 3D-t kreálni.
Előnye, hogy gyors, hátránya, hogy nem lesz olyan részletes a térkép.
Sűrű illesztés: Veszem a két képet, "egy szintbe hozom (rektifikálom)", aztán soronként keresem meg a párokat.
Előnye, hogy többet talál, hátrány, hogy lassabb, mint a ritka illesztés.

OpenCV-ben előre megíva a sűrű illesztés van, ez a cvFindStereoCorrespondenceBM(). Ha benne lenne a ritka is, szóljatok, mert akkor elkerültem :).

Eddigi posztokban a ezzel szenvedtem, de most már megvan a hiba. BM-t újra be kellett állítani, és most már tényleg utána néztem, hogy a beadható adatok mit is csinálnak.

A BM beállításai 3 részre oszthatóak:
Előszűrés: a keresgélés előtt normalizálja a képet (preFilterType, preFilterSize, preFilterCap)
A keresés beállításai (SADWindowSize, minDisparity, numberOfDisparities)
Utószűrés: a hibás találatok törlése (textureThreshold, uniquenessRatio)

Az eljárás lényege:
Tehát van az a kék tárgy, látja a jobb és a bal is. A kép már rektifikálva van, azért a tárgynak mindkét képen egyező sorban kell lennie (y0), innentől kezdve 1D-s keresés (épp ezért nagyon fontos a rektifikálás).
Meg kell keresni, hogy a bal oldali képhez képest mennyire van "elmozdulva" a másik képen a tárgy. A BM szépen elindul a jobb oldali képen a x0,y0 pontból és megkeresi a pixelt egy adott intervallumban (numberOfDisparities) mozogva. Persze lehet, hogy a bal képre csinálja az egészet, nem néztem meg a BM forrását.

Ha megtalálja, eltárolja a bal oldali x0, y0 pixelhez az elmozdulást az elmozdulástérképbe (=disparity map). Ha nem találja meg, akkor általában a minDisparity-1 értéket rakja oda.

Megcsináltam kézzel az elmozdulásokat, egy képpáron saját szememmel megkerestem a térben ugyanazon pontokat, és lemértem, hogy be tudjam állítani a függvényt:

Katt, hogy látszódjon

Az adatok közül csak az X és Y a fontos. A képeket egymás mellé raktam, ezért a jobb oldali X értékekből 320-t ki kell vonni és úgy kiszámolni pixelben az elmozdulást.

A legnagyobb elmozdulás itt 82 volt, tehát a numberOfDisparities-t ennél kisebbre nem rakhatom. A minDisparity meg azt jelenti, hogy az x0, y0 pont X-ben mennyivel mennyen arrébb a jobb képen. Például =0 értéknél marad a helyén, >0 esetén balra tolódik, <0 esetén jobbra tolódik.

Bal disparity maphoz ezeket az adatok adtam meg (többi érték default):

BMState->numberOfDisparities=96;
BMState->minDisparity=0;

Magyarul x0 és y0 ne változzon, és max. 96 pixeles tartományban kereshet. A numberOfDisparities értékének pozitívnak és oszthatónak kell lennie 16-tal ezért 96 és nem 80.

Ugye mindezt fordítva is meg kell csinálnom, hogy a jobboldali képre határozza meg az elmozdulásokat, de a numberOfDisparities nem lehet negatív szám, a pontot meg jobbra kell keresni.

Itt jön a képbe a minDisparity, azt tolom el 96-tal, így a beállítások:

BMState->numberOfDisparities=96;
BMState->minDisparity=-96;

Természetesen a BM meghívásakor is fel kell cserélni a két képet.
Ezzel viszont előfordulhat, hogy hülyeségeket talál, persze alapesetben is találhat nem odaillőket, amiket mégis párosításnak néz. Eredményként a balra csinált elmozdulástérképnek pontosan az ellentétjét kell kapnom (logikus, amit balon +50-re talált meg, azt jobbon -50-nél kell találnia).

A szűrés nagyon egyszerű, ha baloldali képre meghatározott elmozdulás negatív ellentétje van a jobboldali párján, akkor az az elmozdulás jó, megtartjuk, különben minDisparity-1 értéket kapja.

A leszűrt elmozdulástérképet berakom a cvReprojectImageTo3D()-be, aztán ebből a 3D-s ponthalmazból próbálom megállapítani, hogy van-e akadály a robot előtt.

Október 22., még 48 nap

Előző napi dolgokat matlab scripttel tesztelgettem, de ma a kódba berakva is ugyanúgy működik.

Lássuk mit kaptam.

BM default, 3D (minDisparity=0; numberOfDisparities=64)

BM mod, 3D (minDisparity=20; uniquenessRatio=60)

BM bal-jobb szűréssel, a fenti beállításokkal, 3D

Szépen megszűrte a felesleget. Most kérdezhetitek, hogy a BM mod miért nem volt jó.
A BM mod-dal alapvetően az a baj, hogy közelebbi tárgyakat nem találta meg és túl sok elveszett a valós 3D-s pontokból. Szükség volt a "megengedőbb" beállításra, hogy minél több részlet maradjon meg, de a tévedések mégis essenek ki, ezért kellett a bal-jobb szűrés.

Mivel gyakorlatilag megvan minden, a robot mozgásának az algoritmusa van már csak hátra. Terveim szerint kb. fél méteren forduljon ha akadály van előtte, ezért szerintem a fejmozgatást nem úszom meg, mert ilyen távolságon már képtelen balra vagy jobbra látni álló képen, így másképp nem tudja megállapítani, hogy merre van a megfelelő irány.

Október 23., még 47 nap

Implementáltam a robotos programba a bal-jobb szűrés, remekül működik. Az FPS nem csökkent a lehíváshoz képest.

Fogtam az összes adatot, amit csak gyűjtöttem és megalkottam egy algoritmust (ne gondoljatok bonyolultra) ami meglátja a tárgyat. Az adatokat átböngészve pedig a küszöbszámokat is meghatároztam. Mindezt szintén beleraktam a robotos programba, de még csak kiírja. Rövid a bekezdés, de sokáig tartott:).

Október 24., még 46 nap

Itt a nagy nap, ma videót kell csinálnom a mozgásról mindenáron.

Elsőként megvizsgáltam, milyen sebességnél nem rázkódnak a kamerák, mely értékeknél fordul megfelelő szöget a robot úgy, hogy ne boruljon fel, kikísérleteztem, hogy a fejmozgatás után mennyi időt kell várni, hogy tiszta legyen a kép. Fontos adatok, mert nagyon fent van súlypontja a robotnak, gyors fordulásnál hatalmasat tud esni.

Csináltam egy ablakot, amivel a fontos adatokat be tudom vinni, mert előfordulhat, hogy majd máshol is felvesszük a mozgását és ott már nem lehet kódot átírogatni.

Felbukkant egy hatalmas bug, aminek egyelőre nem értem az okát. Jelzést adok egy szálnak, hogy leállhat, de mégse áll le. Ugyanúgy van használva, mint az összes többi, de ez valamiért nem áll le. Felvétel miatt később keresem meg az okát.

Végül boldogan jelenthetem, hogy a heti terv teljesítve, van felvétel :). Majd a videókat is bemutatom, de azokat csak a védés után, addig nem szeretném.

Hozzászólások

(#1) Cucuska2


Cucuska2
őstag

és ha a szál leállítása helyett üres adatokat adsz neki?

És a videóról: mit értesz az alatt, hogy 'védés'?

Rock and stone, to the bone! Leave no dwarf behind!

(#2) Elrood válasza Cucuska2 (#1) üzenetére


Elrood
őstag

Záróvizsgán kérdéseket tesznek fel a szakdogával kapcsolatban, elő kell adnod, beszélned kell róla, ezt hívják védésnek. Elvileg itt kéne kiderülnie, hogy te csináltad vagy sem.

Szál:
Az nem jó, mert magától működik. Az a baj, hogy gyakorlatilag van két szál, az a szál, amit le akarok állítani abban van egy while ciklus. Ami leállítja, megváltoztat egy változót, amitől a while ciklusból ki kéne lépjen a másik. A leállító pedig türelmesen vár, hogy véget érjen a másik, de soha nem ér véget, soha nem jön ki abból a ciklusból, pedig azon belül nincs újabb ciklus. (Erőszakosan nem állíthatom le, mert memory leak keletkezne.)

Más részeken is ezt használtam semmi baja nem volt tőle. A csütörtöktől kezdve nem sokat aludtam, hogy kész legyek, lehet elkövettem valamit ami most nem tűnik fel. A másik ötletem, hogy már annyi szál dolgozik, lehet, hogy belekavarodott az egész.

Úgy is még át kell dolgoznom, mert a videó kedvéért csak össze van hányva az egész, ilyet nem adnék be soha:).

[ Szerkesztve ]

''The spice exists on only one planet in the entire universe. A desolate, dry planet with vast deserts. The planet is Arrakis, also known as DUNE.''

(#3) Elrood válasza Elrood (#2) üzenetére


Elrood
őstag

Sikerült rájönni a szálfagyásra.

Akkor jön elő, ha a program főablakába sok üzenetet írok ki és jelzem a szállnak, hogy leállhat. A főszálban WaitForSingleObject() függvényhez jut, ezzel várom meg, hogy véget érjen a mellékszál, de a mellékszál eközben emiatt a függvény miatt megáll, ezért véget érni se tud. A várakozás végtelenre volt állítva, emiatt befagyott minden.

Két megoldás van erre:
1. Minél ritkábban írok ki üzeneteket a főablakba, hátha nem akad meg.
2. WaitForSingleObject() várakozását nem végtelenre teszem, hanem néhány másodpercre. Ha megakad a mellékszál, a beállított idő múlva a főszál befejezi a várakozást és továbblép, és a mellékszál folytatja a futást, majd le tud állni.

Nem 100%-s megoldás, de ez a két megoldás nem okoz problémát a programomban, ezért minden végtelen várakozást, amit gomboknál használtam átállítottam.
Inkább legyen egy fault mint teljes fagyás, mert a teljesen befagyott programot nagyon nehéz kilőni.

A projekthez annyit, hogy lehet már nem készül újabb poszt jó sokáig, mert úgy néz ki újabb funkcióval nem fog bővülni a program, max. néhány látványi dologgal (ezeket kirakom még), mert november közepén megint demonstrátor leszek pár napig.

A videókat, meg egy esetleges cikket pontosabban leírva mindezt kicsit mély víz szerűen megfogalmazva majd február körül várható.

[ Szerkesztve ]

''The spice exists on only one planet in the entire universe. A desolate, dry planet with vast deserts. The planet is Arrakis, also known as DUNE.''

További hozzászólások megtekintése...
Copyright © 2000-2024 PROHARDVER Informatikai Kft.