5.21. Změna měřítka, převrácení a oříznutí¶
Všechny předchozí podkapitoly pracovaly s pixely na stejných pozicích, kde začínaly. Rodina transformací to mění. Změna měřítka posílá každý vstupní pixel na jinou výstupní pozici, případně na několik výstupních pozic najednou (při zvětšování) nebo na pozici sdílenou s několika dalšími vstupními pixely (při zmenšování). Převracení a otáčení dělají totéž prostřednictvím jiného mapování. Oříznutí zachovává obdélníkovou podmnožinu vstupních pixelů a zbytek zahazuje.
Modul image tuto rodinu zpřístupňuje prostřednictvím tří metod, které sdílejí většinu svých argumentů a většinu svého chování:
copy()– vytvoří kopii obrazu, případně se změněným měřítkem, oříznutou nebo přeorientovanou.crop()– stejná operace jakocopy, ale s předpokladem, že aplikace ze zdroje vybere podobdélník.scale()– opět totéž, s předpokladem, že aplikace změní velikost výsledku.
Tyto tři metody sdílejí stejné argumenty a stejnou transformační mechaniku; rozdíl je v tom, kam výsledek ve výchozím nastavení míří. copy() vytváří nový obraz, zatímco crop() a scale() upravují zdroj na místě.
5.21.2. Interpolace: AREA, BILINEAR, BICUBIC¶
Když změna měřítka posílá každý výstupní pixel na pozici, která se nezarovnává s žádným jediným vstupním pixelem, musí metoda vybrat, jakou hodnotu zapsat. Jak na to, řídí tři příznaky:
image.BILINEAR interpoluje mezi čtyřmi nejbližšími vstupními pixely vážené jejich vzdáleností od výstupní pozice. Výsledek je hladší než nejbližší soused, bez viditelného zubatění na šikmých čarách, ale aritmetika navíc stojí zhruba čtyřnásobek průchodu metodou nejbližšího souseda. Správná volba pro většinu zvětšování a pro jakýkoli neceločíselný činitel měřítka.
image.BICUBIC interpoluje mezi šestnácti nejbližšími vstupními pixely pomocí kubické křivky, což produkuje ještě hladší výsledky za cenu opět vyšší náročnosti na aritmetiku. Nejlepší kvalita pro nákladově citlivé aplikace, které ji potřebují; pro živé snímky, které IDE pouze zobrazí, zřídka stojí za výpočet navíc.
image.AREA zprůměruje každý vstupní pixel, který spadá do plochy výstupního pixelu – správný algoritmus pro zmenšování. Bilineární a bikubická jsou interpolátory: odhadují hodnotu mezi zdrojovými pixely, což je to, co zvětšování potřebuje, ale při zmenšování každý výstupní pixel pokrývá mnoho zdrojových pixelů a interpolátor přečte jen těch několik nejbližších – detail, který přeskočí, se vrátí jako aliasing. image.AREA místo toho zahrne každý pokrytý pixel do průměru.
Výchozí algoritmus změny měřítka bez jakéhokoli příznaku je nejbližší soused, což je nejlevnější a správná odpověď, když je zdroj již v pixelovém rozlišení cíle.
5.21.3. Orientace: převrácení a otočení¶
Příznaky orientace jsou malá sada booleovských transformací, které se volně skládají mezi sebou navzájem i s příznaky interpolace:
image.VFLIPpřevrací obraz svisle (horní část se stává spodní).image.HMIRRORjej zrcadlí vodorovně (levá strana se stává pravou).image.TRANSPOSEprohazuje osy x a y (řádky se stávají sloupci).
Většina otočení vzniká skládáním těchto tří. Modul také zpřístupňuje pojmenované zkratky:
image.ROTATE_90(=VFLIP | TRANSPOSE)image.ROTATE_180(=HMIRROR | VFLIP)image.ROTATE_270(=HMIRROR | TRANSPOSE)
V kódu:
img.copy(hint=image.ROTATE_90, copy_to_fb=True)
5.21.4. Zacházení s poměrem stran¶
Když poměr stran zdroje neodpovídá obdélníku, do kterého se vykresluje, rozhodují o tom, co s tímto nesouladem udělat, tři příznaky:
image.SCALE_ASPECT_KEEP zachovává poměr stran zdroje a výsledek letterboxuje – zdroj se zmenšuje, dokud se nevejde do cíle, přičemž zbytek cíle vyplňují prázdné (nulové) pixely. Správná volba, když je zachování nezkresleného zdroje důležitější než vyplnění celého výstupu.
image.SCALE_ASPECT_EXPAND zachovává poměr stran zdroje a ořezává jej – zdroj se zvětšuje, dokud nevyplní cíl, přičemž části, které přesahují cíl, jsou odříznuty. Správná volba, když je vyplnění celého výstupu důležitější než vidět každou část zdroje.
image.SCALE_ASPECT_IGNORE ignoruje poměr stran a roztáhne zdroj tak, aby vyplnil cíl, a přijímá jakékoli zkreslení, které to způsobí. Správná volba, když aplikace již se zkreslením počítá – například když rozměry cíle ve skutečnosti nejsou obdélníkem téže scény.
Výchozí chování (žádný nastavený příznak poměru stran) je stejné jako SCALE_ASPECT_IGNORE: roztáhnout, aby se vyplnilo. Aplikace, kterým záleží na poměru stran, výslovně určí jeden ze tří.
5.21.5. Kdy sáhnout po které¶
Většina změn velikosti používá scale() s dvojicí x_scale / y_scale a interpolačním hintem:
img.scale(x_scale=0.5, y_scale=0.5, hint=image.AREA)
Většina otočení používá stejné volání s hint=image.ROTATE_90 nebo podobným.
Oříznutí používá crop() s nevýchozím roi:
img.crop(roi=(40, 30, 200, 150))
Když musí zdroj operaci přežít – zachycení referenčního snímku, pořízení náhledu snímku, který se chystá být destruktivně zpracován – copy() produkuje výsledek jako nový obraz a zdroj nechává nedotčený:
thumbnail = img.copy(x_scale=0.25, y_scale=0.25, hint=image.AREA)
Tímto výchozím nastavením je skutečný rozdíl za třemi názvy: scale a crop transformují na místě, copy alokuje. Klíčová slova pro umístění výsledku tento rozdíl překlenují: copy=True u scale nebo crop alokuje výsledek jako samostatný buffer na haldě namísto přepsání zdroje a copy_to_fb=True u kterékoli ze tří jej umístí do snímkového bufferu (frame buffer) pro náhled v IDE.