Loppupuheenvuoro – Esa

Taitaapi kurssi jo olla loppumaan päin! Loppupuheenvuoron paikka. Ensiksi OLO-sessioista. Etenkin alussa tällä tavoin lähes viikottain työskentely tuntui turhalta, turhauttavalta, epämielenkiintoiselta ja tarpeettomalta. Porukkaa oli paljon, suutaan ei viitsinyt tuntemattomien, itseään enemmän tietävien henkilöiden keskuudessa paljoa availla, seitsemän askeleen menetelmä ei tuntunut toimivan ja muutenkin kokonaisfiilis OLOja kohtaan oli vähintäänkin nihkeä. Toisen kierroksen jälkeen tapaukset alkoivat kuitenkin tuntua huomattavan paljon mielenkiintoisemmilta, ja kolmoskierroksen kohdalla porukkaa karsiutui paljon pois, jättäen tiiviimmän ja paremmin toimivan ryhmän jälkeensä. Olisi varmaankin ollut hyvä, jos jo alusta asti ilmapiiri olisi ollut tälläinen, mutta toimintaperiaatteen epämääräisyys ja yleinen negatiivisuus heikensi kokonaisuutta.

OLO-sessioiden virikkeissä ei aluksi ollut itselle mitään uutta – eikä kieltämättä loppuakaan kohti hirveän paljoa – mutta ryhmän sisäinen keskustelu ja itse tutkittavat asiat toivat erittäin paljon syvyyttä tapausten luomille pohjille. Itse pidin paljon siitä, että opin hieman pintaraapaisua tarkemmin monenlaisia asioita. Ryhmä alkoi toimimaan loppua kohden varsin autonomisesti, ja ainakin itse tulin siinä vaiheessa OLO-tapaamisiin ennemminkin mielenkiinnosta kuin pakosta. Jos se muutos olisi tapahtunut jo aiemmin, olisi kurssilla varmasti ollut kokonaisuutena positiivisempi ilmapiiri – mm. tuotantotalouden ykköskurssilla tehtiin koko kurssin ajan laajaa ryhmätyötä hyvin pienen ryhmän kesken, ja se tuntui toimivan heti alussa paremmin. Tiedä sitten käytännön järjestelyjen hankaluuksista.

Mielestäni tietokoneiden sisäisen toiminnan ja ohjelmistojen suunnittelujen pääpiirteiden ymmärtäminen on hyvä jokaisen tietotekniikan opiskelijan osata, ja siitä tuli myös tällä kurssilla opittua niin aiheiden kuin harjoitusten muodossa. Kokonaisuus pysyi hyvin kasassa ja perusteltua itkemistä kuunneltiin mielestäni hyvin. Toisaalta, palautteen määrän perusteella voisi päätellä, että parannettavaakin on vielä paljon. Kieltämättä moni harjoitustehtävä tuntui hieman kohtuuttomankin laajalta tai epäselkeältä, ja deadlinet alkoivat ajoittain tulla kovastikin vastaan (nimim. useampi kierros yhä palauttamatta). Kuitenkin mielestäni kurssi oli käymisen arvoinen – kiitos kaikille sitä toteuttaneille siitä! 🙂

– Esa Koskinen

Tehtävä 3 – Kuva

Kolmannnen kierroksen tehtävän tavoitteena oli ohjelmoida kourallinen suotimia joilla kuvia voisi muokata. Itse käyttöliittymä oli annettu valmiiksi, mutta molemmat suodintyypit (PixelFilter ja FourierFilter) piti viimeistellä itse annetun rungon päälle. Tässä tehtävässä hyödynnettiin ensimmäistä kertaa abstrakteja luokkia; näin kumpaakin suodintyyppiä voitiin käyttää samalla tavalla, vaikka niiden sisäinen toteutus olikin aivan erilainen.

Auringonkukka

Kohdekuvamme

PixelFilter muokkasi kuvia annetun matriisin perusteella. Tämä oli varsin mielenkiintoista, sillä oikeasti selvisi “miten matriisilla kerrotaan pikseleitä” ja myös miten monia tuttuja suotimia voi ylipäätään toteuttaa! Todennäköisesti moniin suotimiin on kuitenkin monia eri tapoja, varmasti tehokkaampiakin, mutta tässä pääsi hyvin alkuun. Alla on esimerkkejä muutamista eri efekteistä, osa poimittu GIMPin ohjemateriaalista matriiseja koskien.

PixelFilter-suotimia

Vasemmalta oikealle: sumennus (blur), tarkennus (sharpen), reunanlöytö (edge detect) ja kohokuva (emboss)

