Autorské riešenie
[stiahni py]

  • Počet riešiteľov: 14 / 14 = 100 %

  • Úspešnosť riešenia: 6,21 / 7 = 89 %

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:

  1. ak je to potrebné, doplníme nuly po okrajoch obrázka,

  2. vypočítajme priemer hodnôt pre každé podokno obrázka,

  3. z jednotlivých vypočítaných priemerov vytvorme novú, redukovanú verziu pôvodného obrázka.

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.