Změna velikosti obrázku Převzorkování pomocí filtrů Ačkoliv jsou výše uvedené metody mnohdy dostačující pro běžné aplikace, občas je zapotřebí dosáhnout lepších výsledků. Pokud chceme obrázky zvětšovat z nebo na různé neobvyklé velikosti, nebo nám jde o to vygenerovat z celé obrazovky jen malý náhled čítající několik desítek pixelů, pak se ke slovu dostává filtrování, protože je v těchto ohledech velice flexibilní. Algoritmus pro převzorkování je jeden, avšak filtrů samotných existuje povícero. Jsou definovány kernelem, který má různý rozsah, nebo poloměr. Ten udává vzdálenost nejzazšího pixelu, který se ještě započítává do hodnoty výsledného pixelu zvětšeného/zmenšeného obrázku. Tato vzdálenost se počítá od umístění pixelu v původním (zvětšovaném/zmenšovaném) obrázku. Čím větší rozsah, tím vyšší výstupní kvalita. Vlastní kernel lze znázornit grafem sudé funkce, ze které lze vyčíst některé charakteristiky kernelu. Funkce s hladším průběhem má ekvivalent v hladkém výstupním obrázku, naopak špičaté a hranaté funkce přinášejí typické artefakty ve výstupním obrázku. Funkční hodnota v daném bodě, která je vždy v intervalu <0,> udává váhový koeficient pro určitý pixel, tedy důležitost toho kterého pixelu. Obecně platí, že čím je pixel v původním obrázku vzdálenější od zdrojového, tím menší má důležitost. Některé kernely jsou však připočítávají více vzdáleným pixelům trochu větší váhu, než pixelům méně vzdáleným, kvůli lepší aproximaci z frekvenčního hlediska, respektuje se tedy vlnová povaha signálu (obrázek chápeme jako dvourozměrný signál). Důvodem existence více různých kernelů je jejich rozličná náročnost a rozsah. Větší kernely potřebují podstatně více výpočetního času, protože pro každý bod zdrojového obrázku je třeba vypočítat více váhových koeficientů a rovněž jejich určení je o to náročnější, čím složitější má funkce předpis. Algoritmus je poměrně jednoduchý na implementaci, je však potřeba dát pozor na okraje obrázku. Často se dělá chyba v tom, že když okolní pixely leží mimo obrázek, vůbec se nezapočítají. To má však za následek ztmavení na okrajích obrázku, protože v těchto oblastech byl součet váhových koeficientů menší než jedna. Tato suma musí být vždy rovna jedné, protože každá hodnota pixelu cílového obrázku je vlastně vážený průměr pixelů v okolí ekvivalentní pozice ve zdrojovém obrázku. Pro dodržení definice je tedy nutné buď vícekrát započítat jeden bod, nebo si pamatovat součet váhových koeficientů a tím pak dělit. Protože jsou souřadnice na sobě nezávislé (stejně jako barevné složky), implementuje se algoritmus dvouprůchodově. Jeden průchod je horizontální, druhý vertikální. U takové varianty stačí použít jednorozměrné varianty kernelů a rychlost algoritmu bude vyšší než u jednoprůchodové verze s funkcemi (kernely) o dvou parametrech. Algoritmus pro převzorkování filtrem do většího obrázku vypadá následovně:. Urči škálovací faktor: scale = n_width/width 2. Pro každou pozici i v cílovém vektoru: a. Transformuj i na pozici center ve vstupním vektrou: center = i/scale b. Urči levou hranici vyhledávání: left = round(center range) c. Urči pravou hranici vyhledávání: right = round(center + range) d. Inicializuj pomocné proměnné: value = 0, weight_sum = 0 e. Pro každou pozici j ve vstupním vektoru v intervalu <left, right>: i. Urči váhový koeficient: weight = kernel(c j) ii. Inkrementuj hodnotu cílového pixelu: value += weight*value iii. Inkrementuj sumu váhových koeficientů: weight_sum += weight f. Urči výslednou hodnotu pixelu: pixel = value/weight_sum Tento pseudokód kvůli názornosti neřeší problém okrajů. Vektorem se zde myslí jeden skenovací řádek obrázku (scanline). Vertikální průchod je obdobný. Tento kód rovněž předpokládá, že zvetšujeme, tj. že scale >. Pro zmenšování platí tato varianta: 3. Urči škálovací faktor: scale = n_width/width 4. Pro každou pozici i v cílovém vektoru: a. Transformuj i na pozici center ve vstupním vektrou: center = i/scale b. Urči levou hranici vyhledávání: left = round(center range/scale) c. Urči pravou hranici vyhledávání: right = round(center + range/scale) d. Inicializuj pomocné proměnné: value = 0, weight_sum = 0 e. Pro každou pozici j ve vstupním vektoru v intervalu <left, right>: i. Urči váhový koeficient: weight = kernel((c j)*scale)*scale ii. Inkrementuj hodnotu cílového pixelu: value += weight*value iii. Inkrementuj sumu váhových koeficientů: weight_sum += weight f. Urči výslednou hodnotu pixelu: pixel = value/weight_sum Proměnná value reprezentuje hodnotu pixelu vstupního obrázku a proměnná range je rozsah daného kernelu. Ve variantě pro zmenšování bude rozsah procházených pixelů tím větší, čím radikálnější je zmenšování. Hodnotou
scale sice dělíme, ale ta je menší než jedna. Naopak při výpočtu váhového koeficientu násobíme jak argument funkce, tak její výsledek. Protože je koeficientů scale-krát víc, je potřeba je poměrně k tomu zmenšit, aby se součet vah opět vyladil. Box filtr Tento filtr dává pro zvětšování stejné výsledky, jako metoda nejbližšího souseda (proto se tak někdy nazývá). Vrací pouze hodnoty nebo 0, takže barvy pixelů ve zvětšeném obrázku nejsou nijak ovlivněny okolními pixely (ty mají totiž vzdálenost minimálně ). Při změnšování přidělí funkce bodům v nejbližším okolí stejné váhy, takže z váženého průměru se stane aritmetický průměr., x 2 = 0, jinak Triangle filtr Box filtr, zleva: originál, zvětšení 2x, 4x, 8x Filtr se také nazývá lineární, protože váha pixelu je nepřímo úměrná jeho vzdálenosti. Proto je filtr vhodný i na zmenšování, při mnohonásobném zvětšování obrázků s ostrými konturami se však objevují uzavřené přechody, způsobené malým rozsahem filtru. Interpolují se totiž vždy jen hodnoty dvou sousedních pixelů. x, x = 0, jinak
Triangle filtr, zleva: originál, zvětšení 2x, 4x, 8x Hermite filtr 3 2 x x + x 2 3, = 0, jinak Hermite filtr, zleva: originál, zvětšení 2x, 4x, 8x Bell filtr 3 2 x, x 4 2 2 3 = x, < x 2 2 2 2 0, jinak
Bell filtr, zleva: originál, zvětšení 2x, 4x, 8x Cubic B-Spline filtr Tento filtr používá pro interpolaci kubickou Beziérovu křivku, která je definována čtyřmi body (proto má kernel rozsah 2 2 body na každé straně). Křivka však těmito body přímo neprochází. Body se připodobňují k magnetům, které elastickou křivku přitahují. Výhodou filtru je prakticky eliminace artefaktů za cenu velkého rozmazání obrázku, proto není filtr příliš vhodný pro vícenásobné zvětšování. Vzhledem k tomu, že křivka přesně nefituje původní hodnoty, má zvětšený obrázek také menší kontrast, než při použití jiných filtrů. 3 3 2 2 B C x + 3+ 2B + C x + B, x 2 3 3 2 4 = B C x + B + 5C x + 2B 8C x + B + 4 C, < x 2 6 3 0, jinak B =, C = 0
Cubic B-Spline filtr, zleva: originál, zvětšení 2x, 4x, 8x Lanczos3 filtr Trojka v názvu filtru znamená jeho rozsah (existují také filtry Lanczos4, Lanczos6 nebo Lanczos8, viz níže). x sinc( x ) sinc, x 3 = 3 0, jinak sinc ( x) sin ( π x), x 0 = π x, jinak Mitchell filtr Lanczos3 filtr, zleva: originál, zvětšení 2x, 4x, 8x 5 3 2 2 C x + ( 3+ 3C ) x + C, x 2 3 7 3 2 6 = C x + 6C x 0 C x + C, < x 2 6 3 0, jinak C = 3
Mitchell filtr, zleva: originál, zvětšení 2x, 4x, 8x Cosine filtr U tohoto filtru je zajímavé, že se můžeme v implementaci vyvarovat výpočtu absolutní hodnoty díky sudé funkci (ta nemusí být ani v pomínce, když se nahradí podmínkou, že x >= - a zároveň x <= ). Tím se ušetří jedna výpočetní operace, i když je náročnost filtru diskutabilní kvůli použití funkce kosinus. xπ + cos, x = 2 0, jinak Cosine filtr, zleva: originál, zvětšení 2x, 4x, 8x Catmull-Rom filtr C = 0, B = 2
Catmull-Rom filtr, zleva: originál, zvětšení 2x, 4x, 8x Quadratic filtr Tento filtr vznikl ze snahy o kompromis mezi rychlostí a výslednou kvalitou. K rychlosti přispívá výpočet pouze kvadratické křivky, která se však tvarově podobá složitějším interpolačním křivkám. 2 2 x +, x 2 2 5 3 3 = x x +, < x 2 2 2 2 0, jinak Quadratic B-Spline filtr Quadratic filtr, zleva: originál, zvětšení 2x, 4x, 8x Podobně jako u kvadratického filtru máme opět kvadratický polynom, avšak při použití Beziérovy křivky.
2 x +, x 2 2 5 3 3 = x x +, < x 2 2 2 2 0, jinak Quadratic B-Spline filtr, zleva: originál, zvětšení 2x, 4x, 8x Cubic Convolution filtr Kubický konvolutivní filtr se snaží přiklánět k ostrým hranám obrázku, avšak při zachování tvaru optimální křivky. 4 3 7 2 x x +, x 3 3 7 3 2 59 5 3, 2 x + x x + < x = 2 2 2 3 2 2 x x + 7 x 3, 2 < x 3 2 3 4 2 0 jinak
Cubic Convolution filtr, zleva: originál, zvětšení 2x, 4x, 8x Lanczos8 filtr Jde vlastně o Lanczos filtr, tedy také o tzv. windowed sinc interpolaci, ovšem velikost okna je v tomto případě větší než u filtru Lanczos3. Tento filtr je nejpomalešjí ze všech, avšak zejména při zmenšování dosahuje nejlepší interpolace. x sinc( x ) sinc, x 8 = 8 0, jinak Fraktální zoom