Itse vedin PixelFilterin toteutuksen vähän överiksi ja tein oman MatrixFilter -luokan, joka sisälsi kaiken tarvittavan tiedon matriisista: sen nimen, itse matriisin, loppukertoimen, kohdekanavien (R, G, B) ja totuusarvon määrittämään kummassa väriavaruudessa kuvaa suodittiin – RGB:ssä vai HSV:ssä. Lopputuloksena ei tarvinnut kuin lisätä uusi instanssi listaan ja rivi pixelfilter.txt:hen niin operateFilter teki taikansa ilman muuta säätöä. Lisäksi kiersin tehtävänannossa mainitun reunaongelman teeskentelemällä kuvan jatkuvan samana reunojen yli.

FFT

Puolitiehen jätetty kuva, joka on käynyt kerran FFT:n läpi ja saanut reunojensiirron

FourierFilter muokkasi kuvia taajuusavaruudessa, ja se oli aivan yhtä selkeä asia kuin miltä kuullostaakin. Onneksi FFT-muunnoksia ei tarvinnut itse keksiä, vaan ohjeita orjallisesti noudattaen lopuksi voi huomata koodin toimivankin vaikka teoria menisikin ohitse. Yllä oleva kuva ei tietenkään ole riittävä alkuperäisen auringonkukan muodostamiseen, sillä FastFourierTransformin jälkeen kuva on jaettu kahteen osaan: reaali- sekä imaginääriosaan. FourierFilter käytännössä kertoo FFTn jälkeisiä arvoja (reaali ja imaginääri) ja sitten muuntaa kuvan takaisin ymmärrettävään muotoon.

Esimerkkejä taajuusavaruuden suotimista:

Notch

Notch

Lowpass

Lowpass

Highpass

Highpass

Ring

Ring

Bonus! Aaltokuvio joka syntyi kirjoitusvirheen ansiosta. Maskia ei voi näyttää, sillä se ylitti reaalimaailman rajat.

Waves

Waves

Tehtävässä oli myös ongelma ratkottavana: kuinka puhdistaa “vahingoittunutta” kuvaa taajuusavaruuden avuin.

Image

Virheellinen kuva taajuusaravuutensa kanssa.

Itse sain jotain aikaan poistamalla pikselirykelmiä, jotka selkeästi poikkesivat alkuperäisestä kuvasta.

Korjailtu kuva

Korjailtu kuva

Kun tehtävän haastavuudesta selvisi, oli se yllättävän hauska; kuvia sai muokattua ihan itse monilla eri tavoin ja tulevaisuudessa muistan kyllä miten matriisifiltterit toimivat.

Tehtävä 2 – Koodaus ja dekoodaus

Kakkoskierroksella tehtävänä oli toteuttaa metodeita, joiden avulla voidaan luoda bittijonolle toistokoodaus, tai dekoodata tälläinen bittijono. Piti myös toteuttaa metodit, joiden avulla pystytään luomaan virheitä erinäisillä parametreillä mallintamalla, sekä selvittää tuntemattoman bittijonon sisältö.

Ensivaikutelma tehtävästä oli erittäin positiivinen! Kunnolla koodaamista, erittäin mielenkiintoinen aihe, kohtuullisen vapaat kädet silti ohjeistuksen ollessa selkeää.. Mitä muuta olisi voinut haluta? Ylimääräistä aikaa kenties, mutta tehtävä oli itsessään todella hauska toteuttaa. Etenkin digitaaliarkeologia antoi mukavaa haastetta, ja oli varsin hauska osa tätä kierrosta. Veikkaan kuitenkin, että ohjelmoinnin aloittelijoille tehtävä varmasti aiheutti enemmän kuin tarpeeksi ongelmia, jos siinä oli hieman mietittävää jo kokeneemmallekin koodarille.

Muistelisin, että kuvan käsitteleminen virheillä ja virheistä selviytymisen tutkiminen käytännön kautta oli varsin hauskaa. Scalan syntaksi tuli huomattavasti tutummaksi ja “bittijonojen” käsittely on aina hyvää harjoittelua. Tehtävä myös laittoi miettimään tehokkaampia ratkaisuja ja hieman kiinnostumaan siitä, miksi tämmöisiä ongelmia kohdataan ja kuinka olennaista niihin varautuminen on. Kaiken kaikkiaan tämä oli todella hauska, vaikkakin hieman työläs tehtävä.

– Esa Koskinen

Tehtävä 5 – Tietokonegrafiikka ja vuorovaikutus (Sokoban)

Kurssin viidennen kierroksen harjoitustyön aiheena oli ohjelmoida yksinkertaistettu versio klassikoksi muodostuneesta Sokoban-ongelmanratkaisupelistä. Sokobanissa pelaaja siirtelee laatikoita tai muita vastaavia esteitä ennalta määrättyihin paikkoihin, ja pelin läpäistäkseen pelaajan on saatava siirrettyä kaikki laatikot merkityille paikoille. Pelin osatehtävien ratkaisemiseksi pelaajan täytyy aina miettiä, millaisia seurauksia tietyn esteen siirtämisellä on jatkoa ajatellen.

