Autorské riešenie
Obrázky, ktoré je potrebné redukovať sú reprezentované v dvojrozmerných zoznamoch. Každý vnorený zozname predstavuje farby pixelov v jednom riadku obrázka. Pri riešení tejto úlohy budeme pracovať, manipulovať a upravovať, s dvojrozmernými zoznamami. Podľa zadania je potrebné pôvodný obrázok redukovať tak, že niekoľko pixelov pôvodného obrázka nahradíme jedným pixelom. Počet nahradzovaných pixelov je určený veľkosťou posuvného okna a výsledná farba sa vypočíta ako priemer farieb pixelov, ktoré nahrádzame. Podľa zadania môžeme predpokladať, že obrázok a posuvné okno majú tvar štvorca. Stačí nám preto vedieť len jeden rozmer. Ak by sa pôvodný obrázok nedal rozdeliť do jednotlivých okien, doplníme ho po krajoch nulami. Riešenie si môžeme rozdeliť do nasledovných krokov:
Pre jednotlivé kroky je výhodné definovať samostatné funkcie. Výsledný kód bude nie len prehľadnejší, ale budeme vedieť otestovať správnosť jeho častí samostatne. Ako prvú vytvorme funkciu pre doplnenie potrebných núl po okrajoch obrázka. #Python def dopln_0(obrazok, velkost_okna): zvysok_v_poslednom_okne = len(obrazok[0]) % velkost_okna if zvysok_v_poslednom_okne == 0: return pocet_chybajucich_policok = velkost_okna - zvysok_v_poslednom_okne for riadok in obrazok: riadok.extend([0] * pocet_chybajucich_policok) for i in range(pocet_chybajucich_policok): obrazok.append([0] * len(obrazok[0])) Najskôr zistíme, koľko núl je potrebné doplniť. Doplníme potrebný počet núl do každého riadka a zároveň doplníme aj potrebný počet riadkov. Obrázok po doplnení má stále tvar štvorca. Ďalšou užitočnou funkciou je funkcia, ktorá vypočíta priemer hodnôt pixelov zo zadaného okna. Tu sa oplatí zamyslieť, ako funkcii oznámiť, s ktorými hodnotami má pracovať. Jednou z možností je, že jej pošleme celý obrázok, súradnice začiatku okna a veľkosť okna. #Python def priemer_okna(obrazok, riadok_start, stlpec_start, velkost_okna): sucet = 0 for posun_r in range(velkost_okna): for posun_s in range(velkost_okna): sucet = sucet + obrazok[riadok_start + posun_r][stlpec_start + posun_s] priemer = sucet / velkost_okna ** 2 return round(priemer) Nakoniec vytvoríme funkciu, ktorá pôvodný obrázok zredukuje a vráti jeho redukovanú verziu. Časť problému už riešia predchádzajúce funkcie. #Python import copy def redukuj_obrazok(obrazok, velkost_okna): obrazok = copy.deepcopy(obrazok) dopln_0(obrazok, velkost_okna) redukovany = [] for idx_riadok in range(0, len(obrazok), velkost_okna): riadok = [] for idx_stlpec in range(0, len(obrazok), velkost_okna): riadok.append(priemer_okna(obrazok, idx_riadok, idx_stlpec, velkost_okna)) redukovany.append(riadok) return redukovany Keďže zoznam je v Pythone meniteľný, vytvoríme sí kópiu obrázka. Prácu si uľahčíme využitím funkcie deepcopy() z modulu copy Dopĺňanie núl budeme realizovať v kópii a do pôvodného obrázka zasahovať nebudeme. Keďže obrázok je reprezentovaný v dvojrozmernom zozname, na prechod cez pixely obrázka potrebujeme dva, navzájom vnorené cykly. Všimnime si aj to, že v tejto funkcii nepracujeme s hodnotami farieb pixelov, ale len so súradnicami. Vaše zaujímavé riešenia a najčastejšie chyby Väčšina z vás vyriešila úlohu správne. Niektorým z vás robilo problém doplnenie potrebných núl po okrajoch obrázka. |
||||||||||
© Univerzita Pavla Jozefa Šafárika v Košiciach, Prírodovedecká fakulta, Ústav informatiky palmaj (zavinac) upjs.sk |