Univerzita Karlova v Praze Matematicko-fyzikální fakulta
DIPLOMOVÁ PRÁCE
Michal Havlena
Pořizování HDR dat
Kabinet software a výuky informatiky Vedoucí diplomové práce: RNDr. Josef Pelikán Studijní program: Informatika
Děkuji RNDr. Josefu Pelikánovi za cenné připomínky a rady při tvorbě této práce. Nepostradatelným pomocníkem se mi stal také server google.com.
Prohlašuji, že jsem svou diplomovou práci napsal samostatně a výhradně s použitím citovaných pramenů. Souhlasím se zapůjčováním práce. V Praze dne 12. srpna 2005
Michal Havlena
2
Obsah
1 High Dynamic Range 6 1.1 Úvod .................................................................................................................. 6 1.2 Pořizování HDR dat........................................................................................... 7 1.2.1 Pořizování skládáním............................................................................ 7 1.2.2 Přímé pořizování................................................................................... 9 1.2.3 Formáty pro ukládání HDR dat .......................................................... 10 1.3 Zobrazování HDR dat...................................................................................... 12 1.3.1 Globální metody komprese................................................................. 13 1.3.2 Lokální metody komprese .................................................................. 13 1.3.3 Přímé zobrazování .............................................................................. 16 1.4 Využití HDR dat .............................................................................................. 17 1.4.1 Zpracování obrazu .............................................................................. 17 1.4.2 Grafické akcelerátory.......................................................................... 18 2 Panoramatické snímky 21 2.1 Přínos panoramatických snímků...................................................................... 21 2.2 Pořizování panoramatických snímků............................................................... 22 2.2.1 Formáty pro ukládání panoramatických snímků ................................ 22 2.2.2 Netradiční metody pořizování panoramat........................................... 24 2.2.3 Klasické pořizování panoramat spojováním....................................... 25 2.3 Tvorba HDR panoramat .................................................................................. 28 2.3.1 Možnosti složení konstrukcí ............................................................... 28 2.3.2 Metoda využívající kompresi HDR dat .............................................. 30 3 Popis aplikace HDR Panorama 32 3.1 Modulární návrh aplikace ................................................................................ 32 3.2 Acquirer – pořizování snímků ......................................................................... 34 3.2.1 Spolupráce s fotoaparátem Canon EOS.............................................. 35 3.3 Combiner – skládání do HDR obrazu.............................................................. 36 3.3.1 Skládání pomocí gamma křivky ......................................................... 36 3.4 Tonemapper – komprese HDR obrazu ............................................................ 37 3.4.1 Logaritmická komprese ...................................................................... 37 3.5 Stitcher – spojování do panoramatu ................................................................ 38 3.5.1 Program Hugin.................................................................................... 38 3.6 Warper – převod panoramatických formátů .................................................... 41 3.7 RadianceIO – vstup a výstup HDR dat............................................................ 42 3
4 Dokumentace k HDR Panorama 44 4.1 Vnitřní datové struktury................................................................................... 44 4.1.1 ShotImages.......................................................................................... 44 4.1.2 RadianceBuffer ................................................................................... 45 4.2 Dialogy aplikace .............................................................................................. 46 4.2.1 Výběr časů expozice pro pořizování HDR dat ................................... 46 4.2.2 HDR Manager..................................................................................... 47 4.2.3 Options dialog..................................................................................... 47 4.2.4 About dialog ....................................................................................... 47 4.3 Hlavní okno aplikace ....................................................................................... 48 4.3.1 Stavy aplikace ..................................................................................... 48 4.3.2 Vizualizace průběhu výpočtu.............................................................. 49 4.3.3 Prohlížeč obrázků ............................................................................... 50 4.4 Ukládání nastavení aplikace ............................................................................ 51 4.5 Přerušení rozdělaného výpočtu........................................................................ 52 4.5.1 Export a import sérií snímků .............................................................. 52 4.5.2 Navázání na kontrolní bod.................................................................. 53 4.6 Kuchařka k přidání další implementace modulu ............................................. 54 4.6.1 Přidání implementace základního modulu.......................................... 54 4.6.2 Přidání implementace modulu Warper ............................................... 54 4.6.3 Přidání implementace modulu RadianceIO ........................................ 54 5 Závěr
56
Literatura
58
A Manuál k HDR Panorama
59
B Popis formátu pto
61
4
Název práce: Pořizování HDR dat Autor: Michal Havlena Katedra: Katedra software a výuky informatiky Vedoucí diplomové práce: RNDr. Josef Pelikán e-mail vedoucího:
[email protected] Abstrakt: Práce se zabývá návrhem systému využívajícího digitální fotoaparát k automatickému pořizovaní high dynamic range (HDR) map okolí. Systém pořizuje snímky s různými časy expozice a s různými směry pohledu. Použitím HDR komprese na složené snímky získá pro každý směr pohledu nový obrázek a tyto obrázky jsou použity ke snadnému nalezení řídících bodů na celé ploše budoucího panoramatu. Pak je spuštěna externí aplikace, která spojí pořízené snímky odděleně pro každý čas expozice za použití těchto řídících bodů, a žádaná HDR mapa okolí je nakonec získána složením spojených panoramat. Aplikace popsaná v druhé části práce implementuje tento systém. Důraz je kladen na to, aby aplikace byla dostatečně modulární a umožňovala vícenásobné implementace jednotlivých kroků. Přiložená aplikace HDR Panorama obsahuje ukázkové implementace navržených rozhraní a umožňuje s použitím fotoaparátu Canon EOS a programu Hugin HDR mapy okolí pořizovat a následně je ukládat do souborů ve formátu RGBE nebo OpenEXR. Klíčová slova: digitální fotografie, high dynamic range, spojování obrázků, mapa okolí Title: HDR Data Acquisition Author: Michal Havlena Department: Department of Software and Computer Science Education Supervisor: RNDr. Josef Pelikán Supervisor’s e-mail address:
[email protected] Abstract: The thesis proposes a system for automatic high dynamic range (HDR) environment maps acquisition using a digital camera. The system acquires images with different shutter speeds and in different directions. It uses HDR compression on combined images to obtain a new image for each direction and these images are used to easily find control points on the whole area of the future panorama. Then an external application is run to stitch acquired images separately for every shutter speed using these control points and the desired HDR environment map is finally obtained by combining the stitched panoramas. The application described in the second part of the thesis implements this system. The focus is given on the fact that the application should be as much modular as possible to allow multiple implementations of all the individual steps. Enclosed application HDR Panorama contains sample implementations of the proposed interfaces and allows to acquire HDR environment maps using a Canon EOS camera and Hugin stitcher and to save them in the RGBE or OpenEXR file format. Keywords: digital photography, high dynamic range, image stitching, environment map
5
Kapitola 1 High Dynamic Range 1.1 Úvod Snahou člověka vždy bylo realisticky zachycovat svět kolem sebe – od prvních obrázků na stěnách jeskyně přes malířské umění a klasickou fotografii až po dnešní digitální videokamery v mobilních telefonech. Postupem času se výsledky stále více přibližovaly realitě, jeden problém však zůstával nevyřešen. V reálném světě nacházíme velké rozdíly v množství světla ve scéně. Podle Reinhard a kol. [1] je rozdíl množství světla v nočních scénách a ve scénách na sněhu za slunného dne až deset řádů absolutního rozsahu, rozdíl množství světla v osvětlených a ve stinných částech jedné scény pak může být i více než čtyři řády rozsahu. Tento rozdíl v rámci jedné scény se nazývá dynamický rozsah1 scény a naším cílem je jej celý přenést do pořízeného snímku. Jedním z nejpalčivějších problémů dnešní digitální fotografie je právě omezená schopnost zachytit na snímcích dostatečně velký dynamický rozsah – současný formát digitálních snímků zvládne pojmout maximálně dva řády rozsahu. Volbou clonového čísla a času expozice při fotografování volíme, kterou část dynamického rozsahu scény přeneseme do snímku a kterou ztratíme (bude podexponována do černé nebo přeexponována do bílé). Proto bylo již v devadesátých letech minulého století navrženo přejít na jiný formát snímků – na formát schopný zachytit velký dynamický rozsah – High Dynamic Range2. Hlavní myšlenka nového formátu spočívá v tom, že místo klasických bitmap, které uchovávají hodnotu světlosti pixelu v položce typu byte poskytující rozsah 0–255, použijeme položku typu float, která svým rozsahem předčí i největší možné rozdíly v reálných scénách. Určitou daní za velký rozsah je pak omezená přesnost, která však při zpracování a zobrazení snímku nevadí. Tento nový formát i přes své nesporné výhody však teprve pomalu proniká mezi veřejnost do všeobecného používání. Současná běžná pořizovací ani zobrazovací zařízení nejsou schopna data v tomto formátu přímo pořizovat respektive zobrazovat, až poslední verze oblíbeného Adobe Photoshop konečně přináší možnost práce s daty v tomto formátu. Problematice pořizování a zobrazování HDR dat se věnují části 1.2 respektive 1.3, v části 1.4 pak shrneme výhody nového formátu i s příklady praktického použití. 1 2
z anglického dynamic range dále budeme používat zkratku HDR
6
1.2 Pořizování HDR dat Pokud se rozhodneme pořídit HDR data, máme dvě možnosti. Když vlastníme speciální pořizovací zařízení, získáváme data přímo v požadovaném formátu. Pravděpodobnější variantou však je, že máme k dispozici pouze klasický digitální fotoaparát3 a z něj získaná sekvence snímků nám slouží jako vstupní data algoritmu, který snímky z této sekvence určitým způsobem složí do výsledného HDR snímku.
1.2.1
Pořizování skládáním
Bez újmy na obecnosti budeme nyní uvažovat pouze černobílé fotografie, kde hodnoty pixelů odpovídají světlosti daného bodu. Přechod k barevným fotografiím je pak zřejmý rozkladem na kanály RGB. Při výrobě HDR snímku využijeme fyzikální vlastnost zvanou reciprocita. Ta říká, že hodnota expozice na daném bodě snímacího CCD čipu, kterou získáme jako součin hodnoty ozáření tohoto bodu a času expozice, X = E∆t
(1)
je závislá pouze na tomto součinu a ne na jeho jednotlivých složkách. Prodloužením času expozice na dvojnásobek při poloviční hodnotě ozáření tedy dostaneme shodnou hodnotu expozice. Jak říkají Debevec a Malik [2], tato vlastnost je při pořizování digitálních fotografií zaručena, pokud hodnota čtená z CCD odpovídá absolutnímu počtu dopadnutých fotonů za určitý čas, což běžně používané CCD čipy dělají. I při omezeném rozsahu hodnot expozice, které je čip schopen změřit, tedy můžeme získat velký rozsah z nich spočtených hodnot ozáření tím, že budeme pořizovat snímky stejné scény s různými časy expozice. Hodnotu ozáření určitého bodu pak určíme jako
E=
X . ∆t
Alternativně lze výslednou hodnotu expozice ovlivňovat také změnou clonového čísla, toto však není z důvodu změny hloubky ostrosti doporučováno. Tím ale naše práce nekončí. Na výsledném snímku pořízeném digitálním fotoaparátem totiž nejsou hodnoty pixelů rovny hodnotám expozice na čipu a tato závislost navíc není ani lineární. Funkce převádějící hodnoty expozice na daném bodě čipu na hodnoty pixelu se nazývá charakteristická křivka zařízení, označíme ji f. Naším dalším úkolem je tuto křivku odhalit. Debevec a Malik [2] prezentují metodu výpočtu této křivky přímo z pořízených snímků. Tato metoda numericky vypočte hledanou křivku až na konstantu, což vzhledem k tomu, že se HDR data často normují do intervalu <0, 1>, nepřináší žádné problémy. Pokud bychom přesto potřebovali mít správné absolutní hodnoty osvětlení, můžeme si pomoci vyfotografováním svítidla o známých parametrech. U digitální fotografie však často stačí uvažovat jednoduchou křivku gamma 2,2, protože digitální proces nepřináší při zpracování žádné nelinearity a tato křivka je do procesu vložena uměle kvůli napodobení vzhledu celuloidové fotografie. Při použití jednotné křivky pro všechny kanály RGB navíc odpadá nutnost znovu vyvažovat bílou. 3
Algoritmy na převod série klasických snímků do HDR snímku lze použít i na obrázky vzniklé naskenováním papírových fotografií, případně přímo celuloidových negativů. Těmito postupy se ale ve své práci nebudu zabývat, píšou o nich například Debevec a Malik [2].
7
Když uvážíme, že charakteristická křivka zařízení je spojitá monotónní funkce, můžeme pak hodnotu ozáření každého bodu spočítat jako
E=
f
−1
(Z ) , ∆t
kde Z = f ( X )
(2)
je hodnota pixelu na daném místě snímku. Nyní je na místě otázka, kolik klasických snímků potřebujeme ke konstrukci příslušného HDR snímku a jaké mají být rozdíly jejich časů expozic. K tomu si musíme objasnit pojem pracovní oblast4 čipu. Je to takový rozsah hodnot expozice, který odpovídá střední části charakteristické křivky zařízení. Její konce, kde velká změna hodnoty expozice způsobí pouze malou změnu hodnoty pixelu, není vhodné k výpočtu hodnoty expozice z hodnoty pixelu použít. K pokrytí celého dynamického rozsahu scény je nutné, aby hodnota ozáření každého bodu padla po přepočítání na expozici alespoň na jednom snímku do pracovní oblasti čipu. Minimální počet pořízených snímků je tedy při označení dynamického rozsahu scény R a pracovního rozsahu čipu C ⎡R⎤ ⎢⎢ C ⎥⎥ .
Pokud zvolíme tento počet snímků, musíme pro pokrytí celého dynamického rozsahu scény nastavit rozdíl časů expozice tak, aby se rozsahy hodnot ozáření, kterým pro daný čas expozice odpovídá pracovní rozsah čipu, nepřekrývaly. Pak padne hodnota ozáření každého bodu po přepočítání na expozici do pracovního rozsahu čipu na právě jednom snímku a hodnota pixelu na příslušném místě tohoto snímku je pak použita k výpočtu hodnoty ozáření daného bodu. Takto navržený postup je však velmi citlivý na šum. Ukazuje se, že ideálním rozdílem časů expozice jsou maximálně dva expoziční stupně5, protože pak padne přepočítaná hodnota ozáření do pracovního rozsahu na více snímcích a můžeme ke snížení vlivu šumu použít průměrování. Nejjednodušším způsobem, jak průměrování aplikovat, je jako hodnotu ozáření daného bodu brát aritmetický průměr hodnot ozáření spočítaných z hodnot pixelů na snímcích, kde tyto hodnoty padnou po přepočítání charakteristickou křivkou zařízení do pracovní oblasti čipu. Častěji používanou a kvalitnější metodou je pak výpočet váženého průměru hodnot ozáření. Váha hodnoty ozáření spočítané z hodnoty pixelu se odvozuje z hodnoty pixelu z následujícím způsobem: w( z ) = z − Z min pro z ≤ 12 ( Z min + Z max )
w( z ) = Z max − z pro z > 12 ( Z min + Z max ) ,
(3)
kde Zmin a Zmax jsou minimální a maximální hodnota pixelu, typicky 0 a 255. Největší váhu mají hodnoty ozáření ze snímků, kde je hodnota pixelu nejblíže středu rozsahu. 4 5
anglicky working range anglicky stops
8
1.2.2
Přímé pořizování
Největší nevýhodou výše popsané metody využívající k pořízení HDR dat skládání klasických snímků je její časová náročnost. Samotné pořízení snímků i následný běh algoritmu potřebují desítky sekund, navíc je nutné, aby během pořizování snímků byla scéna statická. Tyto problémy by odpadly, kdybychom navrhli zařízení, které by pořizovalo současně snímky s různými časy expozice. Přesně tímto problémem se zabývali Aggarwal a Ahuja [3] a navrhli prototyp kamery, která je schopná pořizovat dokonce HDR videosekvence, tedy HDR data v reálném čase.
Obrázek 1.1: Prototyp HDR kamery z článku [3].
Princip kamery je poměrně jednoduchý. Jak naznačuje další obrázek, paprsky jsou hned za objektivem rozděleny zrcadlovým jehlanem na několik svazků, každý z nich dopadá na jeden obyčejný osmibitový senzor.
Obrázek 1.2: Princip HDR kamery z článku [3]: (a) Umístění čočky, jehlanu a senzorů k současnému pořízení snímků s různými časy expozice. (b) Rozdělení povrchu čočky na jednotlivé senzory.
9
Z výpočtů v článku vyplývá, že pokud je osa jehlanu rovnoběžná s optickou osou objektivu a vzdálenost vrcholu pyramidy od středu čočky je nulová, není poloha zobrazovaného bodu scény na povrchu každého ze senzorů závislá na vzdálenosti tohoto bodu od objektivu a toto zařízení se po drobných jasových korekcích chová stejně jako klasické zařízení s jedním senzorem. Pro docílení různých časů expozice na jednotlivých senzorech autoři navrhují množství metod. Je například možné umístit před senzory barevně neutrální filtry s různým přenosem, při konfiguraci s trojbokým jehlanem například 1, 0,5 a 0,25. Dostaneme pak poměr časů expozice 1:2:4, tedy tři snímky s rozdílem jeden expoziční stupeň. Podobného výsledku lze docílit, pokud změníme integrační dobu jednotlivých senzorů. Tato metoda však není autory vzhledem k tomu, že vede u nestatické scény k nepatrně odlišným obrazům na jednotlivých senzorech, doporučována. Další možností je posunout vrchol jehlanu tak, aby osa jehlanu nebyla totožná s optickou osou objektivu, ale stále s ní zůstala rovnoběžná. To způsobuje, že na každý ze senzorů dopadá různé množství světla a vhodnou volbou polohy vrcholu jehlanu můžeme nastavit poměr časů expozice také na 1:2:4, navíc bez zbytečných ztrát světla na filtrech. Stejná skupina vědců zkoumá také možnosti, jak zrychlit pořizování HDR dat při minimálních úpravách běžného hardware. Navrhli například metodu, jak zakrytím poloviny plochy snímacího CCD čipu běžné digitální kamery barevně neutrálním filtrem s přenosem 0,25 pořizovat HDR obraz současně s pořizováním panoramatického snímku. Při rotaci kamery je obraz každé části scény pořízen postupně zakrytou i nezakrytou částí čipu a máme tedy snímek daného místa ve dvou časech expozice s rozdílem dvou expozičních stupňů. Podrobnosti k implementaci této metody včetně prezentovaných výsledků můžete nalézt v Aggarwal a Ahuja [4].
1.2.3
Formáty pro ukládání HDR dat
Pro uložení HDR dat potřebujeme formát, který je schopen uschovat bitmapu složenou z položek typu float. Z běžně používaných formátů určených k ukládání obrázků toto zvládne pouze TIFF ve své variantě pro práci s bitmapami s plovoucí desetinnou čárkou6. Nás však budou více zajímat formáty vyvinuté speciálně za účelem ukládání HDR dat, které zohledňují při případné kompresi jejich specifika. Prvním a také jednodušším z těchto formátů je RGBE, který vymyslel v roce 1992 G. Ward. Ten vychází z toho, že hodnota červeného, zeleného a modrého kanálu pro konkrétní pixel se u většiny obrázků řádově neliší a proto navrhl, aby se tato tři desetinná čísla (RGB) zapisovala se společným exponentem (E). U obrázků je navíc málo důležitá absolutní přesnost uschovaných dat, takže lze data ukládat s poloviční přesností – 8 bitů mantisy a 8 bitů exponentu. Formát používá 32 bitů na pixel, které rozděluje následujícím způsobem: • 3× 8 bitů pro mantisy hodnot jednotlivých barevných kanálů • 8 bitů pro společný exponent Z popsaného principu okamžitě vyplývají výhody a nevýhody tohoto formátu. Když opomineme fakt, že nelze ukládat hodnotu alfa kanálu, dochází při použití tohoto formátu k velké ztrátě přesnosti hodnot některých barevných kanálů, pokud je hodnota jiného barevného kanálu o hodně větší, rozdělení 16-ti bitů na 8 bitů mantisy a 8 bitů exponentu také není ideální. Na druhou stranu si při ukládání vystačíme s 32 bity na pixel a následnou aplikací jednoduché RLE komprese docílíme přijatelné velikosti souboru. 6
floating point TIFF
10
Druhým formátem je OpenEXR, který vyvinula v roce 1999 společnost Industrial Light & Magic jako formát využívaný při produkci digitálních vizuálních efektů. Tento formát prošel v následujících letech dalším vývojem a v roce 2003 se stal volně dostupným. Jeho hlavní rysy jsou následující: • 32-ti nebo 16-ti bitová přesnost ukládaných obrazových HDR dat – nově vyvinutý 16-ti bitový desetinný typ half7 je schopen zachytit devět řádů dynamického rozsahu s krokem 1024 odstínů na expoziční stupeň • kompatibilita s grafickým hardware – moderní grafické karty používají při ukládání HDR dat právě typ half, při komunikaci s grafickou kartou tedy nedochází k žádným konverzím • možnost zvolit rozdílnou velikost datového a zobrazovaného okna – toho lze využít k potlačení okrajového jevu při zpracování obrazu (datové okno je větší než zobrazované) nebo k zobrazení výseku obrázku (zobrazované okno je větší než datové) • bezeztrátová a ztrátová komprese – existuje možnost do formátu přidávat nová kompresní schémata, mezi připravená kompresní schémata patří: o PIZ – bezeztrátová waveletová komprese o ZIP – tradiční bezeztrátová komprese o RLE – jednoduchá bezeztrátová komprese o PXR24 – speciální ztrátová komprese • libovolný počet ukládaných kanálů – kromě základních barevných kanálů a alfa kanálu můžeme uložit například kanál s hodnotami normálového vektoru nebo kanál odpovídající z-bufferu. Každý kanál může mít různý datový typ, na výběr je z těchto typů: o half – 16-ti bitový desetinný typ pro ukládání obrazových dat o float – 32-ti bitový desetinný typ pro ukládání dat bufferů o uint – 32-ti bitový celočíselný typ pro ukládání identifikátorů • možnost ukládat data sekvenčně nebo dlaždicově – dlaždicové uložení umožňuje rychlý přístup k datům při zoomování nebo při posouvání obrazu ve velkém souboru • data ve více rozlišeních v jednom souboru – toto je užitečné hlavně při práci s texturami, konkrétně podporuje tyto formáty: o mipmap – data jsou přítomna v původním rozlišení a pak vždy v rozlišení polovičním v obou rozměrech než bylo předchozí rozlišení, celá posloupnost končí až u velikosti 1×1 o ripmap – podobné jako mipmap, ale navíc obsahuje data zmenšená v každém rozměru jinou mocninou dvojky, i zde posloupnost končí až u velikosti 1×1 • možnost uložení metadat – tato data jsou při načítání souboru ignorována, lze je však číst přes speciální rozhraní • přístup přes C++ rozhraní Z výše uvedeného seznamu je zřejmé, že formát nabízí o mnoho více než potřebujeme. Součástí rozhraní je naštěstí také jednoduchý přístup, který lze použít, pokud chceme pouze číst a zapisovat obyčejná RGBA data typu half do sekvenčního souboru bez podpory více rozlišení a metadat. Všechny zde popsané vlastnosti formátu OpenEXR jsou podrobněji vysvětleny v oficiálním dokumentu OpenEXR skupiny, který mám seznamu použité literatury uveden pod číslem [5]. 7
Typ half má 1 znaménkový bit, 10 bitů mantisy a 5 bitů exponentu, jeho rozsah je zhruba 6,0*10-8 až 6,5*104, přičemž čísla menší než 6,1*10-5 nejsou normalizovaná.
11
1.3 Zobrazování HDR dat Dalším problémem spojeným s HDR daty je jejich zobrazování na běžných zobrazovacích zařízeních. Tato zařízení mají dynamický rozsah zpravidla pouze kolem dvou řádů, což je pro HDR data velmi málo. Alternativou k níže popsaným možnostem zobrazování HDR dat je vlastnit speciální zobrazovací zařízení, dva prototypy takových zařízení představíme v části 1.3.3. První možností, jak HDR data na běžném zařízení zobrazit, je nezobrazovat je celá, ale zobrazit pouze řez těmito daty pro nějaký konkrétní čas expozice, kdy se určitá část desetinných hodnot pixelu namapuje na interval <0, 255> a zobrazí jako běžný obrázek. O tomto řezu mluvíme většinou jako o virtuálním snímku. Obvykle však chceme zobrazit data v jejich celém rozsahu, musíme tedy najít způsob, jak na interval <0, 255> namapovat celý rozsah desetinných hodnot. Bez újmy na obecnosti budeme i zde uvažovat pouze černobílá data, kde hodnoty pixelů odpovídají světlosti8 daného bodu. Všechny níže popsané metody pracují buď shodně nad všemi barevnými kanály, nebo převedou na začátku barvu pixelu například podle vzorce L = 0.30 R + 0.59G + 0.11B
(4)
na jeho světlost, pracují se světlostí a nakonec ji převedou zpět do barevných kanálů vzorcem C out
⎛C = ⎜⎜ in ⎝ Lin
s
⎞ ⎟⎟ Lout , ⎠
(5)
kde za C dosazujeme postupně R, G a B. Parametr s ovlivňuje barevnou sytost výsledného obrazu, ideální hodnota většinou leží mezi 0,4 a 0,6. Převod HDR dat do běžného obrázku nazýváme kompresí HDR dat a nabízejí se dva možné přístupy. Pokud budeme vytvářet mapování9 nezávislé na poloze pixelu na obrázku, mluvíme o globálních metodách komprese10. Tato skupina metod vyniká svojí rychlostí a jednoduchostí, protože si stačí předpočítat převodní tabulku a aplikovat ji na hodnoty jednotlivých pixelů. Abychom se vyhnuli inverzím kontrastu na hranách, je nutné, aby převodní zobrazení odpovídající tabulce bylo vzájemně jednoznačné a monotónní. Nevýhodou je často nedostatečná komprese. Hlavně v případě, že HDR data pokrývají víceméně celý dynamický rozsah, je zachování lokálního kontrastu velmi problematické. Druhou možností je snažit se najít mapování, které určitým způsobem zohledňuje polohu pixelu na obrázku, například jeho okolí – zde jde o lokální metody komprese11. Hlavní výhodou těchto metod je fakt, že jedné vstupní hodnotě pixelu může na jednom místě na obrázku odpovídat po kompresi odlišná výstupní hodnota pixelu než na jiném, což při vhodném zakomponování informací o okolí vede ke značnému vylepšení lokálního kontrastu výsledku. Mezi nevýhody této skupiny metod pak patří především výpočetní složitost a možnost vzniku všemožných artefaktů, způsobených právě lokální variancí převodního zobrazení. 8
anglicky luminance anglicky tonemapping 10 tyto metody se někdy označují jako TRC – Tone Reproduction Curves 11 tyto metody se někdy označují jako TRO – Tone Reproduction Operators 9
12
1.3.1
Globální metody komprese
Nejednodušší globální metodou komprese je lineární uniformní komprese, kde jsou vstupní data rovnoměrně mapována na interval <0, 255>. Tato metoda kromě značného potlačení lokálního kontrastu navíc často vede k neúměrnému ztmavení celého obrázku, protože v HDR datech se často vyskytují malá velmi světlá místa (slunce, svítidla, …), která způsobí, že zajímavé části obrázku jsou mapovány do malé oblasti hodnot kolem černé a tedy prakticky neviditelné. Značným vylepšením této jednoduché kompresní metody je logaritmická komprese. Ta zohledňuje kromě výše zmíněné časté vlastnosti HDR dat také fakt, že lidské oko vnímá intenzitu světla zhruba logaritmicky. Zlogaritmováním vstupních dat převedeme velmi světlá místa do malé oblasti kolem bílé barvy a zbude nám poměrně velká oblast pro zajímavé části obrázku, lokální kontrast je ale i přesto velmi potlačen. Globální metody komprese se nadále vyvíjely, mezi další používané patří například gamma korekce nebo různá vylepšení ekvalizace histogramu. Nejlepší z těchto metod zapojují také zkušenosti z fotografické praxe, případně se opírají o medicínské studie zabývající se lidským viděním. Pěkný shrnující přehled těchto metod s jejich stručným popisem poskytuje například Lischinski a kol. [6].
1.3.2
Lokální metody komprese
Lokální metody komprese dosahují typicky lepších výsledků než metody globální. Najdeme u nich dva základní směry, kterými se ubírají. První z těchto směrů čerpá z bohaté praxe celuloidové fotografie a snaží se stejné principy aplikovat i na fotografii digitální. Jednu z metod tohoto typu popisuje Reinhard a kol. [1]. Nejprve musíme nastavit požadovanou průměrnou světlost výsledného obrázku, k tomu slouží hodnota key12 scény. Ta říká, jestli je scéna subjektivně světlá, normální nebo tmavá – hi-key scénou je například bíle vymalovaný pokoj, low-key scénou naopak temné stáje. Hodnota key normální scény je volena jako 0,18. Při zvolené hodnotě key přepočítáme světlost vztahem L ( x, y ) =
a L w ( x, y ) , Lavg
(6)
kde a je zvolená hodnota key a Lavg je průměrná světlost počítaná přes celý obrázek. Navržená metoda vychází z globální metody, která se snaží podobně jako logaritmická komprese minimalizovat vliv malých velmi světlých míst, zde se k výpočtu výsledné světlosti používá rovnice Ld ( x, y ) =
L ( x, y ) . 1 + L ( x, y )
(7)
Výpočet tímto způsobem zaručuje, že malé světlosti projdou téměř beze změny, zatímco velké budou velmi zmenšeny. Zde přichází ke slovu fotografická praxe. V ní je běžné během zvětšování snímků z negativu na fotografický papír určitá místa zastiňovat13 a snižovat tak jejich expozici, jiným naopak nadržovat14 a tím jejich expozici zvyšovat. 12
v češtině se běžně používá toto anglické označení, včetně výrazů hi-key a low-key anglicky dodging 14 anglicky burning 13
13
Po zanesení tohoto principu do výše zmíněné metody získáme novou metodu výpočtu výsledné světlosti Ld ( x, y ) =
L ( x, y ) , 1 + V ( x, y )
(8)
kde V(x, y) značí průměrnou světlost v okolí právě převáděného pixelu. Pokud je průměrná světlost v okolí převáděného pixelu větší než světlost tohoto pixelu, je výsledná hodnota zlomku menší než hodnota zlomku před úpravou v lokální metodu (zastiňování) a dojde tedy k zesílení lokálního kontrastu. V případě, že je průměrná světlost v okolí menší než světlost pixelu, je výsledná hodnota zlomku větší (nadržování) a lokální kontrast je opět zesílen. Pro správnou funkci metody je velmi důležitá správná volba okolí pixelu, ze kterého se průměrná světlost počítá. Autoři použili kruhové okolí s lokálně variabilním poloměrem. Tato variabilita poloměru okolí zaručuje, že bude zvolena vždy optimální velikost poloměru vzhledem k rozptylu světlosti v dané oblasti. Podrobnosti k výpočtu tohoto poloměru naleznete přímo ve zmiňovaném článku. Druhý směr lokálních kompresních metod vychází z předpokladu, že obrázek I(x, y) můžeme rozložit na složku odpovídající odrazivosti R(x, y) a na složku odpovídající osvětlení L(x, y) I ( x, y ) = R(x, y )L(x, y ) .
(9)
Složka R odpovídající odrazivosti bývá občas nazývána jako intrinsický obrázek scény a neobsahuje obvykle větší kontrasty než 100:1. Velké komprese s dokonalým zachováním kontrastů způsobených rozdílností textur a odrazivostí a citelným oslabením kontrastů způsobených přechody světla a stínu bychom docílili, kdybychom od obrázku oddělili složku L, zmenšili ji na novou složku L‘ a pomocí ní spočítali nový obrázek I‘ I ' ( x, y ) = R( x, y )L' ( x, y ) .
(10)
Rozdělení reálného obrázku na tyto dvě složky bohužel není možné. Pokud se snažíme tohoto rozdělení dosáhnout, musíme vždy k řešení přidat nějaké omezující podmínky týkající se vzhledu funkcí odpovídajících jednotlivým složkám. Shrnující přehled možností, jak tyto omezující podmínky definovat a proč, nám nabídne opět Lischinski a kol. [6]. Jádrem tohoto článku je však jejich vlastní metoda přinášející při kompresi HDR dat velmi zajímavé výsledky. V této metodě se její autoři opírají o fakt, že každá drastická změna světlosti v HDR datech se musí v nějakém měřítku obrazu projevit velkou hodnotou gradientu světlosti, jemné detaily, jako například textura, naopak odpovídají mnohem menším hodnotám gradientu. Cílem tedy je najít v různých měřítkách velké hodnoty gradientu a ty určitým způsobem ztlumit. Metoda je poměrně složitá, pokusím se zde nastínit její hlavní myšlenky bez uvažování různých měřítek s tím, že přesný popis metody naleznete v uvedeném článku15. Definujeme funkci, která bude počítat požadované ztlumení gradientů jako 15
Metoda navíc ve skutečnosti nepracuje přímo s obrázkem ale s jeho logaritmem – podle autorů totiž gradienty logaritmu světlosti přesně odpovídají lokálnímu kontrastu.
14
⎛ ∇I ( x , y ) ⎜ Φ( x, y ) = ∇I ( x, y ) ⎜⎝ α
α
β
⎞ ⎟ , ⎟ ⎠
(11)
hodnotami parametrů α a β řídíme vlastnosti ztlumení. Parametr α určuje hranici, nad kterou jsou gradienty ztlumovány, parametr β zase velikost ztlumení. Experimentálně zjištěné ideální hodnoty těchto parametrů jsou α rovna 0,1 násobku průměrného gradientu a β mezi 0,8 a 0,9. Aplikací tohoto ztlumení na obrázek získáme funkci G(x, y) G (x, y ) = ∇I ( x, y )Φ( x, y ) .
(12)
Nyní potřebujeme najít obrázek takový, že funkce G(x, y) bude jeho gradientem. Existence takového obrázku není zaručena, určitě však existuje obrázek, jehož gradient se od G(x, y) liší nejméně z gradientů všech možných obrázků ve smyslu nejmenších čtverců. Požadovaný obrázek I’(x, y) dostaneme jako řešení Poissonovy rovnice ∇ 2 I ' = divG .
(13)
Pokud se snažíme porovnat výsledky jednotlivých kompresních metod, záleží na tom, jaká kritéria při hodnocení preferujeme. Logaritmická komprese je velmi rychlá, způsobuje však velkou ztrátu lokálních kontrastů, metoda podle Reinhard a kol. [1] přináší pěkný fotorealistický obrázek, komprese ale není dostatečná. Nejlepší komprese z výše zmíněných metod dosahuje metoda od Lischinski a kol. [6], která však dává nefotorealistické obrázky s velmi zvýrazněným lokálním kontrastem.
Obrázek 1.3: Výsledky jednotlivých kompresních metod. Vlevo nahoře logaritmická komprese, vpravo nahoře komprese podle Reinhard a kol. [1], vlevo dole komprese od Lischinski a kol. [6] a vpravo dole na ukázku jedna ze vstupních fotografií pro tvorbu HDR dat, která byla následně metodami komprimována.
15
1.3.3
Přímé zobrazování
S rostoucí oblibou pořizovat HDR data roste také potřeba zobrazovat tato data přímo bez nutnosti mapovat je algoritmem do běžného obrázku. Prohlížení HDR dat by se pak spíše podobalo pohledu na reálnou scénu než pohledu na monitor. S tímto cílem navrhli Seetzen a kol. [7] dvě zařízení, která přímé zobrazení HDR dat umožňují. Princip takovýchto zařízení spočívá v tom, že využívají LCD panel jako optický filtr s proměnlivým přenosem k modulaci vysoce intenzivního obrazu s nízkým rozlišením. Zdrojem tohoto obrazu je v případě prvního z navržených zařízení digitální dataprojektor, jak ukazuje následující obrázek.
Obrázek 1.4: Nahoře vidíme princip HDR displeje z článku [7], dole pak fotografii jeho prototypu.
Lampa uvnitř dataprojektoru generuje velké množství bílého světla. To postupně prochází dvěma LCD panely, které toto světlo modulují. LCD panel uvnitř projektoru je upraven tak, že je pouze černobílý, protože průchod barevnými filtry značně zmenšuje přenos panelu, jeho maximální dosažitelný kontrast je 800:1. Po průchodu Fresnelovo čočkou paprsky z projektoru rovnoběžně dopadají na druhý LCD panel s maximálním kontrastem 300:1. Maximální teoretický kontrast dosažitelný touto soustavou je tedy 240000:1, experimentálně bylo změřeno 54000:1 při jasu 2700cd/m2, což hravě předčí všechna běžná zobrazovací zařízení. Kvůli potížím s moaré a s dokonalou kalibrací není možné dosáhnout přesného překryvu pixelů prvního a druhého LCD panelu, lepší je obraz projektoru mírně rozostřit a toto rozostření pak kompenzovat na druhém LCD panelu. 16
Podrobný popis, jak ze vstupního HDR obrazu spočítat obraz pro první a pro druhý LCD panel16 spolu se zdůvodněním, proč lidskému oku nevadí rozostření obrazu projektoru, naleznete přímo ve zmiňovaném článku. Mezi hlavní nevýhody zmíněného řešení patří především velikost soustavy, cena projektoru a jeho energetické nároky a v neposlední řadě množství vznikajícího tepla. To je způsobeno tím, že světlo generované lampou projektoru postupně prochází dvěma filtry, i při zobrazení zcela bílé barvy jsou přenosy LCD panelů tak malé, že více než 98% světla je na filtrech pohlceno. Pokud lampu a první LCD panel nahradíme dvourozměrným polem bílých vysoce svítivých LED diod, světlo bude vznikat pouze tam, kde je skutečně potřeba, a energetické nároky se rapidně sníží. Toto pole je zdrojem vysoce intenzivního obrazu s nízkým rozlišením pro druhé zařízení navrhované ve zmíněném článku. Vzhledem k tomu, že je pole diod šestiúhelníkové a že záře jedné diody ovlivňuje okolní, je výpočet kompenzace na druhém LCD panelu obtížnější než v prvním případě a mezi jediné nevýhody tohoto řešení patří při použití současného grafického hardware nízká snímková frekvence. Ostatní parametry jsou však impozantní – kontrast 280000:1 při jasu 8500cd/m2.
1.4 Využití HDR dat HDR data nalézají široké uplatnění především v místech, kde dynamický rozsah běžného obrázku nestačí. Kromě popsaného použití ve fotografii se uplatňují například při vizualizaci medicínských dat. Mimo vylepšenou vizualizaci však přinášejí díky odstranění nutnosti při ukládání dat ořezat hodnoty příliš světlých nebo příliš tmavých pixelů na bílou respektive černou také dobrý základ pro všemožné výpočty ve zpracování obrazu. Druhou velkou oblastí využití HDR dat je herní průmysl, který pomalu objevuje jejich kouzlo. Podporu HDR dat v současném grafickém hardware rozebereme v části 1.4.2.
1.4.1
Zpracování obrazu
Základní výhodou při použití HDR dat ve zpracování obrazu je možnost pořizovat virtuální snímky scény pro různé časy expozice. Pokud navíc pořizujeme HDR data správně, jsou pak úplně nezávislá na pořizovacím zařízení a lze tedy bez problémů v jednom obrázku míchat data pořizovaná různými zařízeními, bez toho, aby to působilo nepřirozeně nebo přímo rušivě. Je dokonce možné pořízená data míchat i s daty vyrobenými synteticky, například renderováním. Asi nejdůležitějším přínosem pro zpracování obrazu je ale správná propagace velmi světlých míst při používání různých konvolučních jader. Debevec a Malik [2] toto ukazují na příkladu syntetického rozmazání pohybem. Pokud simulujeme horizontální rozmazání pohybem konvolucí s obdélníkovým jádrem velikosti například 37×1 na obrázku s velkým dynamickým rozsahem, dostaneme při použití běžných a HDR dat zcela odlišné výsledky. Při výpočtu nad běžným obrázkem dojde díky tomu, že hodnota světlých pixelů odpovídající nejsvětlejším částem scény byla při ukládání oříznuta, k potlačení propagace těchto velmi světlých míst. U výpočtu nad HDR daty však toto nenastane. Zde jsou tyto světlé pixely opravdu o mnoho světlejší než okolní a nejsvětlejší místa jsou propagována správně. Vše vidíme na následujícím obrázku převzatém z článku [2]. 16
K výpočtu jsou použity pixelshadery moderních grafických karet, po zavedení rozšíření DVI standardu o desetinná data však bude možné výpočet provádět přímo ve speciálním hardware uvnitř zařízení.
17
Obrázek 1.5: Levý obrázek vznikl aplikací syntetického rozmazání na běžný snímek – vidíme značný pokles světlosti oken. Pravý obrázek je virtuálním snímkem HDR dat, na která bylo aplikováno stejné syntetické rozmazání – zde je světlost oken v pořádku a snímek se téměř neliší od reálného rozmazání.
1.4.2
Grafické akcelerátory
Až do nedávné doby grafické akcelerátory neposkytovaly HDR datům žádnou nativní podporu. Objevovaly se proto různé postupy, jak implementovat jednotlivé techniky týkající se HDR dat pomocí toho, co grafické karty nabízejí. Jeden z těchto postupů umožňující používat na běžném grafickém akcelerátoru HDR textury popisuje Cohen a kol. [8]. Zatímco běžná 8-bitová přesnost celočíselných textur je pro zachycení dynamického rozsahu nedostačující, 16-bitová přesnost přináší 256× větší rozsah hodnot, což vede při použití standardní zobrazovací křivky k přibližně 200000× většímu zachytitelnému dynamickému rozsahu17. Běžný grafický akcelerátor ale bohužel neumí s 16-bitovými texturami pracovat, můžeme však tuto texturu v rozdělit na dvě 8-bitové – v0 a v1. První bude obsahovat 8 dolních a druhá 8 horních bitů původní textury. Pokud uvažujeme lineární zobrazovací křivku, určíme hodnotu texelu pro danou hodnotu expozice e jako I (v ) = clamp(ev ) = clamp(e(v0 + 256v1 )) = clamp(clamp(ev0 ) + clamp(256ev1 )) . (14)
Tento výpočet je grafická karta schopna hardwarově akcelerovat, pouze musíme dbát na to, aby e bylo z intervalu <1/256, 1>. Pokud je e menší, projeví se oříznutí hodnot původní 16-bitové textury (nedostatek horních bitů), když je naopak větší, bude docházet ke kvantizaci hodnot textury (nedostatek dolních bitů). Protože chceme produkovat správné zobrazované hodnoty, musíme vzít opět do úvahy standardní zobrazovací křivku. Hodnoty 16-bitové textury přepočítáme inverzní funkcí k zobrazovací křivce, tedy v’ = v1/2,2, rozdělením získáme 8-bitové textury v’0 a v‘1. Povolený rozsah hodnot e pak bude <1/2562,2, 1> a hodnotu texelu budeme počítat I (v )
1 / 2, 2
17
(
)
(
(
)
(
))
= clamp e1 / 2, 2 v' = clamp clamp e1 / 2, 2 v' 0 + clamp 256e1 / 2, 2 v'1 .
Standardní zobrazovací křivka je gamma 2,2, zachytitelný dynamický rozsah je tedy 2562,2× větší.
18
V nejnovější GeForce6 řadě grafických akcelerátorů od společnosti nVidia již nalezneme plnou podporu pro práci s daty ve formátu OpenEXR. Podle technické zprávy, kterou vytvořili Green a Cebenoyan [9], umějí karty pracovat s 32-bitovým typem float i 16-bitovým typem half. Oproti předchozím řadám karet pracují nové karty s těmito typy velmi efektivně a implementují následující operace a datové struktury: • aritmetika s plovoucí desetinnou čárkou pro veškeré matematické operace prováděné v shaderech • desetinné snímkové buffery pro ukládání vypočítaných desetinných hodnot, autoři preferují z důvodu omezené šířky pásma spíše použití typu half • desetinný blending fungující pouze s typem half umožňuje například použití algoritmů, které počítají iterativně pro každé světlo ve scéně, nebo operace využívající průhlednost • desetinné textury ve formátu OpenEXR mohou být použity k uložení všech druhů textur, autoři však radí vzhledem k paměťovým nárokům dobře zvážit, které textury je skutečně nutné uchovávat v desetinném formátu • desetinná filtrace je užitečná hlavně pro post-processing obrazu, nativní podpora této filtrace v hardware velmi zrychluje různé operace využívající k výpočtu konvoluci První počítačovou hrou, která tyto nové možnosti při tvorbě obrazu využívá, je Far Cry od společnosti Ubisoft. Podle prezentace Wenzel [10] renderuje tato hra plně v OpenEXR formátu s tím, že před zobrazením aplikuje na obraz dva filtry. Nejprve je opakovaně použito jemné rozmazání okrajů velmi světlých míst, které simuluje neschopnost oka pozorovat hranu, pokud je rozdíl světlosti jednotlivých částí příliš veliký a následně je použita globální varianta komprese podle Reinhard a kol. [1].
Obrázek 1.6: Vlevo vidíme výsledný obrázek, pokud použijeme tradiční rendering, vpravo pak obrázek vzniklý renderováním v OpenEXR formátu po aplikaci obou filtrů. Obrázky jsou převzaty z Wenzel [10].
V interaktivní aplikaci, jakou počítačová hra bezesporu je, můžeme navíc simulovat přizpůsobivost oka různým světelným podmínkám. Pokud avatar18 vyjde ze tmy do světla, chtěli bychom, aby byl množstvím světla na chvíli oslepen, když naopak vejde do temné místnosti, chceme ho nechat chvíli rozkoukávat. Tohoto efektu docílíme, pokud mírně upravíme metodu komprese. Při přepočítávání světlosti scény podle hodnoty key nahradíme průměrnou světlost scény Lavg funkcí, která se k průměrné světlosti scény pomalu přibližuje. Vneseme tak do celého procesu jistou setrvačnost. 18
Slovem avatar označujeme počítačovou reprezentaci uživatele, který vstoupil do virtuálního světa, v počítačové hře to je tedy postava, za kterou hrajeme.
19
Grafické akcelerátory od ATI v současné době formát OpenEXR nepodporují. Tyto akcelerátory implementují pro práci s HDR daty vlastní 24-bitový desetinný formát, který ale neumožňuje desetinný blending ani desetinnou filtraci. Podpora pro HDR však byla přítomna již v kartě Radeon 9700, jak ukazuje technická zpráva Mitchell [11]. Pro tuto kartu bylo v roce 2002 napsáno demo Rendering with Natural Light, které sofistikovaným způsobem renderuje HDR scénu v reálném čase. Demo využívá panoramatického HDR obrázku jako mapy okolí19 k výpočtu osvětlení syntetických objektů. Samotná vizualizace pak probíhá přes rozmazání ostrých hran přechodu světla a stínu Gaussovským filtrem a následným pořízením virtuálního snímku podle požadovaného času expozice.
Obrázek 1.7: Snímek z dema Rendering with Natural Light převzatý z [11].
19
anglicky environment map – více o panoramatických formátech naleznete v části 2.2.1
20
Kapitola 2 Panoramatické snímky 2.1 Přínos panoramatických snímků Při zachycování reality, kterou pozorujeme kolem sebe, do snímků řešíme kromě problémů s omezeným dynamickým rozsahem také problémy s omezeným zorným úhlem, který nám pořizovací zařízení respektive jeho objektiv nabízí. Tento úhel má pro běžný objektiv hodnotu pouze kolem 53°, pokud však chceme zachytit celý prostor kolem nás, potřebujeme zorný úhel 360°/180°. Problémy spojené s nedostatečným zorným úhlem snímku řeší lidé již několik desetiletí, proto jsou metody pořizování i vizualizace panoramatických snímků v současné době na velmi vysoké úrovni. Některé z těchto pořizovacích metod stručně popíšeme v části 2.2. Konkrétní podoba výsledného panoramatického snímku záleží na tom, pro jaké účely byl daný snímek pořízen. V oblasti hobby fotografie jde většinou o jednoduché širokoúhlé panoramatické snímky, kdy spojením několika málo fotografií focených s odlišným směrem pohledu při stejné úrovni horizontu získáme například pěkný pohled do krajiny. Nás však budou zajímat všesměrová panoramata, která zachycují celý 360°/180° prostor a jsou proto označována jako mapy okolí. Tato všesměrová panoramata nacházejí uplatnění například v systémech virtuální reality. Systém QTVR a jemu podobné simulují naši přítomnost ve snímaném prostoru, můžeme si interaktivně volit směr pohledu i velikost přiblížení. Mapy okolí mají v poslední době ještě jedno důležité využití. Pokročilé renderovací techniky moderních grafických karet využívají mapu okolí jako obraz vzdálené scény. Mapa okolí je v tomto případě uložena v textuře takového formátu, že ji lze adresovat směrovým vektorem. Při renderování jsou pak pro paprsky, které již neprotínají žádný objekt ve scéně, použita data z této textury podle směru daného paprsku. Modifikace této techniky využívá mapu okolí i pro výpočet lesklého osvětlení pocházejícího od vzdálených světel ve scéně. Pro střed scény je vygenerována mapa okolí, která obsahuje jednotlivá vzdálená světla, a ta je následně uložena do textury. Tato textura je pak použita ve všech místech scény jako obraz vzdálené scény, protože odchylka od přesného výpočtu je minimální. Přirozenějších výsledků dosáhneme, pokud mapu okolí negenerujeme, ale použijeme pořízený panoramatický snímek. Vzhledem k tomu, že výsledný panoramatický snímek má obsahovat obrazy světel, je potřeba, aby zachycoval velký dynamický rozsah. Tvorbou HDR panoramat se budeme zabývat v části 2.3.
21
2.2 Pořizování panoramatických snímků Klasickou metodou k pořízení panoramatického snímku je spojování snímků s odlišným směrem pohledu. Vzhledem k tomu, že zorný úhel běžného objektivu je skutečně velmi malý, potřebujeme mít na vstupu desítky fotografií. Snaha o snížení počtu potřebných fotografií vedla k vývoji netradičních metod pořizování. Dříve než se podíváme na jednotlivé metody umožňující všesměrové panoramatické snímky pořizovat, seznámíme se s formáty, ve kterých lze vzniklou mapu okolí uložit.
2.2.1
Formáty pro ukládání panoramatických snímků
Jednotlivé formáty si budeme ukazovat na panoramatu vyrenderovaném aplikací Terragen od společnosti Planetside Software. Data, která chceme uložit odpovídají 3D kulové ploše, body na ní adresujeme pomocí prostorových úhlů θ a ϕ. Základním formátem je válcová projekce dobře známá z kartografie. Úhel θ zde obíhá 2π v rovině horizontu (rovina kolmá na osu y), úhel ϕ jde shora dolů. Souřadnice bodu na obrázku dostaneme z prostorových úhlů jako u=
1 θ ϕ − , v= . 2 2π π
(15)
Obrázek 2.1: Válcová projekce – latitude/longitude.
Druhou možností je použít projekci na stříbrnou kouli. Touto projekcí získáme obrázek odpovídající odrazu scény ve stříbrné kouli. Zde úhel θ obíhá 2π v rovině pozorovatele (rovina kolmá na osu z), úhel ϕ jde zpředu dozadu. Obrázek je posunut, aby se bod [0, 0] nacházel uprostřed, souřadnice z prostorových úhlů spočítáme jako u=
sin
( )cos(θ ) + 1 , v = − sin ( )sin(θ ) + 1 . ϕ
ϕ
2
2
2
2
(16)
Tato projekce velmi deformuje části obrázku nacházející se na obvodu kruhu odpovídajícího stříbrné kouli. Proto byla zavedena alternativní projekce do úhlové mapy. Zde je mapování úhlu ϕ lineární a příslušné vzorce vypadají
22
u=
ϕ π
− πϕ sin (θ ) + 1 cos(θ ) + 1 , v= . 2 2
(17)
Obrázek 2.2: Vlevo projekce na stříbrnou kouli – mirrored ball, vpravo projekce do úhlové mapy – angular map. Je vidět, že projekce do úhlové mapy méně deformuje oblasti umístěné na obvodu kruhu.
Posledním používaným formátem je projekce na krychli. Ta se díky velmi snadné adresaci směrovým vektorem používá jako formát textury odpovídající mapě okolí v grafických akcelerátorech.
Obrázek 2.3: Projekce na krychli – vertical cross.
23
2.2.2
Netradiční metody pořizování panoramat
První z netradičních metod pořizování panoramatických snímků je fotografování scény přes stříbrnou kouli. Stříbrnou kouli umístíme na stojan do volného prostoru a fotografujeme ji ze stativu o stejné výšce jakou má stojan. Na povrchu stříbrné koule vidíme téměř celý okolní prostor, problémem zůstává pouze místo přímo za koulí, velmi zdeformovaný obraz na obvodu koule a přítomnost fotografa na snímku. Pokud použijeme postup, který navrhuje P. Debevec, pořídíme dva snímky pevně umístěné stříbrné koule s tím, že polohu fotografa změníme vzhledem ke středu koule o 90°20. Když pak formát obou snímků změníme z projekce na stříbrnou kouli na projekci do úhlové mapy a jeden z nich přitom přepočítáme tak, aby oba snímky odpovídaly stejnému směru pohledu, získáme dva snímky, které se ideálním způsobem doplňují. Na prvním snímku vidíme místa, která jsou na druhém snímku skryta za fotografem, navíc oblast poblíž obvodu kruhu vznikla přepočítáním obrazu z nezdeformovaných částí původního snímku na rozdíl od druhého snímku, kde vznikla roztažením velmi zdeformovaných obvodových dat. Naopak oblasti mezi středem a obvodem snímku jsou dobře zachyceny pouze na druhém snímku, na prvním snímku tato oblast odpovídá přepočítaným zdeformovaným obvodovým datům. K získání kvalitní mapy okolí bez fotografa a deformací tedy stačí použitím vhodné masky spojit tyto dva snímky dohromady.
Obrázek 2.4: Snímky pořídil P. Debevec, všechny operace byly prováděny v jeho aplikaci HDRShop 1.0. V levém sloupci vidíme pořízené snímky stříbrné koule, v prostředním pak tyto snímky po převodu na projekci do úhlové mapy. Prostřední horní obrázek je navíc přepočítán, aby odpovídal stejnému směru pohledu jako dolní. Vpravo nahoře vidíme masku, která slouží ke spojení upravených snímků – bílá oblast odpovídá částem převzatým z dolního a černá oblast částem převzatým z horního snímku, šedivá oblast znamená prolnutí těchto dvou snímků. Vpravo dole je pak vyobrazena výsledná mapa okolí.
20
Laickým rozumem se nabízí myšlenka, že ideální změna polohy je 180°. To však není pravda, protože části scény za koulí na prvním snímku by na druhém snímku zakrýval fotograf.
24
Druhou a více používanou alternativní metodou je pořizování snímků objektivem s velmi malou ohniskovou vzdáleností, který má v důsledku toho velmi velký zorný úhel – až 190°. Takové objektivy označujeme jako rybí oka. Při použití těchto objektivů však narážíme na dva problémy. Vzhledem k extrémním optickým vlastnostem objektivu dochází na čočce ke chromatické aberaci, kterou je nutné následně opravovat a co je horší, velmi světlé objekty, jako je například slunce, výrazně ovlivňují světlost ve svém okolí. Tyto objektivy tedy nejsou příliš vhodné pro pořizování HDR dat.
Obrázek 2.5: Tento snímek byl pořízen objektivem s velmi malou ohniskovou vzdáleností. Jasně vidíme, jak velmi světlé slunce výrazně ovlivňuje světlost ve svém okolí. Autorem snímku je J. Regester.
Snímky pořízené rybím okem lze pomocí specializovaných nástrojů převést na válcovou projekci. Pokud je zorný úhel stále nedostatečný, můžeme použít metodu popsanou v části 2.2.3 ke spojení více snímků.
2.2.3
Klasické pořizování panoramat spojováním
Jak již bylo zmíněno v úvodu části 2.2, klasickou metodou pořizování panoramatických snímků je spojování snímků s odlišným úhlem pohledu. Úhly pohledu jsou přitom voleny tak, aby pořízené snímky měly dostatečný překryv, ideální hodnota je uváděna jako 20% plochy snímku. Dalším důležitým pravidlem, které musíme při pořizování snímků pro následné spojení v panorama dodržovat, je správná rotace fotoaparátu. Aby byly zákryty různě vzdálených předmětů na všech snímcích stejné, je nutné, aby rotace probíhala kolem optického středu pořizovacího zařízení, který se většinou nalézá ve středu povrchu čočky objektivu. Za tímto účelem jsou vyráběny různé nástavce na stativ, které toto umožňují. Původní metoda využívá člověka k určení přibližné vzájemné polohy pořízených snímků a k označení odpovídajících si oblastí na dvojicích snímků. Spojení obrázků pak spočívá v určení polohy a natočení každého ze snímků na konstruované 3D kulové ploše, jedním z parametrů je také poloměr této plochy. Hodnota těchto parametrů je nalezena iterativním výpočtem, který se snaží maximálně zohlednit označené korespondence mezi snímky. 25
Pokud chceme tento proces automatizovat, musíme především navrhnout postup, jak hledat odpovídající si oblasti automaticky. Máme na výběr ze dvou možných přístupů. První pracuje s celým snímkem a snaží se vhodným posouváním jeho okraje nad jiným snímkem minimalizovat rozdíl hodnot jednotlivých překrývajících se pixelů. Kromě velice přesného nalezení korespondence však tento přístup přináší samé problémy. I pokud budeme tolerovat velkou časovou náročnost výpočtu, stále nelze nalézt korespondenci, když se obraz na snímcích liší jinak než pouhým posunutím, kdybychom například chtěli zkoušet i rotaci o malý úhel, časová náročnost výpočtu dále řádově roste. Výsledky hledání také výrazně zhoršuje případný rozdílný jas snímků. Druhý přístup spočívá v tom, že nehledáme korespondenci celých oblastí snímků, ale pouze bodů na nich. Za tyto takzvané řídící body volíme významná dobře identifikovatelná místa, například rohy jednotlivých objektů. V každém z řídících bodů spočítáme hodnotu vektoru příznaků a míru korespondence dvou řídících bodů nacházejících se na rozdílných snímcích určíme jako Eukleidovskou vzdálenost jejich vektorů příznaků. Velmi důležitá zde je vhodná volba příznaků. Tyto příznaky musejí být invariantní ke všem očekávaným transformacím a přitom dobře odlišovat jednotlivé řídící body, aby nedošlo k nalezení nesprávné korespondence. Právě riziko nalezení nesprávné korespondence je jedinou nevýhodou druhého přístupu, časová náročnost je v tomto případě přijatelná. Jeden z možných způsobů, jak plně automatizovat spojování snímků do panoramat, popisují Brown a Lowe [12]. Jejich návrh postupu při konstrukci panoramatického snímku dokonce rozpozná, které ze snímků na vstupu tvoří panorama, a ostatní snímky ignoruje. K nalezení korespondencí je použit druhý zmiňovaný přístup. Postup se skládá z několika kroků: 1) Na každém snímku je vygenerováno velké množství řídících bodů s příznaky invariantními k posunutí, rotaci, změně měřítka i k jasovým rozdílům mezi jednotlivými snímky. 2) Ke každému řídícímu bodu je nalezen určitý počet (např. 4) řídících bodů na ostatních snímcích, které k němu mají nejblíže vzhledem k hodnotám příslušných vektorů příznaků. U těchto bodů je pak nastaven příznak, že s daným řídícím bodem korespondují. 3) Ke každému snímku je nalezen určitý počet (např. 6) snímků, které obsahují nejvíce řídících bodů korespondujících s řídícími body nacházejícími se na daném snímku. Tyto snímky jsou pak označeny jako potenciální pár ke vzájemnému spojení. 4) Pro každý potenciální pár snímků je ověřena geometrická konzistence korespondujících řídících bodů. V případě, že není počet konzistentních korespondencí dostatečný, jsou zrušeny všechny korespondence řídících bodů mezi těmito dvěma snímky. Pokud je počet dostatečný, jsou zrušeny pouze korespondence, které testem nebyly prohlášeny za konzistentní. 5) Je spuštěn iterativní výpočet, který se snaží vhodným rozmístěním snímků na 3D kulovou plochu minimalizovat součet druhých mocnin geometrických vzdáleností korespondujících řídících bodů. 6) Okraje překrývajících se snímků jsou prolnuty takovým způsobem, že nevzniká ostrá hranice mezi snímky. Nyní si uvedený postup projdeme podrobněji včetně možných implementací jednotlivých kroků. Použité algoritmy nebudou popisovány do detailu, spíše bude vždy nastíněna hlavní myšlenka výpočtu, protože jejich podrobný popis je nad rámec této práce. Detailní popisy naleznete buď ve zmíněném článku, nebo v některém z článků, které zmíněný článek referencuje.
26
Řídící body s příznaky s požadovanými vlastnostmi generuje algoritmus SIFT21. Nejprve potřebujeme určit polohy řídících bodů. Teorie ukazuje, že pokud od sebe odečteme dva obrázky vzniklé konvolucí snímku s dvourozměrnými Gaussiány o různém poloměru klobouku, jsou lokální extrémy nalezené v tomto rozdílu vhodnými kandidáty na řídící body. Když navíc volíme poloměry Gaussiánů jako mocniny dvojky a spočteme rozdílové obrázky pro každé dvě sousední mocniny, můžeme považovat za sousedy daného bodu i body na stejném místě v sousedních rozdílových snímcích a extrémy tedy počítat třírozměrně – každý bod má v tomto případě 26 sousedů. Malou oblast kolem každého nalezeného řídícího bodu převedeme do nějakého standardního měřítka a standardního natočení, tím získáme invarianci ke změně měřítka, respektive k rotaci. Zbývá ještě určit vektor příznaků tak, aby byl invariantní k jasovým rozdílům. Použijeme proto místo hodnot pixelů ve standardizované oblasti hodnoty lokálních gradientů těchto hodnot. Kvůli odolnosti vůči lehkému posunutí řídícího bodu na jednotlivých snímcích zanášíme hodnoty lokálních gradientů do histogramů směrů, které sumarizují pro danou část oblasti převažující směry gradientů. Výsledný vektor příznaků pak získáme jako souhrn dat z těchto histogramů. Kvůli invarianci k velikosti gradientů ho jako poslední krok normalizujeme. Získané řídící body ukládáme do kD-stromu22 podle příslušného vektoru příznaků. Vyhledání 4 nejbližších bodů k zadanému bodu je v této datové struktuře časově náročná operace, používá se proto aproximační algoritmus BBF23. K ověření geometrické konzistence korespondujících řídících bodů slouží algoritmus RANSAC24. Ten u zkoumaného páru snímků náhodně zvolí dvě korespondence a umístí snímky tak, aby tyto korespondující body ležely na sobě. Při tomto umístění spočítá odchylky poloh ostatních korespondujících řídících bodů. Pokud se odchylka vejde do určené tolerance, je tato korespondence prohlášena za konzistentní. Když je výsledkem pouze malý počet konzistentních korespondencí, je celý test opakován pro jiný výběr dvou počátečních korespondencí, mohlo se totiž stát, že některá z původních počátečních korespondencí není konzistentní, ale pár snímků ke vzájemnému spojení je určen správně. Počet opakování testu v případě neúspěchu je závislý právě na předpokládaném počtu nekonzistentních korespondencí při správném určení páru snímků. Hledání vhodného umístění a natočení snímku na kulové ploše je vzhledem k tomu, že minimalizujeme součet druhých mocnin geometrických vzdáleností korespondujících řídících bodů, nelineární problém nejmenších čtverců, který lze řešit algoritmem Levenberg-Marquardt. Posledním krokem je správné prolnutí překrývajících se částí snímků. Jednoduchou metodou je například zavést váhovou funkci, která uprostřed snímku nabývá jedničky a směrem k okrajům snímku její hodnota klesá až na nulu. Hodnota výsledného pixelu je pak spočtena ze všech snímků, které do tohoto pixelu zasahují, jako průměr vážený touto funkcí. Toto bohužel může vést ke ztrátě vysokofrekvenční informace, pokud jsme se při určování vzájemných poloh snímků dopustili drobných chyb. Lepší je rozložit obrázky do frekvenčních pásem a nakládat s každým z těchto pásem odlišně. Vysoké frekvence prolínáme ostrým přechodem, nízké se naopak snažíme průměrovat na celých překrývajících se částech. 21
Scale Invariant Feature Transform, autorem D. Lowe kD-strom je binární vyhledávací strom pro ukládání k-rozměrných vektorů. V jednotlivých patrech se postupně mění pořadí složky vektoru, podle jejíž velikosti se v danou chvíli rozhoduje. Je vždy zvolena taková složka vektoru, ve které mají data ukládaná do příslušného podstromu největší rozptyl. 23 Best Bin First, autorem J. Beis 24 Random Sample Consensus, autorem M. Fischler 22
27
2.3 Tvorba HDR panoramat Naším cílem nyní bude navrhnout metodu, která umožní pořizovat panoramatické snímky ve formátu HDR. Jednu z představených metod pořizování panoramat lze na metodu pořizující HDR panoramata snadno rozšířit – je to fotografování scény přes stříbrnou kouli. Toto rozšíření navrhl sám P. Debevec a spočívá v tom, že dva vstupní obrázky stříbrné koule budou v HDR formátu. Toho docílíme například složením několika snímků s rozdílnými časy expozice, jak jsme o tom mluvili v části 1.2.1. Složení těchto snímků i následné operace při zpracování panoramatu lze provést v jeho aplikaci HDRShop 1.0, která je pro nekomerční účely volně dostupná, postup však není automatizovaný a vyžaduje spoluúčast uživatele při hledání korespondencí mezi dvěma HDR obrázky. Popsaná rozšířená metoda umožňuje velmi rychlé pořízení HDR panoramat, protože potřebný počet vstupních snímků je pouze dvojnásobný než požadovaný počet časů expozice. Pokud volíme rozdíl časů expozice jako dva expoziční stupně, stačí v každém ze dvou směrů pořídit kolem sedmi fotografií, celkový potřebný počet fotografií je tedy 14. Mezi nevýhody však kromě nutnosti vlastnit vhodnou stříbrnou kouli patří nízké rozlišení výsledného panoramatu. Stříbrná koule tvoří pouze kolem 60% plochy snímku, který má i při použití nejlepších cenově dostupných fotoaparátů rozlišení pouze 6Mpixelů. Velikost vzniklých panoramat je pak maximálně 2680×1340, což je vzhledem k tomu, že panorama zachycuje celý prostor kolem nás, málo. My však chceme najít metodu, která nebude vyžadovat žádné speciální vybavení a bude poskytovat větší rozlišení výsledných panoramat. Použijeme proto jako základní postup pro získání panoramat klasické spojování. Při této volbě musíme počítat s tím, že metoda bude kvůli velkému počtu vstupních snímků výrazně pomalejší. Počet různých směrů pohledu pro zachycení celého okolního prostoru běžným objektivem se blíží padesáti, při volbě sedmi různých časů expozice se dostáváme s počtem vstupních snímků k číslu 350.
2.3.1
Možnosti složení konstrukcí
Předpokládejme, že jsme pořídili množství snímků s různými směry pohledu tak, že pro každý směr pohledu máme snímky s různými časy expozice a tato sada časů je pro všechny směry stejná. Máme pak dvě možnosti, jak složit konstrukci HDR obrazu s konstrukcí panoramatického snímku. První možností je začít konstrukcí HDR obrazu.
Obrázek 2.6: Obrázek schematicky ukazuje, jak probíhá tvorba HDR panoramatu, pokud začneme konstrukcí HDR obrazů. Pro každý směr pohledu je vytvořen HDR obraz a tyto obrazy jsou následně spojeny do HDR panoramatu. HDR obraz je zde zobrazen pomocí komprese od Lischinski a kol. [6].
28
V tomto případě vytvoříme pro každý směr pohledu HDR obraz a tyto obrazy následně spojujeme do HDR panoramatu. Zmíněné pořadí složení konstrukcí přináší několik problémů. Jedním z nich je skutečnost, že spojování HDR obrazů ještě nebylo teoreticky zkoumáno a není tedy jasné, jestli například metody automatického hledání řídících bodů fungují spolehlivě i na nich. Dalším problémem je to, že HDR obraz obsahuje pouze relativní a ne absolutní informace o světlosti jednotlivých pixelů, pro kvalitní spojení bychom tedy měli také zkoušet měnit absolutní jas jednotlivých spojovaných HDR obrazů. Pokud vytváříme všechny HDR obrazy skládáním snímků se stejnou sadou časů expozice, tento problém odpadá, kdyby se nám však opravdu podařilo absolutní jas spojovaných HDR snímků vyvažovat, získali bychom metodu odolnou vůči změnám osvětlení v průběhu focení, což je vzhledem k tomu, že pořizování požadovaných 350 snímků trvá kolem hodiny, žádaná vlastnost25. Vzhledem k popsaným problémům souvisejících se spojováním HDR obrazů do HDR panoramat jsem od složení konstrukcí v tomto pořadí upustil a zkoumal jsem podrobněji druhou možnost – začít konstrukcí panoramatického snímku.
Obrázek 2.7: Obrázek schematicky ukazuje, jak probíhá tvorba HDR panoramatu, pokud začneme konstrukcí panoramat. Pro každý čas expozice je vytvořeno panorama a tato panoramata jsou následně složena do HDR panoramatu. I zde je HDR obraz zobrazen pomocí komprese od Lischinski a kol. [6].
Zde nejprve vytvoříme pro každý čas expozice panoramatický snímek a tato panoramata pak skládáme do HDR panoramatu. Vzhledem k tomu, že spojujeme pouze běžné snímky, lze ke spojení použít známé metody a existující aplikace, což nám velmi zjednoduší práci. Mezi nevýhody tohoto pořadí složení konstrukcí pak patří větší časová náročnost, protože vytváříme panorama pro každý čas expozice, a také nemožnost jednoduše bojovat proti změnám osvětlení v průběhu focení. Základním předpokladem správného složení snímků do HDR obrazu je fakt, že všechny skládané snímky obsahují ten samý obraz, pouze pořízený s různým časem expozice. Abychom toto zaručili, není možné spojovat panoramata odděleně, ale musíme všechna panoramata spojovat na základě stejných řídících bodů a jejich korespondencí. Právě hledání řídících bodů a jejich korespondencí není vůbec přímočaré. Při pořizování HDR panoramatu je velmi pravděpodobné, že scéna obsahuje velké rozdíly v množství světla – může se například jednat o pokoj, jehož jedna stěna je tvořena velkým světlým oknem, zatímco za dveřmi na jiné stěně najdeme temné zákoutí. 25
Dokonalá odolnost vůči změnám osvětlení by byla možná pouze pokud by všechny předměty ve scéně měly stejnou odrazivost. Pak bychom skutečně zesvětlením tmavého HDR obrazu získali HDR obraz více osvětlené scény. V praxi je toto bohužel nereálné.
29
Naším cílem je najít řídící body a jejich korespondence ve velmi tmavých i ve velmi světlých částech scény, toto však není pro žádný konkrétní čas expozice možné. G. Downing například radí vybrat nějaký průměrný čas expozice a použít řídící body a jejich korespondence, které jsou nalezeny ve snímcích pořízených s tímto časem expozice, část 2.3.2 však představuje zcela novou metodu, která umožňuje nalézt řídící body a jejich korespondence napříč expozičními časy.
2.3.2
Metoda využívající kompresi HDR dat
Hlavní myšlenka této metody je jednoduchá. Nebudeme hledat řídící body a jejich korespondence ve snímcích pořízených s nějakým konkrétním časem expozice, ale v obrázcích, které vzniknou kompresí HDR obrazu pro každý směr pohledu. Zvláště vhodné jsou takové metody komprese, které se snaží o rozdělení obrazu na složku odpovídající odrazivosti a na složku odpovídající osvětlení, například komprese od Lischinski a kol. [6]. Takový druh komprese totiž umí potlačit vliv osvětlení. Vše je pěkně vidět na následujícím obrázku:
Obrázek 2.8: Horní řada obsahuje dva sousední snímky pořízené se stejným časem expozice, která byla v rámci celé série snímků určena jako průměrná. Okno je při tomto čase expozice přeexponované a nelze v něm nalézt žádné řídící body, kdyby okno zabíralo celou plochu snímku, byli bychom zcela ztraceni. Spodní řada obsahuje dva obrázky vzniklé kompresí HDR obrazů pro příslušné směry pohledu. Zde jsou pokoj i okno vidět mnohem lépe a je díky tomu nalezeno větší množství korespondujících řídících bodů.
Celý postup tvorby HDR panoramat využívající tuto metodu si shrneme: 1) Vytvoříme HDR obraz pro každý směr pohledu. 2) Na vytvořené HDR obrazy aplikujeme kompresi. 3) Na obrázcích vzniklých kompresí nalezneme korespondující řídící body. 4) Původní snímky spojíme podle nalezených korespondencí do panoramat. 5) Ze vzniklých panoramat složíme HDR panorama.
30
Na základě tohoto postupu funguje aplikace HDR Panorama, která vznikla za účelem umožnit automatizovanou tvorbu HDR panoramat. Popis implementace jednotlivých kroků navrženého postupu naleznete v kapitole 3, technické detaily týkající se aplikace jako celku pak v kapitole 4.
Obrázek 2.9: HDR panorama pokoje vytvořené aplikací HDR Panorama. Vstupem byly snímky pořízené fotoaparátem Canon EOS 300D s 31 různými směry pohledu a s 12 různými časy expozice. Výsledkem je panorama zachycující horní polokouli prostoru. Předměty přilepené na stropě umožňují jednoduché automatické spojení horních snímků. Na výsledný obrázek je použita komprese od Reinhard a kol. [1].
31
Kapitola 3 Popis aplikace HDR Panorama 3.1 Modulární návrh aplikace Vzhledem k použití objektově orientovaného programovacího jazyka C# je vhodné rozdělit požadovaný výpočet do jednoduchých modulů. Podrobnější pohled na postup, který máme implementovat, ukazuje, že potřebujeme čtyři moduly, které budou provádět základní operace – pořizování, skládání, kompresi a spojování. Přidáme ještě další dva moduly pro převod a ukládání vzniklých panoramat. Přehled modulů je tedy následující: • Acquirer – modul zajišťující pořizování běžných snímků • Combiner – modul, který umí skládat z běžných snímků HDR obrazy • Tonemapper – modul komprimující HDR obrazy • Stitcher – modul, který umí spojovat běžné snímky do panoramat • Warper – modul umožňující převod panoramatických formátů • RadianceIO – modul sloužící k zápisu HDR dat do souboru Spolupráci jednotlivých modulů popisuje následující diagram. Některé moduly obsahují i datové struktury, jiné fungují pouze jako filtry.
Obrázek 3.1: Diagram popisuje spolupráci jednotlivých modulů při tvorbě HDR panoramatu. Moduly Acquirer a Stitcher obsahují i datové struktury, ostatní moduly fungují pouze jako filtry. Červené šipky znamenají toky dat, modrá šipka naznačuje, že Stitcher ke své práci potřebuje obrázky vzniklé kompresí.
32
Princip fungování aplikace HDR Panorama, určené k automatickému pořizování HDR map okolí s využitím digitálního fotoaparátu, si nyní popíšeme trochu podrobněji. Vstupem aplikace je scéna, jejíž HDR panorama chceme pořídit, výstupem potom toto panorama v některém z používaných panoramatických formátů uložené do souboru v nějakém HDR formátu. Nejprve použijeme modul Acquirer k pořízení množství snímků scény s různými směry pohledu tak, abychom pro každý směr pohledu měli snímky s různými časy expozice a tato sada časů byla pro všechny směry stejná. Tyto snímky jsou během pořizování ukládány na disk a podrobné informace o nich (čas expozice, clonové číslo, cesta k souboru, …) zapisovány do datové struktury uvnitř tohoto modulu, která umožňuje ostatním modulům tyto pořízené snímky na disku najít. Pak přicházejí ke slovu moduly Combiner a Tonemapper. Modul Combiner podle datové struktury modulu Acquirer nalezne série snímků se stejným směrem pohledu a jejich složením získá pro každý směr pohledu HDR snímek. Ten je ihned s využitím modulu Tonemapper komprimován, získáme tedy množství obrázků vzniklých HDR kompresí složených snímků. Tyto jsou také uloženy na disk a informace o nich připsány do zmíněné datové struktury modulu Acquirer spolu s informací, kterému směru pohledu daný obrázek odpovídá. Modul Stitcher, jehož výstupem jsou spojená panoramata pro každý použitý čas expozice, má relativně nejsložitější práci. Nejprve nalezne podle datové struktury modulu Acquirer obrázky vzniklé HDR kompresí a hledá na nich řídící body a jejich korespondence, pak se snaží iterativním výpočtem najít správné polohy a natočení těchto obrázků na konstruované 3D kulové ploše. V tuto chvíli nabídne uživateli možnost zasáhnout do procesu spojování a editovat polohy řídících bodů tak, aby podoba výsledného panoramatu byla co možná nejlepší. Po případném zásahu uživatele pokračuje v práci spojením původních pořízených snímků, které nalezne opět díky datové struktuře modulu Acquirer, do panoramat pro každý použitý čas expozice podle řídících bodů nalezených na obrázcích vzniklých HDR kompresí. Tato panoramata jsou následně uložena na disk a informace o nich se uchovávají v datové struktuře uvnitř tohoto modulu. Ta podobně jako datová struktura modulu Acquirer slouží především k tomu, aby další moduly uložená spojená panoramata na disku našly. Zbývá znovu použít modul Combiner a složit získaná panoramata do HDR panoramatu. Zde využijeme informace uložené v datové struktuře modulu Stitcher k nalezení spojených panoramat. Výsledné HDR panorama uložíme pouze do vnitřní datové struktury aplikace, uložení na disk totiž není triviální a vyžaduje spolupráci s modulem RadianceIO. Volitelné je použití modulu Warper. Ten předpokládá, že vzniklé HDR panorama je ve formátu válcové projekce a umožňuje jej převádět do jiného panoramatického formátu, například do projekce na stříbrnou kouli, projekce do úhlové mapy nebo projekce na krychli. Při tomto převodu lze také určit požadovanou velikost výsledného HDR panoramatu. Posledním krokem je uložení HDR panoramatu do souboru s využitím modulu RadianceIO. Tento modul odpovídající nějakému HDR formátu čte HDR panorama z vnitřní datové struktury aplikace (případně z výstupu modulu Warper) a konvertuje čtená data do podoby, ve které mohou být na disk uložena, například do jednoduchého formátu RGBE nebo do složitějšího OpenEXR. Po skončení výpočtu jsou s využitím datových struktur modulů Acquirer a Stitcher smazána z disku všechna dočasná data včetně pořízených snímků a spojených panoramat.
33
Modulární návrh má kromě přehlednosti zápisu výpočtu ještě jednu podstatnou výhodu, umožňuje nám totiž navrhnout rozhraní pro jednotlivé moduly a následně vytvořit množství implementací každého z nich. Můžeme takto použít pro každou ze základních operací různé metody a porovnávat, která poskytuje lepší a která horší výsledky z hlediska kvality výsledného panoramatu či z hlediska času potřebného k jeho výrobě. V současné době má každý modul pouze jedinou implementaci odpovídající nějaké jednoduché metodě, navržené modulární prostředí je však plně připraveno k dopsání dalších implementací. Následující části obsahují kromě popisu jednotlivých navržených rozhraní také popis jejich současné implementace. Kuchařku k přidání další implementace modulu naleznete v části 4.6.
3.2 Acquirer – pořizování snímků Rozhraní pro pořizovací zařízení musí především umožňovat zjistit seznam vhodných k počítači připojených zařízení, připojit se k jednomu z těchto zařízení a následně se od něj zase umět odpojit. Dále je nutné zjistit možné hodnoty časů expozice, clonového čísla a dalších parametrů zařízení, tyto hodnoty je také potřeba nastavovat a zjišťovat jejich nastavení. V neposlední řadě musí rozhraní umožňovat pořídit snímek a uložit ho do souboru. Rozhraní HDRPanorama.Acquirer.IAcquirer obsahuje následující vlastnosti a metody: • ArrayList Connect(handle) – inicializuje pořizovací modul a vrací seznam připojených pořizovacích zařízení, se kterými umí tento modul pracovat, v parametru dostává kontextový handle aplikace • void StartDevice(device) – připojí se ke zvolenému zařízení • void StopDevice() – odpojí se od zařízení • void Disconnect() – deinicializuje pořizovací modul • • • • • • • • • •
void GetImageFormatList(list) – zjistí možné hodnoty formátu pořizovaného snímku a uloží je do seznamu object ImageFormat – nastavuje a zjišťuje nastavenou hodnotu formátu pořizovaného snímku void GetWhiteBalanceList(list) – zjistí možné hodnoty vyvážení bílé pořizovaného snímku a uloží je do seznamu object WhiteBalance – nastavuje a zjišťuje nastavenou hodnotu vyvážení bílé pořizovaného snímku void GetISOSpeedList(list) – zjistí možné hodnoty citlivosti ISO pořizovaného snímku a uloží je do seznamu object ISOSpeed – nastavuje a zjišťuje nastavenou hodnotu citlivosti ISO pořizovaného snímku void GetApertureValueList(list) – zjistí možné hodnoty clonového čísla pořizovaného snímku a uloží je do seznamu object ApertureValue – nastavuje a zjišťuje nastavenou hodnotu clonového čísla pořizovaného snímku void GetShutterSpeedList(list) – zjistí možné hodnoty času expozice pořizovaného snímku a uloží je do seznamu object ShutterSpeed – nastavuje a zjišťuje nastavenou hodnotu času expozice pořizovaného snímku
34
• • • • • • • •
3.2.1
bool Release(path) – pořídí snímek s nastavenými hodnotami parametrů zařízení, uloží ho do souboru a vrací příznak, zda se pořízení podařilo bool HDRRelease() – pořídí sérii snímků s různými časy expozice pro konstrukci HDR obrazu, uloží je do souborů a vrací příznak, zda se pořízení celé série podařilo ShotImages ShotImages – vrací datovou strukturu reprezentující pořízené série snímků void DeleteImages() – smaže všechny pořízené série snímků a další dočasná data tohoto modulu ArrayList GetStep1ShutterSpeedList(), ArrayList GetStep2ShutterSpeedList(), void InsertIntoShutterSpeedList(list, shutterSpeed), ArrayList HDRShutterSpeeds – tyto tři metody a jedna vlastnost slouží k výběru expozičních časů pořizovaných sérií snímků pro konstrukci HDR obrazu, o způsobu výběru těchto časů hovoří část 4.2.1
Spolupráce s fotoaparátem Canon EOS
Jediná implementace tohoto rozhraní HDRPanorama.Acquirer.CanonEOSAcquirer umožňuje práci s fotoaparáty Canon třídy EOS. Pro komunikaci s fotoaparátem je použito Canon RC-SDK v8.3, které není volně k dispozici, ale pro přístup k němu musíte vstoupit do Canon programu pro vývojáře. Soubory tohoto SDK určené k distribuci s aplikací však volně dostupné jsou, celé SDK potřebujeme pouze ke kompilaci aplikace, kdy musejí být uloženy v kořenovém adresáři. Při implementaci jsem použil velmi pěkný C# wrapper, jehož autorem je E. Torres. Kód si však vyžádal určité úpravy, protože původní wrapper je psán pro CD-SDK, které spolupracuje s klasickými fotoaparáty Canon. Tento upravený wrapper je do aplikace přidán jako projekt CanonEOS, jeho hlavní třída CanonEOS.Camera je virtuální reprezentací fotoaparátu, ostatní třídy definují konstanty a typy používané v SDK a importy všech funkcí, které SDK nabízí. Kvůli ukládání pořízených snímků do souboru je do aplikace přidán ještě C++ projekt CanonEOSSDK. Pokud použijeme takto upravený wrapper, samotná implementace rozhraní modulu pořizovače je pak velmi jednoduchá. Jednotlivá volání metod rozhraní jsou převáděna na volání odpovídajících metod instance třídy CanonEOS.Camera. Korespondence mezi konstantami SDK pro hodnoty jednotlivých parametrů fotoaparátu a jejich textovými reprezentacemi v aplikaci jsou drženy pomocí několika (jednou pro každý parametr) obousměrných hašovacích tabulek CoolMan.Collections.BidirHashtable, které navrhl T. Gleason. Pořízené snímky s různými časy expozice pro následnou konstrukci HDR obrazu jsou ukládány do souborů v adresářích, jejichž jména odpovídají jednotlivým expozičním časům, jména souborů jsou zase určena podle příslušnosti snímku k nějaké sérii snímků. Informace o tom jaké snímky byly pořízeny a kam byly uloženy se uchovávají v instanci třídy HDRPanorama.Data.ShotImages, která bude podrobně popsána v příští kapitole. Implementace také obsahuje soukromou statickou metodu pro výpočet expozice snímku ze zadaného času expozice a clonového čísla. Tato funkce je využívána ke správnému třídění expozičních časů a clonových čísel, navíc je získaná hodnota expozice použita při skládání série snímků do HDR obrazu.
35
3.3 Combiner – skládání do HDR obrazu Rozhraní HDRPanorama.Combiner.ICombiner pro modul, který bude zajišťovat skládání snímků do HDR obrazu, je velmi jednoduché a obsahuje jedinou metodu. Skládání probíhá iterativně, uvedená metoda je postupně volána pro každý snímek v sérii snímků: • void Combine(width, height, alphaChannel, redBuffer, greenBuffer, blueBuffer, inputImage) – vezme zadaný vstupní snímek a složí ho s dosavadním HDR obrazem, HDR obraz je uložen rozložený do jednotlivých kanálů, mezi další parametry metody patří šířka a výška skládaného HDR obrazu Jednotlivé implementace tohoto rozhraní se pak budou lišit použitou charakteristickou křivkou zařízení, která určuje převod hodnot pixelů na hodnoty expozice, a metodou, jak určovat hodnotu ozáření, pokud lze k jejímu výpočtu použít hodnoty pixelů z více snímků.
3.3.1
Skládání pomocí gamma křivky
Třída HDRPanorama.Combiner.GammaCombiner je jednoduchou implementací tohoto rozhraní. Jako charakteristickou křivku zařízení používá gamma křivku, hodnota gamma je nastavena v konstruktoru, doporučovanou hodnotou je 2,2. Z důvodu maximální snahy o rychlost výpočtu jsou hodnoty křivky pro jednotlivé možné hodnoty pixelu předpočítány. K určení hodnoty ozáření, pokud lze k jejímu výpočtu použít hodnoty pixelů z více snímků, je použit lehce modifikovaný vážený průměr. V konstruktoru jsou nastaveny minimální a maximální použitelná hodnota pixelu a průměr je počítán pouze z pixelů, jejichž hodnota do tohoto rozmezí padne. Vrchol střechy tohoto váženého průměru je umístěn doprostřed mezi minimální a maximální použitelnou hodnotu. Volba minimální a maximální použitelné hodnoty pixelu umožňuje eliminovat zkreslené hodnoty pixelů na okrajích křivky, doporučovanými hodnotami této minimální a maximální použitelné hodnoty pixelu je 6, respektive 248.
Obrázek 3.2: Levý graf ukazuje průběh gamma křivky pro hodnotu gamma rovnou 2,2, pravý graf zase průběh váhové funkce pro minimální použitelnou hodnotu 6 a maximální použitelnou hodnotu 248.
Barevné kanály jsou skládány odděleně, alfa kanál není skládán tímto způsobem. Předpokládá se, že případná průhlednost všech skládaných snímků je stejná, hodnota alfa kanálu je tedy převzata z jednoho ze vstupních snímků. 36
3.4 Tonemapper – komprese HDR obrazu Pro modul zajišťující v aplikaci kompresi HDR obrazů definujeme rozhraní HDRPanorama.Tonemapper.ITonemapper. Ani toto rozhraní není složité a také obsahuje pouze jednu metodu: • Bitmap Tonemap(width, height, alphaChannel, redBuffer, greenBuffer, blueBuffer) – provede kompresi zadaného HDR obrazu a výsledek vrátí jako klasickou bitmapu, HDR obraz je zadán rozložený do jednotlivých kanálů, mezi další parametry metody patří šířka a výška komprimovaného HDR obrazu Zde se budou jednotlivé implementace lišit použitou metodou komprese. Jak již bylo zmíněno v části 2.3.2, zvláště vhodné jsou metody, které se snaží o rozdělení obrazu na složku odpovídající odrazivosti a na složku odpovídající osvětlení.
3.4.1
Logaritmická komprese
Do třídy HDRPanorama.Tonemapper.LogTonemapper byla implementována globální metoda logaritmické komprese, která pracuje se světlostí pixelů. Alfa kanál prochází kompresí beze změny. Pro místa, kde je hodnota světlosti nulová a nejde zlogaritmovat, je zvolena minimální světlost přítomná na obrázku. Po úspěšném zlogaritmování je obraz uniformně namapován na interval <0, 255> tak, že hodnotě 0 odpovídá minimální a hodnotě 255 maximální dosažená hodnota logaritmu, rozsah běžného obrázku je tedy plně využit. Barevnost obrazu je obnovena metodou popsanou v části 1.3, hodnota požadované barevné sytosti se nastavuje v konstruktoru, doporučovanou hodnotou je 0,4.
Obrázek 3.3: Princip logaritmické komprese. HDR obraz je nejprve převeden na černobílý HDR obraz. Ten je zlogaritmován a uniformně namapován do klasické bitmapy. Následně je metodou popsanou v části 1.3 obnovena barevnost obrazu se sytostí rovnou 0,4. HDR obraz zde reprezentují běžné snímky.
37
Implementovaná metoda sice nepatří mezi metody, které se snaží o rozdělení obrazu na složku odpovídající odrazivosti a na složku odpovídající osvětlení, přesto je pro naše potřeby dostačující díky tomu, že použijeme při spojování do panoramatu řídící body s příznaky invariantními k jasovým rozdílům a nevadí tedy i velmi rozdílný jas jednotlivých vzniklých obrázků.
3.5 Stitcher – spojování do panoramatu Naším cílem bylo navrhnout celý postup tak, aby byl plně automatický a nevyžadoval žádné zásahy ze strany uživatele. Správné spojování panoramat je však natolik obtížné, že je dobré ponechat uživateli možnost zkontrolovat navrhovaná napojení a v případě špatného napojení i přidat řídící body a jejich korespondence. Rozhraní HDRPanorama.Stitcher.IStitcher obsahuje následující vlastnosti a metody: • void PreStitch(shotImages) – spustí operace prováděné před případným zásahem uživatele, jedná se především o automatické generování řídících bodů, hledání jejich korespondencí a o vytvoření projektu s panoramatem, v parametru dostává pořízené série snímků • void StitchingTool() – otevře projekt s panoramatem, umožní uživateli zkontrolovat navrhovaná napojení a v případě špatného napojení i přidat řídící body a jejich korespondence • void PostStitch(shotImages) – spustí operace prováděné po případném zásahu uživatele, zde se jedná především o spojení panoramat pro každý čas expozice podle vytvořeného projektu s panoramatem, v parametru dostává pořízené série snímků • InputImages PanoramaImages – vrací datovou strukturu reprezentující spojená panoramata • void DeleteImages() – smaže všechna spojená panoramata a další dočasná data tohoto modulu Jednotlivé implementace tohoto rozhraní mohou být naprosto odlišné. Stejný musí zůstat pouze princip, že z pořízených snímků se za pomoci obrázků vzniklých kompresí HDR obrazů vytvoří panoramata pro každý čas expozice a že ve vhodnou chvíli umožníme uživateli proces korigovat.
3.5.1
Program Hugin
Existuje množství aplikací, které umožňují lépe či hůře spojovat snímky do všesměrových panoramat. Většina z těchto aplikací je komerčních, existují však také open source aplikace vyvíjené pod licencí GNU. Vzhledem k náročnosti tohoto kroku výpočtu jsem se rozhodl jednu z nich použít. Lepší než zdrojový kód takové aplikace do mé aplikace jako další projekt zahrnout je tuto aplikaci z mé aplikace volat. Takto je pak možné například nahradit aplikaci její novou verzí bez nutnosti rekompilace. Použitou open source aplikací je Hugin26, který pro svou práci potřebuje další open source utility. Ke generování řídících bodů a k hledání jejich korespondencí slouží Autopano-SIFT27, iterativní výpočet, který se snaží vhodným rozmístěním snímků na 3D kulovou plochu minimalizovat vzdálenosti korespondujících řídících bodů obstarává Libpano1228, hezké prolínání okrajů překrývajících se snímků zajišťuje Enblend29. 26
verze 0.5, autorem Pablo d’Angelo verze 2.3, autorem Sebastian Nowozin 28 verze 2.7, autorem Helmut Dersch 29 verze 2.3, autorem Andrew Mihal 27
38
Spojování do panoramatu využívající aplikaci Hugin je implementováno ve třídě HDRPanorama.Stitcher.HuginStitcher. Vytváření panoramatu začíná generováním řídících bodů pro každý obrázek algoritmem SIFT. K tomu slouží volání generatekeys.exe image output.key [minDim],
parametr minDim určuje, od jakého rozlišení obrázku má generování začínat, v našem volání za něj dosazujeme šířku obrázku. Generování je pak poměrně pomalé, ale poskytuje výborné výsledky. Potom jsou použitím aproximačního algoritmu BBF nalezeny mezi řídícími body korespondence a jejich geometrická konzistence je následně ověřena algoritmem RANSAC. Tyto operace včetně vytvoření projektu s panoramatem zajišťuje volání autopano.exe [options] output.pto keys1.xml keys2.xml ..
ve kterém použijeme jako parametry --maxmatches <matches> a --align. První parametr určuje, kolik korespondencí mezi dvěma obrázky má být zachováno. Pro plně automatické spojování je dobré zvolit toto číslo velké, pokud však chceme do tvorby panoramatu ručně zasahovat, potřebujeme kvůli zvětšení váhy námi přidávaných korespondencí toto číslo snížit. Hodnota maximálního počtu zachovávaných korespondencí se nastavuje v konstruktoru, doporučená hodnota je 10. Druhý parametr umožní v případě, že skupina obrázků ke spojení začíná posloupností obrázků v rovině horizontu (a takto většinou fotíme), výpočet přibližných poloh obrázků na kulové ploše a usnadní tak práci optimalizátoru provádějícímu ke zjištění přesných poloh iterativní výpočet. Vytvořený projekt s panoramatem je uložen do souboru ve formátu pto, jemuž Hugin rozumí. Další z volaných utilit, která iterativním výpočtem určuje polohu a natočení obrázků na konstruované 3D kulové ploše, používá tento projekt jako svůj vstup i výstup, je proto nutné umět soubory v tomto formátu editovat, abychom mohli nastavovat parametry volání optimalizátoru PTOptimizer.exe panorama.pto
tak, jak potřebujeme. Podrobný popis formátu pto najdete v dodatku B, zde si vystačíme s intuitivním popisem, co v souboru nastavujeme. Do souboru je především nutné zapsat požadovanou velikost panoramatu. Šířka panoramatu se nastavuje v konstruktoru, experimentálně zjištěný nejlepší poměr mezi velkým rozlišením a časem výpočtu dává hodnota 576530, výška panoramatu je vzhledem k tomu, že generujeme panorama ve tvaru odpovídajícím válcové projekci, poloviční. Dále je potřeba do souboru zadat, které parametry chceme optimalizovat. K získání ideálních poloh a natočení obrázků je totiž také možné zkoušet měnit odhad intrinsických parametrů pořizovacího zařízení, jako například úhlu pohledu, zkreslení čočky nebo posunu středu snímacího čipu od jeho průsečíku s optickou osou objektivu. Není vhodné hned od začátku dovolit optimalizátoru měnit hodnoty odhadů těchto parametrů, protože by se lehce mohlo stát, že by je iterativní výpočet ve snaze zmenšit vzdálenost korespondencí špatně umístěných obrázků změnil velmi razantním způsobem. Při prvním volání tedy optimalizujeme pouze polohy a natočení. 30
Tato velikost odpovídá při použití běžného objektivu rozlišení vstupních snímků 800×600. Typicky budou mít vstupní snímky rozlišení větší, nehrozí tedy vznik artefaktů přílišným zvětšením vstupních dat.
39
Teď přichází vhodná chvíle k zásahu uživatele. Otevřením projektu s panoramatem v aplikaci Hugin umožníme uživateli editovat řídící body a jejich korespondence.
Obrázek 3.4: Hugin – editace řídících bodů.
Polohu uživatelem zadaných korespondujících řídících bodů Hugin svým vnitřním výpočtem dále zpřesňuje, nemusíme se tedy bát, že přibližným zadáním korespondencí tvorbu panoramatu pokazíme. Je také možné průběžně spouštět z aplikace optimalizaci a kontrolovat podobu vznikajícího panoramatu.
Obrázek 3.5: Hugin – náhled panoramatu.
40
Po ukončení případných úprav projektu s panoramatem voláme pro případ, že to neudělal sám uživatel, opět optimalizaci, nyní dokonce dvakrát. Při prvním volání optimalizujeme pouze polohy a natočení, při druhém dovolíme pro zlepšení napojení měnit i odhady intrinsických parametrů. V projektu s panoramatem jsou zapsány plné cesty k souborům s obrázky, které mají být spojeny. V této chvíli cesty odpovídají obrázkům vzniklým kompresí HDR obrazů pro jednotlivé směry pohledu. Pro každý použitý čas expozice tedy nahradíme tyto cesty cestami k pořízeným snímkům s tímto časem expozice a s odpovídajícím směrem pohledu a spojení provedeme voláním nona [options] -o output project_file,
formát výsledku zvolíme nastavením uvnitř projektu s panoramatem na „multiple tiff files“, protože tento formát potřebujeme k závěrečnému kroku. Je tedy vytvořeno tolik obrázků, kolik je směrů pohledu, každý z nich má velikost výsledného panoramatu a je průhledný všude kromě místa, kde je umístěný správně zdeformovaný snímek pro daný směr pohledu. Závěrečným krokem je správné prolnutí překrývajících se částí snímků. Zde je použita metoda zohledňující vyskytující se frekvence. Místa obsahující nízké frekvence jsou prolínány přes široké oblasti, místa s převahou vysokých frekvencí naopak přes oblasti velmi úzké. K provedení tohoto prolnutí voláme enblend [options] -o OUTPUT INPUTS
s parametry –a, který minimalizuje paměťové nároky spojením nepřekrývajících se snímků, –w, který oznamuje, že se jedná o všesměrové panorama a –z, který zapíná kompresi výsledného obrázku.
3.6 Warper – převod panoramatických formátů Vyrobené panorama je vždy ve formátu válcové projekce, ocenili bychom tedy možnost toto panorama převádět do dalších panoramatických formátů. K tomu slouží inverzní filtrace s přepočtem přes 3D souřadnice na kulové ploše, na kterou všesměrové panorama promítáme. 2D souřadnice bodu na obrázku ve formátu, který chceme získat, převedeme s využitím vzorců uvedených v části 2.2.1 do 3D souřadnic a tyto následně do 2D souřadnic existujícího obrázku ve formátu válcové projekce. Výsledné desetinné 2D souřadnice padnou do čtverce určeného nějakými čtyřmi body existujícího obrázku, výslednou hodnotu pixelu určíme buď jako hodnotu pixelu v nejbližším z těchto bodů nebo bilineární interpolací hodnot pixelů ve všech těchto čtyřech bodech.
Obrázek 3.6: Převod panoramatických formátů. 2D souřadnice bodu jsou převedeny do 3D souřadnic na kulové ploše a tyto následně do 2D souřadnic existujícího obrázku. 2D souřadnice padnou do čtverce určeného čtyřmi body, hodnotu pixelu určíme třeba bilineární interpolací hodnot pixelů v těchto bodech.
41
Pro převod 2D souřadnic nějakého formátu do příslušných 3D souřadnic definujeme rozhraní HDRPanorama.Warper.IWarper. Toto rozhraní obsahuje pouze jednu metodu a jednu vlastnost: • bool Warp(u, v, out x, out y, out z) – převede zadané 2D souřadnice příslušného panoramatického formátu do 3D souřadnic, vrací příznak, zda zadaná 2D souřadnice leží v platné oblasti obrázku vzhledem k použitému formátu (toto je užitečné pro neobdélníkové formáty) • double AspectRatio – vrací poměr mezi šířkou a výškou obrázku v příslušném panoramatickém formátu V aplikaci nalezneme tři různé implementace tohoto rozhraní pro tři další základní panoramatické formáty: • HDRPanorama.Warper.MirroredBallWarper – převádí do formátu projekce na stříbrnou kouli, poměr šířky a výšky je 1, oblast mimo kruh je neplatná • HDRPanorama.Warper.AngularMapWarper – převádí do formátu projekce do úhlové mapy, poměr šířky a výšky je 1, oblast mimo kruh je neplatná • HDRPanorama.Warper.VerticalCrossWarper – převádí do formátu projekce na krychli, poměr šířky a výšky je 3/4, oblast mimo šest stěn krychle je neplatná Velikost výsledného panoramatu nezávisí na velikosti zdrojového existujícího panoramatu a je parametrem převodu.
3.7 RadianceIO – vstup a výstup HDR dat Modul pro vstup a výstup HDR dat zajišťuje ukládání a načítání souborů31 obsahujících HDR data. Jeho rozhraní HDRPanorama.RadianceIO.IRadianceIO tvoří následující metody: • void Write(width, height, alphaChannel, redBuffer, greenBuffer, blueBuffer) – uloží zadaný HDR obraz do souboru, HDR obraz je zadán rozložený do jednotlivých kanálů, mezi další parametry metody patří šířka a výška ukládaného HDR obrazu • void Read(out width, out height, out alphaChannel, out redBuffer, out greenBuffer, out blueBuffer) – provede načtení HDR obrazu ze souboru, v parametrech vrátí HDR obraz rozložený do jednotlivých kanálů, dále vrátí i šířku a výšku načteného HDR obrazu Jméno souboru, do kterého jsou data ukládána nebo ze kterého jsou čtena, je nastaveno v konstruktoru jednotlivých implementací. V aplikaci jsou vytvořeny dvě implementace tohoto rozhraní – jedna pracuje s formátem RGBE, druhá umožňuje práci s formátem OpenEXR. K práci se soubory ve formátu RGBE slouží první implementace tvořená třídou HDRPanorama.RadianceIO.RGBERadianceIO. Vlastní C knihovna pro práci s tímto formátem, kterou napsali B. Walter a G. Ward, je vložena do C++ projektu RGBE spolu s wrapperem umožňujícím přístup k této knihovně z jazyka C#. Volání jednotlivých metod rozhraní je převáděno na volání statických metod třídy RGBE.RGBEFile. Jediný problém, který musíme řešit, je převod našich vnitřních dat do formátu vhodného pro knihovnu. Datový typ používaný knihovnou je float[3], při ukládání dat jsou všechny barevné kanály přenásobeny alfa kanálem, při čtení dat je hodnota alfa kanálu nastavena ve všech bodech na jedničku.
31
Načítání HDR dat není nikde v aplikaci použito, bylo využíváno pouze během vývoje aplikace.
42
Třída HDRPanorama.RadianceIO.OpenEXRRadianceIO je druhou implementací umožňující zápis a čtení souborů ve formátu OpenEXR. Zde byla použita volně dostupná knihovna OpenEXR v1.2.2 od Industrial Light & Magic, Lucasfilm Ltd. Ta byla vložena do C++ projektu OpenEXR také spolu s příslušným wrapperem zprostředkovávajícím přístup z jazyka C#. Volání jednotlivých metod rozhraní je převáděno na volání statických metod třídy OpenEXR.OpenEXRFile. Pro kompilaci aplikace je potřeba tuto knihovnu umístit do kořenového adresáře. Převod vnitřních dat do formátu vhodného pro knihovnu je zde o něco obtížnější. Knihovna používá datový typ Imf.Rgba obsahující 4 čísla typu half, který je aplikaci neznámý. Převod do něj a z něj probíhá voláním dalších statických metod třídy OpenEXR.OpenEXRFile. Přestože knihovna OpenEXR umožňuje ukládání dat ve velice sofistikovaných formátech, nám plně postačuje pracovat s obyčejnými RGBA daty typu half a se sekvenčními soubory bez podpory více rozlišení a metadat. Proto implementace používá pouze základní rozhraní této knihovny.
43
Kapitola 4 Dokumentace k HDR Panorama 4.1 Vnitřní datové struktury Datové struktury využívané aplikací HDR Panorama jsou umístěny v namespace HDRPanorama.Data. Nebudeme zde popisovat všechny použité datové struktury, pouze dvě nejdůležitější a některé další, které jsou jejich součástí. Naším cílem také není popisovat všechny vlastnosti a metody těchto tříd, podrobný strukturovaný popis všech tříd aplikace lze totiž nalézt v automaticky generovaném souboru nápovědy Documentation.chm přiloženém k aplikaci.
4.1.1
ShotImages
HDRPanorama.Data.ShotImages je datová struktura reprezentující pořízené série snímků. Je to pouze kolekce instancí třídy HDRPanorama.Data.InputImages, která reprezentuje jednu pořízenou sérii snímků odpovídající jednomu směru pohledu. Pro tuto sérii jsou implementovány následující vlastnosti a metoda: • InputImageList Images – vrací seznam snímků v této sérii • InputImage TonemappedImage – vrací obrázek získaný kompresí HDR obrazu vzniklého z této série snímků, ten není nastaven hned při pořízení série snímků ale až později v průběhu výpočtu • bool Deleted – vrací příznak, zda má být tato série použita při stavbě HDR panoramatu, důvodem k nepoužití série může být přerušení pořizování série nebo ruční vyřazení, jak o tom bude řeč v části 4.2.2 • RadianceBuffer Combine(combiner) – složí z této série snímků HDR obraz s využitím zadané implementace modulu Combiner a vrátí ho Datová struktura HDRPanorama.Data.InputImageList je pouze kolekce instancí třídy HDRPanorama.Data.InputImage, která reprezentuje jeden pořízený snímek. Mezi její vlastnosti a metody patří: • string Path – vrací cestu ke snímku na disku • object ShutterSpeed – vrací čas expozice snímku • object ApertureValue – vrací clonové číslo snímku • float Exposure – vrací spočtenou expozici snímku • int Width – vrací šířku snímku • int Height – vrací výšku snímku • float ViewAngle – vrací spočtený zorný úhel snímku
44
•
void Load() – načte snímek z disku do paměti a umožní tím přístup k jeho jednotlivým pixelům • Color GetPixel(x, y) – pro zadanou polohu vrací hodnotu pixelu snímku, snímek musí být při volání této metody načten do paměti, tato metoda je volána při skládání snímků do HDR obrazu • void UnLoad() – uvolní snímek z paměti Tato třída má také tři různé konstruktory. Bezparametrový konstruktor pro umožnění XML serializace, konstruktor s množstvím parametrů nastavující všechny vlastnosti a pak konstruktor s parametry cesta ke snímku, čas expozice, clonové číslo a expozice pro použití po pořízení snímku. V tomto konstruktoru je z pořízeného snímku voláním open source utility Jhead32 jhead.exe [options] files
s parametrem –c získána stručná podoba EXIF dat, která je následně přeparsována pro zjištění šířky a výšky obrázku, údaj o ohniskové vzdálenosti je použit k výpočtu zorného úhlu snímku.
4.1.2
RadianceBuffer
Datová struktura HDRPanorama.Data.RadianceBuffer je vnitřní reprezentací HDR obrazu. Definujeme pro ni následující vlastnosti a metody: • int Width – vrací šířku HDR obrazu • int Height – vrací výšku HDR obrazu • void Save(fileName) – voláním metody vhodné implementace modulu RadianceIO uloží HDR obraz do souboru, vhodná implementace je vybrána na základě přípony zadaného jména cílového souboru • void Combine(combiner, inputImage) – voláním metody zadané implementace modulu Combiner složí zadaný vstupní snímek s dosavadním HDR obrazem • Bitmap Tonemap(tonemapper) – voláním metody zadané implementace modulu Tonemapper provede kompresi HDR obrazu a vrací výsledek v podobě běžné bitmapy • RadianceBuffer Warp(warper, panoramaSize, bilinear) – voláním metody zadané implementace modulu Warper převádí HDR obraz do jiného panoramatického formátu, podle zadaného příznaku provádí ve zdrojovém HDR obrazu bilineání interpolaci nebo hledání nejbližšího souseda, dalším zadaným parametrem je šířka vzniklého panoramatu, výška se získává z poměru mezi šířkou a výškou cílového formátu, vrací převedený HDR obraz I u této třídy najdeme více konstruktorů, klasický s parametry šířka a výška, který vytvoří prázdný HDR obraz zadaných rozměrů a druhý s parametrem cesta k souboru. Ten vytvoří HDR obraz jeho načtením z tohoto souboru, vhodná implementace modulu RadianceIO je vybrána na základě přípony zadaného jména zdrojového souboru. HDR obraz je uchováván rozložený do jednotlivých barevných kanálů a alfa kanálu. Alfa kanál je uložen v instanci třídy HDRPanorama.Data.AlphaChannel, která je implementována jako dvojrozměrné pole typu float. Ukládání barevných kanálů je však složitější. 32
verze 2.4, autorem Matthias Wandel
45
Každý barevný kanál je uložen v instanci třídy HDRPanorama.Data.ChannelBuffer, tyto instance však sdílejí instanci třídy HDRPanorama.Data.RadianceExtremes k výpočtu maximální a minimální hodnoty napříč kanály. Zjištění maximální hodnoty je potřebné k normování hodnot HDR obrazu do intervalu <0, 1>, minimální hodnota je zase užitečná pokud obraz chceme zlogaritmovat. Vlastní uložení kanálových dat se skládá z jedné položky typu float, jedné položky typu int a jedné položky typu bool. To je způsobeno faktem, že výsledná hodnota dat se získává váženým aritmetickým průměrem. Položka typu float obsahuje součet hodnot a položka typu int jejich počet, hodnota se získá podílem. Pokud je položka typu int nulová, zvolí se 0 nebo 1 podle hodnoty položky typu bool.
4.2 Dialogy aplikace 4.2.1
Výběr časů expozice pro pořizování HDR dat
Při pořizování série snímků pro následné spojování do HDR obrazu postupně měníme čas expozice pořizovaných snímků. K volbě použité množiny expozičních časů slouží dialog HDRPanorama.ShutterSpeedsDialog.
Obrázek 4.1: Dialog s výběrem časů expozice pro pořizování HDR dat.
Uživatel v dialogu vybírá z nabízených časů expozice ty, které chce použít při pořizování HDR dat. Aby bylo vybírání pohodlné, je nutné, aby seznam časů byl setříděný. Uživatel navíc často nechce přemýšlet nad tím, jaké expoziční časy použít, pouze ví, že chce pořizovat s rozdílem jeden nebo dva expoziční stupně. Pro tyto dvě možnosti jsou tedy připraveny dvě přednastavené množiny expozičních časů. K implementaci takového chování do tohoto dialogu jsou využity tři výše zmíněné metody a jedna vlastnost modulu Acquirer: • ArrayList GetStep1ShutterSpeedList() – vrací přednastavený seznam časů expozice pro rozdíl jeden expoziční stupeň • ArrayList GetStep2ShutterSpeedList() – vrací přednastavený seznam časů expozice pro rozdíl dva expoziční stupně • void InsertIntoShutterSpeedList(list, shutterSpeed) – zatřídí zadaný čas expozice do zadaného seznamu • ArrayList HDRShutterSpeeds – vrací seznam obsahující vybrané časy expozice 46
4.2.2
HDR Manager
Během pořizování sérií snímků i po něm potřebujeme mít kontrolu nad tím, jaké série snímků (a fotky v nich) jsme již pořídili a jak se povedly. K tomu slouží dialog HDRPanorama.HDRManager.
Obrázek 4.2: Dialog HDR Manager.
V levé části dialogu zvolíme jednu z pořízených sérií a v pravé části se nám v instancích třídy HDRManager.ImagePreview zobrazují náhledy jednotlivých snímků z této série spolu s informacemi o velikosti, zorném úhlu, času expozice a clonovém čísle daného snímku. Dialog také umožňuje zvolenou sérii snímků smazat a tím ji vyřadit z tvorby HDR panoramatu, což je užitečné, pokud se některý ze snímků v této sérii nepovedl. Kvůli zachování číselné řady pořizovaných sérií je u této série pouze nastaven příznak, že je smazaná, pořízené snímky jsou však z důvodu úspory místa z disku odstraněny, obnovení smazané série tedy není možné.
4.2.3
Options dialog
Třída HDRPanorama.OptionsDialog je implementací dialogu s možnostmi aplikace. Celý dialog pracuje nad datovou strukturou obsahující nastavení aplikace, která bude popsána v souvislosti s ukládáním nastavení aplikace v části 4.4.
4.2.4
About dialog
Klasický dialog „O aplikaci…“ obsahuje informace o autorovi a o autorech použitých knihoven a utilit. Jeho kód je součástí třídy HDRPanorama.AboutDialog.
47
4.3 Hlavní okno aplikace Třída HDRPanorama.MainApp je hlavním oknem aplikace a tedy zastřešuje všechny moduly a dialogy. Z datových struktur významných pro výpočet obsahuje pouze proměnnou pro uložení výsledného HDR panoramatu a instance čtyř základních modulů. Na formuláři tohoto okna najdeme množství tlačítek, jejichž stisknutím voláme požadovanou posloupnost akcí příslušných modulů. Protože mohou být některé z operací prováděného výpočtu časově náročné, rozhodl jsem se tyto operace spouštět ve zvláštním pracovním vlákně. Výpočet tedy neomezuje hlavní vlákno aplikace, které kreslí okno. Jedním z tlačítek lze běžící vlákno přerušit. Pokud toho vlákno zrovna volá nějakou utilitu, je nutné počítat s časovou prodlevou nastavenou na 1000 milisekund.
4.3.1
Stavy aplikace
Aplikace v průběhu výpočtu prochází množstvím stavů, které se musejí odrazit v povolení respektive zakázaní jednotlivých tlačítek a položek menu. Proto definujeme výčtový typ HDRPanorama.State, který může nabývat následujících hodnot: • Start – počáteční stav aplikace, je povoleno připojit se k zařízení a začít pořizovat snímky, importovat dříve pořízené snímky nebo navázat na přerušený výpočet přes uložený kontrolní bod, toto je také jediný stav, kde lze nastavovat možnosti aplikace • Acquire – aplikace je připojena k pořizovacímu zařízení, zatím však nebyly vybrány časy expozice pro pořizování HDR dat, je tedy možné pouze nastavovat jednotlivé parametry zařízení a pořizovat testovací snímky • AcquireHDR – do tohoto stavu aplikace přejde po výběru časů expozice pro pořizování HDR dat, žádná série snímků však ještě nebyla pořízena, je tedy stále možné měnit parametry zařízení • AcquiringHDR – po pořízení první série snímků je nastavení parametrů zařízení zablokováno přechodem do tohoto stavu, naopak je povolena možnost prohlížet a mazat pořízené série přes HDR Manager • AcquiringHDRAbort – právě ve zvláštním vlákně probíhá pořizování série snímků, toto vlákno lze přerušit • PreStitch – tohoto stavu dosáhneme po odpojení od pořizovacího zařízení případně po importu dříve pořízených snímků, stále máme možnost prohlížet a mazat pořízené série přes HDR Manager, navíc můžeme pořízené snímky exportovat nebo na nich spustit první krok výpočtu • PreStitchAbort – právě ve zvláštním vlákně probíhá první krok výpočtu, toto vlákno lze přerušit • PostStitch – po doběhnutí prvního kroku výpočtu se dostaneme do stavu, ze kterého můžeme pokračovat buď zavoláním aplikace umožňující editaci řídících bodů nebo spuštěním druhého finálního kroku výpočtu • PostStitchAbort – právě ve zvláštním vlákně probíhá druhý krok výpočtu, toto vlákno lze přerušit • Save – výpočet je hotový a my můžeme uložit vniklé HDR panorama, případně ho předtím ještě převést do jiného panoramatického formátu • SaveAbort – právě ve zvláštním vlákně probíhá ukládání HDR panoramatu do souboru, toto vlákno lze přerušit
48
4.3.2
Vizualizace průběhu výpočtu
Probíhající výpočet je v hlavním okně aplikace vizualizován. Průběh je vidět ve stavovém řádku, detaily výpočtu se také logují. Přibližný odhad zbývajícího času výpočtu poskytuje progress bar.
Obrázek 4.3: Hlavní okno aplikace s probíhajícím výpočtem.
Kvůli sjednocení informací poskytovaných těmito třemi způsoby byly implementovány následující soukromé metody: • void showBusy(progressBarMaximum) – změní kurzor na přesýpací hodiny a nastaví maximální hodnotu progress baru podle zadané hodnoty • void showReady() – změní kurzor zpět na šipku, vynuluje progress bar a změní text stavového řádku na „Ready“ • • • •
void showInfo(info, details), void showInfo(info) – zobrazí ve stavovém řádku informace o probíhající operaci výpočtu a zároveň je spolu s detaily (pokud jsou zadány) zapíše do logu void showDone(stepCount) – zapíše do logu úspěšné dokončení operace a posune progress bar o zadanou hodnotu void showAborted() – zapíše do logu neúspěšné dokončení operace void showState(State state) – nastaví stav aplikace na zadanou hodnotu a tím způsobí povolení respektive zakázaní jednotlivých tlačítek a položek menu
49
Tyto metody je potřeba volat především z jednotlivých modulů, které nemají žádný odkaz na hlavní okno aplikace. Proto moduly obsahují množství událostí, které jsou vyvolány, když nějaká operace výpočtu začíná nebo je úspěšně dokončena. Jejich handlery v hlavním okně aplikace pak volají odpovídající metody. Delegáty těchto handlerů nalezneme v namespace HDRPanorama.Data: • delegate void ActionEventHandler(sender, e, details) – delegát metody oznamující začátek nějaké operace, parametrem jsou detaily operace zobrazované v logu • delegate void WorkDoneEventHandler(sender, e, stepCount) – delegát metody oznamující úspěšné dokončení operace, parametrem je požadovaný posun progress baru Vzhledem k tomu, že operace modulů jsou spouštěny ve zvláštním vlákně, není možné vizuální komponenty hlavního okna aplikace měnit přímo, ale pomocí volání přes Invoke(). Metoda volaná přes Invoke() musí být bezparametrová, proto je zavedeno množství proměnných invokeX a bezparametrových metod changeY(), které odpovídají parametrovým metodám showY(X).
4.3.3
Prohlížeč obrázků
Při běhu aplikace vzniká množství obrázků. Některé jsou pořízeny, jiné jsou výsledkem výpočtu. Pokud chceme mít alespoň rámcovou představu o tom, jaká obrazová data program právě zpracovává, můžeme použít jednoduchý prohlížeč obrázků.
Obrázek 4.4: Prohlížeč obrázků s právě spojeným panoramatem.
50
Třída HDRPanorama.ImageViewer obsahuje pouze jedinou vlastnost: • Bitmap Image – vrací právě zobrazovaný obrázek Instance této třídy je vytvořena hned po spuštění aplikace a zavření příslušného okna ji nezruší, pouze skryje. Změna zobrazovaného obrázku probíhá voláním soukromé metody hlavního okna • void showImage(imagePath) – pomocí výše zmíněné vlastnosti zobrazí obrázek na zadané cestě pro handler události z modulu je připraven delegát • delegate void ShowImageEventHandler(sender, e, imagePath) – delegát metody oznamující, že vznikl nový obrázek, který je potřeba zobrazit, parametrem je cesta k obrázku
4.4 Ukládání nastavení aplikace K ukládání a načítání nastavení z XML jsem použil netradiční postup – využil jsem XML serializaci, kterou použité prostředí .NET nabízí. Při této serializaci jsou do souboru formátu XML ukládány hodnoty veřejných položek a vlastností serializované třídy, během načítání jsou zase naopak podle XML souboru tyto hodnoty v nově vytvořené instanci třídy nastavovány. Pokud serializovaná třída obsahuje ve veřejných položkách instance serializovatelných tříd, jsou jejich serializace vloženy do výsledného XML stromu jako podstromy. Je tedy nutné vytvořit jednu kořenovou třídu nastavení33 a přidáváním veřejných položek s instancemi dalších tříd vytvářet požadovaný tvar XML stromu. Touto kořenovou třídou ukládající nastavení aplikace je HDRPanorama.Settings.Settings a kromě vlastností reprezentujících jednotlivá nastavení obsahuje jednu metodu: • void Init(mainApp) – promítne načtená nastavení do hlavního okna Princip práce s nastaveními je jednoduchý. Všechny parametry, které jsou součástí nastavení, zpřístupňuje hlavní okno přes svoje vlastnosti. Při ukládání nastavení jsou skrz vlastnosti třídy nastavení tyto vlastnosti přímo čteny, při načítání nastavení jsou hodnoty ukládány do pomocných proměnných a voláním výše zmíněné metody zapsány do hlavního okna. V případě, že se načtení nastavení ze souboru nezdaří, jsou použity přednastavené hodnoty pomocných proměnných. Součástí nastavení jsou také informace o aktivní implementaci každého z modulů a o parametrech všech jeho implementací. Pro každý modul nalezneme v kořenové třídě nastavení veřejnou položku s instancí třídy, která toto nastavení uchovává. Jsou to třídy: • HDRPanorama.Settings.Acquirer.AcquirerSettings • HDRPanorama.Settings.Combiner.CombinerSettings • HDRPanorama.Settings.Tonemapper.TonemapperSettings • HDRPanorama.Settings.Stitcher.StitcherSettings Princip jejich práce si popíšeme například u druhé z nich. Zmíněná třída obsahuje ve veřejných položkách instance nastavení všech implementací modulu Combiner, zde tedy instanci třídy HDRPanorama.Settings.Combiner.GammaCombinerSettings. Ta implementuje stejně jako jakákoli další instance nastavení implementace tohoto modulu rozhraní HDRPanorama.Settings.Combiner.ICombinerSettings obsahující jedinou metodu: • ICombiner GetCombiner(workPath) – vrací podle současných hodnot nastavení parametrů vytvořenou implementaci modulu Combiner, která bude používat zadanou pracovní cestu 33
Tuto třídu budeme serializovat do souboru Settings.xml v adresáři aplikace.
51
Ke zjištění, která implementace modulu Combiner je právě aktivní, slouží další vlastnost a metoda třídy HDRPanorama.Settings.Combiner.CombinerSettings: • CombinerSetting SelectedCombinerSetting – vrací informaci o tom, která implementace modulu Combiner je právě aktivní • ICombinerSettings GetSelectedCombinerSettings() – vrací nastavení aktivní implementace modulu Combiner, například proto, abychom pak voláním jeho metody GetCombiner(workPath) získali podle nastavení inicializovanou instanci aktivní implementace modulu Combiner
4.5 Přerušení rozdělaného výpočtu Výpočet, který aplikace provádí, může být velmi časově náročný, hodila by se tedy možnost výpočet přerušit a někdy později na přerušený výpočet navázat. Vše by navíc mělo fungovat takovým způsobem, aby šlo navázat i na neúmyslně přerušený výpočet, například výpadek proudu. Na druhou stranu by se také hodilo, aby šlo fotografie pořizovat s použitím snadno přenositelného počítače, například notebooku, zatímco výpočet panoramatu spouštět na výkonném stolním počítači, tedy export a import sérií snímků. Obě tyto funkčnosti aplikace HDR Panorama implementuje.
4.5.1
Export a import sérií snímků
Myšlenka exportu je jednoduchá – vezmeme pořízené snímky a zkomprimujeme je do jediného souboru. Po importu bychom pak však museli postavit z informací v EXIF datech jednotlivých snímků znovu datovou strukturu ShotImages, která je vytvářena v modulu Acquirer v průběhu focení. Snazší je existující instanci této třídy serializovat do XML souboru a zkomprimovat spolu se snímky. Poslední problém pak zůstává s potenciálně různou pracovní cestou na exportujícím a importujícím stroji, v ShotImages jsou totiž uloženy absolutní cesty k jednotlivým snímkům. Tento problém odpadne, pokud si pracovní cestu na exportujícím stroji zapamatujeme a po importu ji v ShotImages u všech snímků změníme. Z tohoto důvodu obsahuje třída HDRPanorama.Settings.Export následující položky: • string WorkPath – pracovní cesta na exportujícím stroji • ShotImages ShotImages – datová struktura reprezentující pořízené série snímků Tuto třídu serializujeme do souboru Export.xml v pracovním adresáři a zkomprimujeme spolu s fotkami voláním open source utility 7za34 7za
[<switches>] <archive_name> []
s parametry a –tzip do běžného ZIP archívu, který je uložen na místo zvolené v dialogu exportu. Import začíná dekomprimací archívu získaného z místa zvoleného v dialogu importu do pracovního adresáře voláním 7za s parametry x –aoa, což způsobí přepsání souborů v případě shody jména. V pracovním adresáři pak hledáme soubor Export.xml. Pokud není nalezen, je zobrazena chybová hláška a export se nezdařil. V případě, že byl archív v pořádku a soubor nalezen je, deserializujeme jej a získanou pracovní cestu na exportujícím stroji použijeme ke změně absolutních cest získané datové struktury ShotImages, kterou následně uložíme do modulu Acquirer. 34
verze 4.23, autorem Igor Pavlov
52
4.5.2
Navázání na kontrolní bod
Vzhledem k tomu, že přerušený výpočet a navázání na něj bude probíhat na stejném počítači, obejdeme se zde bez exportu pracovních dat. Během výpočtu se mění stav aplikace a obsah dvou základních datových struktur, které výpočet zprostředkovávají – ShotImages v modulu Acquirer a PanoramaImages v modulu Stitcher. Ze stavu aplikace a obsahu těchto datových struktur je přesně poznat, kde se právě výpočet nalézá, proto jejich uložením získáme kontrolní bod. Dále potřebujeme také zajistit, aby byla aplikace při navázání na kontrolní bod nastavena stejně, jako byla v průběhu přerušení výpočtu. Jedná se zejména o volbu aktivních implementací jednotlivých modulů a o správné nastavení jejich parametrů. Je tedy nutné aktuální nastavení přidat do kontrolního bodu a při navázání na něj tato nastavení obnovit. Třída HDRPanorama.Settings.Checkpoint, jejíž serializací do XML souboru Checkpoint.xml v adresáři aplikace získáme kontrolní bod, obsahuje tyto položky: • State State – stav aplikace v době ukládání kontrolního bodu • Settings Settings – nastavení platná pro výpočet • ShotImages ShotImages – datová struktura reprezentující pořízené série snímků • InputImages PanoramaImages – datová struktura reprezentující spojená panoramata Navázání na kontrolní bod je jednoduché. Po ověření, že kontrolní bod byl uložen, proběhne jeho deserializace, jsou aplikována získaná nastavení, ShotImages uloženy do modulu Acquirer, PanoramaImages uloženy do modulu Stitcher a je obnoven stav aplikace v době ukládání kontrolního bodu, všechny tyto operace provádí soukromá metoda hlavního okna • void loadCheckpoint(onlyImages) – načte kontrolní bod, podle hodnoty zadaného parametru pak na něj buď naváže nebo ne, načtení kontrolního bodu bez navázání na něj je užitečné, pokud chceme kontrolní bod smazat, jak o tom bude řeč níže Nyní musíme vyřešit otázku, kdy kontrolní body ukládat. Rozhodl jsem se kontrolní bod uložit v každé chvíli, kdy je dokončena nějaká časově náročná operace, která svůj výsledek ukládá do souboru v pracovním adresáři, při současném návrhu kontrolních bodů totiž není možné (a často ani kvůli velikosti stovek megabytů vhodné) ukládat datové struktury aplikace, které v sobě nesou mezivýsledky výpočtu, například vnitřní reprezentaci HDR obrazu. Požadavek na uložení kontrolního bodu pochází často z modulů, které nemají žádný odkaz na hlavní okno aplikace, proto je kromě soukromé metody hlavního okna • void saveCheckpoint() – uloží kontrolní bod definován také delegát pro handler události z modulu • delegate void SaveCheckpointEventHandler(sender, e) – delegát metody oznamující, že je potřeba uložit kontrolní bod Nakonec zbývá umožnit kontrolní body mazat. Spolu s kontrolním bodem jsou vždy mazány také veškeré dočasné soubory v pracovním adresáři včetně pořízených snímků, protože bez informací uložených v kontrolním bodu jsou nepoužitelné. Ke smazání kontrolního bodu a dočasných souborů slouží soukromá metoda hlavního okna • void deleteCheckpoint() – smaže kontrolní bod a dočasné soubory Tato metoda je volána na uživatelovu žádost při zavírání aplikace a také když začínáme pořizovat další HDR panorama. V druhém případě je potřeba nejprve uložený kontrolní bod načíst, abychom věděli, které dočasné soubory máme smazat.
53
4.6 Kuchařka k přidání další implementace modulu Následující text slouží jako návod, jak do navrženého modulárního systému přidat další implementaci některého z modulů. Postup se liší podle toho, zda se jedná o implementaci některého ze základních modulů, implementaci modulu Warper nebo implementaci modulu RadianceIO.
4.6.1
Přidání implementace základního modulu
Nová implementace některého ze základních modulů je do aplikace přidána jednoduše implementací příslušného rozhraní. Kromě metod rozhraní je nutné implementovat také konstruktor, který nastaví všechny parametry metody použité v této nové implementaci. Abychom umožnili použití této implementace, musíme přidat také třídu s jejími nastaveními a správně ji zakomponovat do systému nastavení. Všechny potřebné kroky k přidání implementace základního modulu si ukážeme například u fiktivní implementace modulu Tonemapper – GradientTonemapper: • vytvoříme třídu HDRPanorama.Tonemapper.GradientTonemapper, která bude implementovat rozhraní HDRPanorama.Tonemapper.ITonemapper • vytvoříme této implementaci modulu odpovídající třídu s nastaveními HDRPanorama.Settings.Tonemapper.GradientTonemapperSettings, která implementuje HDRPanorama.Settings.Tonemapper.ITonemapperSettings • do výčtového typu HDRPanorama.Settings.Tonemapper.TonemapperSetting přidáme položku GradientTonemapper • uvnitř třídy HDRPanorama.Settings.Tonemapper.TonemapperSettings vytvoříme veřejnou položku typu GradientTonemapperSettings a v metodě GetSelectedTonemapperSettings() přidáme větev pro GradientTonemapper • posledním krokem je úprava dialogu s možnostmi, kde v konstruktoru vložíme GradientTonemapper do listBoxTonemapper a přidáme do dialogu panel s jeho nastaveními, který se bude vhodně zobrazovat úpravou metody listBoxTonemapper_SelectedIndexChanged()
4.6.2
Přidání implementace modulu Warper
Přidání nové implementace modulu Warper začíná opět implementací příslušného rozhraní, zde HDRPanorama.Warper.IWarper. Každý podporovaný panoramatický formát má v nastaveních uvedenou požadovanou šířku výsledného panoramatu, pro nově implementovaný formát ji tedy musíme přidat jako položku a veřejnou vlastnost do hlavního okna aplikace a do kořenové třídy nastavení. Také je potřeba vytvořit příslušné políčko pro editaci tohoto údaje v dialogu s možnostmi. Jednotlivé převody panoramatických formátů jsou volány stiskem příslušného tlačítka hlavního okna aplikace, pro nový formát tedy zavedeme další tlačítko. V případě, že by bylo formátů mnoho, stojí za úvahu návrh jiného způsobu výběru požadovaného převodu. Návrh tlačítek se opíral o to, že pravděpodobně nebude nikdy nutné podporu dalšího panoramatického formátu přidávat.
4.6.3
Přidání implementace modulu RadianceIO
Pravděpodobně nejjednodušší je přidat novou implementaci modulu RadianceIO. V tomto případě implementujeme rozhraní HDRPanorama.RadianceIO.IRadianceIO a konstruktor, který v parametru typu string dostává jméno souboru, do kterého jsou data ukládána nebo ze kterého jsou čtena.
54
Nyní stačí do aplikace přidat podporu pro tento nový formát souboru, kterému odpovídá nějaká přípona. To zařídíme vložením příslušné větve s touto příponou do konstruktoru a do metody Save(fileName) třídy HDRPanorama.Data.RadianceBuffer. Danou příponu také přidáme do filtru dialogu uložení.
55
Kapitola 5 Závěr V této práci jsem navrhl a implementoval systém využívající digitální fotoaparát k automatickému pořizovaní high dynamic range (HDR) map okolí. Systém pořizuje snímky s různými časy expozice a s různými směry pohledu. Použitím HDR komprese na složené snímky získá pro každý směr pohledu nový obrázek a tyto obrázky jsou použity ke snadnému nalezení řídících bodů na celé ploše budoucího panoramatu. Pak je spuštěna externí aplikace, která spojí pořízené snímky odděleně pro každý čas expozice za použití těchto řídících bodů, a žádaná HDR mapa okolí je nakonec získána složením spojených panoramat. Systém se podařilo navrhnout modulárně, umožňuje tedy vícenásobné implementace jednotlivých kroků výpočtu. Pro každou ze základních operací lze použít různé metody a porovnávat, která poskytuje lepší a která horší výsledky z hlediska kvality výsledného panoramatu či z hlediska času potřebného k jeho výrobě. V přiložené aplikaci HDR Panorama má každý modul pouze jedinou implementaci odpovídající nějaké jednoduché metodě, navržené modulární prostředí je však plně připraveno k dopsání dalších implementací. Tato aplikace umožňuje s použitím fotoaparátu Canon EOS a programu Hugin HDR mapy okolí pořizovat a následně je ukládat do souborů ve formátu RGBE nebo OpenEXR. Hlavním přínosem této práce je právě myšlenka hledat řídící body a jejich korespondence potřebné ke spojení snímků na obrázcích vzniklých HDR kompresí složených snímků pro každý směr pohledu, což zaručuje kvalitní napojení snímků i v případě, že se intenzita osvětlení v jednotlivých směrech pohledu velmi liší a není možné řídící body hledat pro žádný konkrétní čas expozice, jak to dělají metody, které HDR kompresi nevyužívají. Další výhodou navrženého systému je možnost provádět výpočet v plně automatickém režimu bez zásahu uživatele. Porovnáme-li navržený systém s jiným používaným postupem, pořizováním HDR map okolí fotografováním scény přes stříbrnou kouli, jak navrhuje P. Debevec, získáme při použití navrženého systému z důvodu většího počtu potřebných vstupních snímků lepší rozlišení vzniklého panoramatu za cenu větší časové náročnosti celého výpočtu. Mezi možná rozšíření práce patří hlavně přidání dalších implementací jednotlivých modulů. Za úvahu stojí především implementace metody výpočtu charakteristické křivky zařízení přímo z pořízených snímků podle Debevec a Malik [2] a gradientní metoda HDR komprese prezentovaná v Lischinski a kol. [6]. Experimenty ukazují, že s použitím gradientní metody HDR komprese dosáhneme lepšího potlačení vlivu osvětlení a tím dalšího zlepšení podmínek pro hledání řídících bodů.
56
V rovině spekulací pak zůstává možnost pořadí složení konstrukcí obrátit a spojovat přímo HDR obrazy. Mezi největší problémy zde patří skutečnost, že HDR obraz obsahuje pouze relativní a ne absolutní informace o světlosti jednotlivých pixelů, pro kvalitní spojení bychom tedy měli také zkoušet měnit absolutní jas jednotlivých spojovaných HDR obrazů. Kdyby se nám však opravdu podařilo jas těchto HDR obrazů vyvažovat, získali bychom metodu odolnou vůči změnám osvětlení v průběhu focení a navíc bychom podstatně zkrátili čas výpočtu.
57
Literatura [1]
Reinhard E., Stark M., Shirley P., Ferwerda J. (2002): Photographic tone reproduction for digital images. ACM Trans. Graph. (special issue SIGGRAPH 2002) 21, 3, 267–276.
[2]
Debevec P., Malik J. (1997): Recovering high dynamic range radiance maps from photographs. In Proc. of ACM SIGGRAPH ’97, 369–378.
[3]
Aggarwal M., Ahuja N. (2001): Split aperture imaging for high dynamic range. In Proc. IEEE ICCV, vol. II, 10–17.
[4]
Aggarwal M., Ahuja N. (2001): High dynamic range panoramic imaging. In Proc. IEEE ICCV, vol. I, 2–9.
[5]
Industrial Light & Magic, Lucasfilm Ltd. (2005): Technical introduction to OpenEXR. http://www.openexr.com/TechnicalIntroduction.pdf
[6]
Fattal R., Lischinski D., Werman M. (2002): Gradient domain high dynamic range compression. ACM Trans. Graph. (special issue SIGGRAPH 2002) 21, 3, 249– 256.
[7]
Seetzen H., Heidrich W., Stuerzlinger W., Ward G., Whitehead L., Trentacoste M., Ghost A., Vorozcovs A. (2004): High dynamic range display systems. ACM Trans. Graph. (special issue SIGGRAPH 2004) 23, 3, 760–768.
[8]
Cohen J., Tchou C., Hawkins T., Debevec P. (2001): Real-time high-dynamic range texture mapping. In Rendering Techniques 2001, S. J. Gortler and K. Myszkowski, Eds. Springer-Verlag, 313–320.
[9]
Green S., Cebenoyan C. (2004): High dynamic range rendering on the GeForce 6800. nVidia Corporation, http://developer.nvidia.com/object/hdr_on_6800.html
[10] Wenzel C. (2005): Far Cry and DirectX. Crytek, http://www.ati.com/developer/gdc/D3DTutorial08_FarCryAndDX9.pdf [11] Mitchell J. L. (2002): Radeon™ 9700 shading. ATI Technologies, http://www.ati.com/developer/SIGGRAPH02/ATIHardwareShading_2002_Chapte r3-1.pdf [12] Brown M., Lowe D. G. (2003): Recognising panoramas. In Proc. ICCV 2003, 1218–1227.
58
Dodatek A Manuál k HDR Panorama Aplikace je napsána v jazyce C# a zkompilována do prostředí .NET, pro umožnění uživatelského zásahu do průběhu spojování je navíc potřeba mít nainstalovanou aplikaci Hugin a příponu pto asociovanou s ní. Softwarové požadavky k plnohodnotnému běhu aplikace HDR Panorama jsou tedy následující: • Microsoft .NET Framework 1.1 http://msdn.microsoft.com/netframework/downloads/framework1_1redist/ • Hugin 0.5 rc 1 http://prdownloads.sourceforge.net/hugin/hugin-0.5_rc1_allinone_setup.exe Jediným hardwarovým požadavkem je pořizovací zařízení, v současné době jsou podporovány pouze fotoaparáty Canon třídy EOS, aplikace byla testována s fotoaparátem Canon EOS 300D. Následující body se pokusí popsat postup, jak s použitím tohoto fotoaparátu a aplikace HDR Panorama pořídíte HDR panorama: 1) Najděte pěkné místo, odkud budete panorama pořizovat (pokud se jedná o panorama místnosti, ideální je její střed) a umístěte do něj stativ s fotoaparátem. Doporučuji použít speciální stativ určený k pořizování panoramat, který provádí rotaci fotoaparátu kolem jeho optického středu a nedochází pak při rotaci k nežádoucím změnám zákrytů různě vzdálených předmětů. 2) Zvolte k pořizování správnou dobu, je totiž nutné během pořizování zachovat stejné osvětlení. Pokud pořizujete panorama v uměle osvětlené místnosti, na zvolené době nezávisí, problém však nastává, pokud je scéna osvětlena sluncem. Počítejte s tím, že pořizování zabere několik desítek minut času, není tedy vhodné volit východ nebo západ slunce, případně dobu, kdy se slunce chvílemi skrývá za mraky. 3) Přepněte fotoaparát do plně manuálního režimu, vypněte automatické zaostřování a zvolte minimální přiblížení. Takto nastavený fotoaparát připojte pomocí USB kabelu k počítači, kde máte nainstalované potřebné ovladače a zapněte jej. Mělo by dojít k nalezení připojeného zařízení. 4) Spusťte aplikaci HDR Panorama a případně výběrem příkazu z hlavní nabídky zobrazte dialog s možnostmi a zadejte požadovaná nastavení pořizování. Jedná se zejména o velikost vzniklého panoramatu o a parametry metod použitých k jednotlivým krokům výpočtu. Potom se stiskem tlačítka Connect k fotoaparátu připojte. V jednotlivých rozbalovacích nabídkách pak získáte možné hodnoty nastavitelných parametrů fotoaparátu. 59
5) Stiskem tlačítka Show Image Viewer vyvolejte okno s náhledem. Nyní střídavě měňte nabízené parametry fotoaparátu včetně zaostření a stiskem tlačítka Test Shot pořizujte testovací snímky, dokud se vám použitá nastavení nelíbí. Není vhodné volit položku Auto, je nutné zvolit nějaká pevné nastavení, sám doporučuji následující: o pro vytvoření panoramatu typické velikosti je vhodné z hlediska časové a paměťové náročnosti výpočtu nastavit co možná nejmenší velikost a nejhorší kvalitu pořizovaných snímků o hodnotu citlivosti ISO volíme podle druhu scény, pro exteriéry nižší, pro interiéry vyšší o vyvážení bílé volíme podle druhu osvětlení o clonové číslo volíme spíš větší, abychom docílili dostatečné hloubky ostrosti a scéna nebyla vzhledem k vypnutému automatickému zaostřování příliš rozostřená 6) Zaměřte fotoaparát na nejsvětlejší místo ve scéně a nalezněte čas expozice, pro který je snímek dostatečně tmavý, především nesmí být žádné oblasti snímku přeexponované. Pak zaměřte fotoaparát na nejtemnější místo ve scéně a nalezněte čas expozice, pro který je snímek dostatečně světlý, zde nesmějí být žádné oblasti podexponované. 7) Vyvolejte stiskem tlačítka Configure HDR Shutter Speeds dialog s časy expozice pro pořizování HDR dat a zvolte časy s maximálním vzájemným rozdílem dva expoziční stupně tak, aby maximální a minimální čas expozice odpovídaly časům zjištěným v předchozích bodech. Pokud jste časy nezjišťovali, stiskněte tlačítko Step 2 pro použití přednastavených časů. 8) Začněte pořizovat opakovaným stiskem tlačítka HDR Shot série snímků pro HDR panorama. První snímky pořizujte s fotoaparátem vodorovně, pokryjte rotací kolem svislé osy postupně celých 360° tak, aby snímky měly dostatečné překryvy. Potom pořizujte další snímky, ale vždy tak, aby pořizovaný snímek měl nějaký překryv s některým dříve pořízeným snímkem. V průběhu pořizování dbejte na to, abyste neměnili zaostření ani přiblížení objektivu. Při pořizování jedné série navíc nesmíte s fotoaparátem pohybovat. 9) Pořízené série snímků si můžete prohlížet po stisku tlačítka HDR Manager. Nepodařené série (pohyb fotoaparátu nebo jiná neplánovaná změna scény) je možné nenávratně mazat. 10) Stiskem tlačítka Disconnect odpojíte fotoaparát a skončíte pořizování snímků. Pokud si přejete pořízené snímky zpracovat na jiném (typicky výkonnějším) počítači, můžete je příkazem z hlavní nabídky exportovat do jediného souboru35. Stiskem tlačítka Pre-stitch Combine zahájíte první krok výpočtu, o jehož průběhu jste informováni v pravé části okna. 11) Po skončení prvního kroku výpočtu můžete navrhované panorama stiskem tlačítka Stitching Tool upravit v aplikaci Hugin (práce s aplikací je popsána v jejím manuálu) nebo rovnou stiskem tlačítka Post-stitch Combine zahájit druhý finální krok výpočtu. 12) Po skončení druhého kroku výpočtu je HDR panorama hotové, zbývá ho stisknutím tlačítka podle požadovaného panoramatického formátu uložit. 35
Na importujícím počítači pak po spuštění aplikace HDR Panorama a případném nastavení možností nezačínáte stiskem tlačítka Connect, ale výběrem příkazu k importu z hlavní nabídky.
60
Dodatek B Popis formátu pto Soubory formátu pto používá Hugin a s ním související utility k ukládaní projektu s panoramatem, původně se jedná o skript utility PTOptimizer. Je to textový soubor, kde každý řádek začíná písmenem, které určuje charakter informací na daném řádku. Rozepíšeme si pro všechna možná písmena strukturu poskytovaných informací: p
m
i
v c
o
Informace o panoramatu jako celku f – projekční formát panoramatu, v našem případě equirectangular f2 w, h – šířka a výška panoramatu v – zorný úhel panoramatu, pro naše použití v360 n – výstupní formát panoramatu, používáme více TIFF souborů n”TIFF_m” Informace o metodě spojování g – hodnota gamma, není využito, ponecháme tedy přednastavenou g1 i – použitý interpolátor, v našem případě bikubický i0 Informace o vstupních snímcích w, h – šířka a výška snímku f – projekční formát snímku, zde rectilinear f0 a, b, c – parametry zkreslení čočky d, e – posun středu snímacího čipu od jeho průsečíku s optickou osou objektivu g, t – požadované ořezání snímku před spojením, my neořezáváme, tedy g0 t0 v – zorný úhel snímku p, r, y – poloha snímku na konstruované 3D kulové ploše ve stupních u – velikost prolnutí, není využito, ponecháme tedy přednastavenou u10 n – relativní nebo absolutní cesta ke snímku Informace o parametrech, které mají být u snímků optimalizovány a, b, c, d, e, v, p, r, y – význam stejný jako u informace o vstupních snímcích Informace o řídících bodech n, N – číslo prvního a druhého snímku x, y – poloha řídícího bodu na prvním snímku X, Y – poloha řídícího bodu na druhém snímku t – způsob počítání vzdálenosti mezi body, používáme Euklidovskou t0 Informace o vstupních snímcích po proběhlé optimalizaci aby bylo možné optimalizaci spustit znovu, je nutné tyto řádky převést na i
61
Číslování vstupních snímků probíhá vzestupně od čísla 0 podle pořadí výskytu jednotlivých řádků s informacemi o vstupních snímcích. Tato čísla se využívají nejen na řádcích s informacemi o řídících bodech ale také na samotných řádcích s informacemi o vstupních snímcích pokud chceme vyjádřit, že hodnota nějakého parametru daného snímku je stejná jako hodnota odpovídajícího parametru jiného snímku, například že zorný úhel daného snímku je stejný jako prvního snímku: v=0. Výše uvedený přehled obsahuje popis pouze takových hodnot jednotlivých parametrů, které jsou důležité pro aplikaci HDR Panorama. Úplný seznam naleznete v tutoriálu, jehož autorem je B. Kreunen a z něhož jsem při tvorbě tohoto přehledu sám čerpal: http://www.path.unimelb.edu.au/~bernardk/tutorials/360/readme/
62