Scala-muotoinen ohjelmointitehtävämme oli tosiaankin karsittu versio alkuperäisestä esikuvastaan, sillä meidän versiossamme pelin osatehtävien läpäisemiseksi riitti ainoastaan esteiden siirteleminen pois kulkuväylältä siten, että pelaaja pääse maaliin. Tämän kertainen koodaustehtävä oli täysin erilainen kuin edellisen kierroksen kuvasuotimien kanssa puuhastelu. Kuvakoodauksen jäljiltä minulla, jolla ei ennen Otaniemeen ja Tikille tuloa ollut mitään aikaisempaa kokemusta ohjelmoinnista, oli varsin kaksijakoiset tuntemukset ohjelmoinnista. Toisaalta oli onnistunut fiilis, kun olin saanut aluksi ylipääsemättömän vaikealta tuntuneen tehtävän kunnialla tehtyä. Toisaalta oli vähän sekavat tuntemukset siitä, että tälläistako ohjelmointi sitten ylipäätänsä tulee olemaan, sekavaa ja raskasta. Onneksi tämän viidennen kierroksen Sokoban oli lähempänä sitä, mitä olin ehkä jonkin verran ohjelmoinnilta odottanutkin, vaikka sisältyyhän koodaamiseen paljon muutakin kuin graafisten käyttöliittymien parissa työskentelyä.

Tämän kertaisen näpyttelyn tehtävänanto oli jo mielestäni sitä tasoa, jota voisi ohjeistukselta odottaakin; selkeä ja kattava. Lisäksi kierrokseen liittyvän OLO-tapaamisen virike antoi perustietoa piirtämiseen tarkoitetun Graphics2D-luokan käytöstä, jota hyödynnettiin Sokobanin graafisen ilmeen muodostamisessa. Ohjelmointi 1 -kurssilla graafisia käyttöliittymiä oli jo aikaisemmin sivuutettu hiukan, mutta sen enemmin niistä tiedoista ei tässä tehtävässä ollut apua.  Näillä perusteilla ryhdyin tuottamaan tehtävän vaatimaa koodia ja aluksi tehtävä tuntuikin haastavalta,  mutta kun aiheesta sai kunnon otteen ja teki omaa etsivän työtä, alkoi koodia syntyä tasaiseen tahtiin. Tehtävän suorittamisen kannalta varmasti eniten haasteita tuotti siis se, että Scalan Swing-kirjaston oma dokumentaatio ei näin aloittelevan ohjelmoijan näkökulmasta ole se kaikkein selkein ja yksinkertaisin opas. Pulmien ratkaisemiseksi jouduinkin käyttämään huomattavan paljon Googlea apunani, jotta Eclipsen antamista virheviesteistä päästiin eroon. Assareiden antamaa apua ei pidä sitäkään yhtään vähätellä, sillä ilman heitä tämän kurssin suorittamisesta ei yksinkertaisesti tulisi yhtään mitään.  Tehtävä itsessään ei siis loppujen lopuksi ollut edes kovin vaikea, mutta ensikertalaisen alkuhaparoinnit tuottivat aluksi mutkia matkaan eikä tehtävänannon kuvan mukaiselta reaktioltakaan voitu välttyä, mutta onneksi virheet oli helposti löydettävissä ja korjattavissa. Suurimmat ongelmat johtuivatkin siis Swing-kirjaston dokumentaation auttamattomasta köyhyydestä, tai ehkä en vain osannut hyödyntää sen kaikkea potentiaalia.

Tehtävän palauttamisen jälkeen miettiessäni, mitä kierroksesta oli jäänyt käteen, pystyin rehellisesti toteamaan, että aika paljonkin. Opin nimittäin käyttämään Graphics2D:tä ja Scalan Swingiä perustasolla, ja näitähän tullaan hyödyntämään myös kurssin seuraavalla ja samalla myös kurssin päättävällä ohjelmointikierroksella, jossa koodataaan yhteensä kolme pientä peliä ja omien mieltymysten sekä taitojen mukaan myös lisäpelejä.

Tässä vielä lopuksi kuvakaappaus omasta tuotoksestani tältä harjoituskierrokselta. Aikaansaannokseni ei kuitenkaan ole se kaikkein kaunein monipuolisin toteutus, jonka tehtävänannon puitteissa olisi voinut koodata, mutta aikaa on aina rajallinen määrä ja haasteiden tuomat viivästykset syövät sitä yleensä yllättävän paljon. Nyt voin kuitenkin luottavaisin mielin jatkaa kohti finaalikierrosta. 🙂

Kierros 5 - Sokoban


Markus Pajari