• No results found

Formatet för punktmoln skapade genom COLMAP består av ett par filer där främst points3D.txt och images.txt var av intresse.

Bild 17: Segmenterade träd av varierande kvalité.

Points3D:

 POINT3D_ID

 X, Y, Z

 R, G, B

 ERROR, TRACK[] as (IMAGE_ID, POINT2D_IDX) Images:

 IMAGE_ID

 QW, QX, QY, QZ

 TX, TY, TZ

 CAMERA_ID

 NAME

 POINTS2D[] as (X, Y, POINT3D_ID)

Eftersom att jag på något sätt behöver hålla reda på alla kopplingar mellan punkterna i 3D och pixlarna i 2D för varje existerande bild som användes vid skapandet av punktmolnet – där även denna information måste var lättillgänglig när det kommer till hastighet för hämtning och manipulation – så var jag tvungen att skapa mig en mer eller mindre omfattande samling av datastrukturer.

Tittar man på attributen som points3D innehåller så kunde man skapa följande sätt att hålla informationen:

Hash table: { point_id : [x,y,z, ...] }

Man har då möjlighet att hämta en specifik punkts’ koordinater i 3D givet dess point_id.

Utöver det så skapade jag även följande efter inläsning av points3D:

Hash table: { point_id : [image_id_1, image_id_2, …] }

Vilket då ger oss möjlighet att hämta alla bilder som en viss punkt är synlig i, vilket blev relevant för många delar av programmet.

Sedan för inläsning av images skapades ytterligare datastrukturer, där även { point_id : [x,y,z] } användes i processen för att beräkna varje punkts’ avstånd från kameran i varje enskild bild. Detta användes aldrig för någon funktion i programmet, men ansågs nödvändigt för framtida utveckling, utifall man på något sätt vill basera uppdateringar eller modifikationer av pixel-masker på hur långt ifrån punkterna i fråga är från kameran.

Så jag gjorde att programmet vid inläsning skapar en distance.txt-fil, om den inte redan är skapad sedan tidigare, för att inte behöva göra om avståndsberäkningarna vid varje uppstart, då avståndet för punkterna är konstant.

Jag behövde även för varje image_id ha möjlighet att kunna få fram punkt→pixel- och pixel→punkt-kopplingen på ett smidigt sätt, så jag skapade följande:

Hash table: { image_id : [ImageData, ImageData, ...] } Där ImageData är en klass som ser ut på följande sätt:

Så för varje bild har man då möjlighet att få fram pixel→punkt-kopplingen eller tvärtom. Vi ser även qvec och tvec, som innehåller QW, QX, QY, QZ och TX, TY, TZ som används för att beräkna varje punkts avstånd.

Jag behövde även möjlighet att ha en koppling mellan image_id och bildens riktiga filnamn, så datastrukturer för detta skapades även:

Hash table: { image_id : image_name } Hash table: { image_name : image_id }

Slutligen för att skapa de initiala pixel-maskerna för samtliga träd i alla bilder i bildsekvensen så använde jag mig av följande datastrukturer som skapades ovan:

List: [ [tree1_point_1, tree1_point_2 ... ] …]

Listan ovan skapas genom att man går igenom alla segmenterade träd, som är lagrade i filer innehållande alla punkter som trädet består av.

Alla punkter som ett träd består av återfinns i punktmolnet som de segmenterades från.

Hash table: { image_id : [ImageData, ImageData ...] } Hash table: { point_id : [image_id_1, image_id_2 …] }

Med all denna data kunde jag då börja gruppera ihop allting i objekt av klassen PointObject som ser ut på följande vis:

Så låt oss säga att man segmenterar ut 10 träd som man matar in under inläsningen i form av filer innehållande alla dess punkter. Genom alla datastrukturer ovan så kan man skapa 10 objekt av PointObject.

Varje objekt besitter då följande:

obj_name – Namnet på objektet.

Points – Samtliga punkter som objektet består utav.

img_polygon – Varje bild som objektet är synligt i och den skapade pixel-masken utifrån alla punkter som tillhör objektet i samtliga bilder.

img_pixels – Varje bild som objektet är synligt i med tillhörande samling av pixlar som har en pixel→punkt-koppling till objektets punkter.

img_points – Varje bild som objektet är synligt i och en samling av alla punkter som har en punkt→pixel-koppling till objektet.

img_update – Varje bild som kräver en uppdatering av sin pixel-mask efter att en uppdatering har skett hos någon av objektets alla pixel-masker.

Med denna gruppering av all relevant data både vad gäller 2D och 3D så kan man på ett enkelt sätt hämta all data för ett givet objekt i en given bild bara genom att veta img_id.

Varje PointObject skapas genom att man läser in alla segmenterade träd och tittar på deras point_id. Med denna data så kan man då genom datastrukturerna ovan finna alla bilder som punkterna är synliga i och deras motsvarande pixel-koordinater. Man har nu tillräckligt med data för att titta på exakt vilka pixlar som tillhör ett träd för alla bilder trädet är synligt i.

Bild 18: Automatiskt genererade pixel-masker genom bildsekvensen.

För varje bild och dess pixlar skapar man då en konvex pixel-mask, eftersom i alla pixlar som har motsvarande synliga punkter i trädet för en given bild, kommer att ha pixlar som existerar inom trädets egentliga konturer. Genom att ta samtliga pixlar och köra dessa genom en algoritm som skapar en konvex pixel-mask så har man slutligen trädets initial pixel-mask – den automatiskt genererade pixel-masken som sedan kan redigeras av användaren. Denna lagras då i img_polygon, där man enkelt kan hämta en pixel-mask genom ett img_id.

Den stora användningen av hash table och dess O(1) tidskomplexitet för hämtning av värdet i sina key-value-par gjorde att jag på ett väldigt snabbt sätt kan hämta samtliga träds’ pixel-masker för ett givet img_id.

Jag gjorde även bedömningen att det var värt att läsa in och bearbeta all data för alla segmenterade objekt direkt vid inläsning i stället för att låta vissa delar ske dynamiskt under användning av programmet. Då man får en förbättrad användbarhet om operationer sker snabbt vid användning.

Related documents