Kuvataide ja ohjelmointi

Johdanto

Tähän mennessä tällä polulla on ohjattu visualisoimaan omia haaveita ja havaintoja ohjelmoimalla. Ohjelmoidessa kaikkea ei kuitenkaan tarvitse keksiä itse. Olet tähän mennessä saattanut käyttää tukenasi tämän oppimateriaalin lisäksi esimerkiksi muiden opettajien ideoita sekä Processing reference -sivustoa. Ohjelmoijan onkin tärkeää oppia hyödyntämään lähiyhteisön ja internetin voimavaroja. Voimavarat voivat toisinaan olla valmista koodia, toisinaan taas esimerkiksi kuvallisia tai tekstuaalisia aineistoja.

  • Idea: Tee oma runokone teksti- ja kuva-aineistoja hyödyntäen. Etsi ensin työllesi taustan taidemuseoiden avoimista arkistoista. Sitten lisää mukaan valitsemiasi sanoja, joita arvotaan taustan päälle. Näin samalla myös häkätään museoituja taideteoksia uuteen uskoon, uutta ja vanhaa kunnioittavasti yhdistäen.
Pohdintaruutu
Tutustu Sanataideyhdistys Yöstäjän sivuilta löytyvään haikuja kirjoittavaan runorobottiin ja kokeile sitä muutamilla sanoilla. https://www.yostaja.fi/runorobotti
Miten arvelet generaattorin toimivan? Runoudessa tärkeää on myös sanojen visuaalinen asetelma ja järjestys. Minkälainen kuva sopisi näiden haikujen taustaksi?

Avoimia arkistoja

Avoimet digitaaliset arkistot?
Viime aikoina taidetta ja kulttuuria on koottu kasvavissa määrin digitaalisiin arkistoihin. Osa hankkeista on ollut laajoja ja kansallisia, mutta arkistointia ovat tehneet myös yksittäiset taidemuseot ja toimijat. Tavoitteina on ollut kulttuuriperinnön säilyttäminen ja sen saavutettavuuden parantaminen. Toisaalta avoimet arkistot mahdollistavat myös luovan jatkokehittelyn ja julkaisun silloin, kun teosten lisenssit sen sallivat. Esimerkiksi Hack4FI-tapahtumassa on jo vuosia kehitelty ja häkätty taideteoksia!
Vaihe 1
Tutki hieman avoimia taidearkistoja. Kaikki kolme alla esiteltyä arkistoa sisältävät hakutoiminnon, jolla teoksia voi helposti etsiä niiden nimen tai tekijän avulla.
  • Yhdysvaltalaisen Metropolitan Museum of Artin aineiston etu on sen pökerryttävä laajuus, sillä mukana on teoksia ympäri maailmaa tuhansien vuosien ajalta. Iso osa varsinkin vanhemmista teoksista on myös julkaistu avoimella CC0-lisenssillä, joten niiden muokkaaminen ja julkaisukin on täysin vapaata!

  • Europeanaan on koottu Eurooppalaista kulttuuriperintöä.

  • Suomessa  Kansallinen digitaalinen kirjasto -hankkeessa on koottu paljon aineistoa Finna-palveluun. Finnasta löytyy kuvallisten aineistojen lisäksi esimerkiksi kirjoja, lehtiä ja äänitteitä. 

Vaihe 2

Etsi jokin sinua kiinnostava graafinen teos, joka voisi sopia runogeneraattorisi taustaksi. Teoksesta pitäisi siis löytyä väljempiä kohtia, johon sanat voisivat ilmestyä.

Tarkista teoksen lisenssi. Alla on näytetty, miten näet teoksen lisenssin Metropolitan Museum Of Artin akistossa.

Lataa kuva tietokoneellesi. Nimeä kuva myöhempää käyttöä varten jollain yksinkertaisella tavalla, esimerkiksi "tausta".

Tallenna linkki teokseen itsellesi johonkin. Tarvitset sitä osana työsi dokumentointia.


Kuvan lisääminen

Olet aiemmin kuvataiteen ja ohjelmoinnin polulla luonut erilaisia maisemia muoto kerrallaan. Tällä tavoin voit vaihtaa muotojen värejä ja kokoa dynaamisesti ja luoda jotain elävää. Joskus on kuitenkin paikallaan lisätä valmis kuvatiedosto työhösi. Tämä mahdollistaa myös itse tehtyjen maalausten, valokuvien ja piirrustusten käytön osana digitaalisia teoksiasi. 

Vaihe 3

Avaa Processingissa tyhjä ikkuna (File -> New), ja tallenna työsi jollain nimellä (File -> Save As), esim. "runogeneraattori".
Tallennuksen oletussijaintina on luultavasti Processingin Sketchbook, jonne luotiin nyt kansio työsi nimellä. Löydät Sketchbookin sijainnin kohdasta File -> Preferences -> Sketchbook Location.

Jotta kuvan tuominen osaksi Processing-työtä on mahdollista, täytyy meidän ensin siirtää valitsemasi kuva Processingin ohjelmakansioon. Klikkaa Sketch -> Add File ja etsi lataamasi kuva.  Processing loi työsi kansioon Data-kansion, ja kopioi kuvan sinne. Kuvan ei vielä ole tarkoitus ilmestyä ruudulle, koska emme ole käyttäneet mitään ohjelmointikomentoja. Tätä pääset tekemään seuraavaksi.

Vaihe 4

Lisää kuva ohjelmasi taustaksi. Tämä hoituu kolmella komennolla, jotka löydät sivun alalaidan ohjelmasta.

Aivan ylälaidassa sinun tulee luoda PImage-tyypin objekti ja nimetä se.

Setup-osassa sinun pitää ladata tähän objektiin aiemmin valitsemasi kuva loadImage-komennolla. Huom: tarkista kuvatiedoston nimen kirjoitusasu ja kirjoita koodissa nimen perään myös tiedostotyyppi (esim. .jpg tai .png). Tiedostotyypin löydät Windowsissa alla  olevassa animaatiossa näytetyllä tavalla. Nimi pitää kirjoittaa tismalleen oikein, jotta koodi toimii.

Setup-osassa kuva lisätään piirtoikkunaan image-komennolla.

// Luodaan PImage  (Processing Image) -tyypin objekti ja annetaan sen nimeksi "tausta"
PImage tausta;

void setup() {
  size(800, 800);         
  // Tarkista kuvatiedoston nimi koneellasi ja kirjoita se tismalleen samalla tavalla
  tausta = loadImage("tausta.jpg");
  // Lisätään kuva piirtoikkunaan. Kuvan vasen yläkulma on pisteessä (0, 0) eli piirtoikkunan vasemmassa yläkulmassa.
  image(tausta, 0, 0); 
}

void draw() {
  // Draw-osa on toistaiseksi tyhjä. 
  // Kun ohjelma käynnistetään, suoritetaan siis vain setupissa olevat komennot kerran läpi.
}

Kuvan koon säätäminen

Kuva on todennäköisesti liian suuri eikä sovi piirtoikkunaasi. Jos kuva on liian pieni, kannattaa valita toinen kuva, sillä kuvan suurentaminen heikentää sen laatua. 

Vaihe 5
Pienennä kuva, jos se on tarpeen. Voit käyttää jotakin kuvankäsittelyohjelmaa (esim. Paint) tai sitten jotakin selainpohjaista työkalua, joista alla linkattu Simple Image Resizer on kätevä. Ohjeet kuvan koon muuttamiseksi Simple Image Resizerilla löydät alla olevasta animaatiosta.
http://www.simpleimageresizer.com/

Kun olet tehnyt kuvasta järkevämmän kokoisen, siirrä se Processing-ohjelmasi data-kansioon ja nimeä se jollakin yksinkertaisella tavalla. Voit korvata kuvalla vanhan vääränkokoisen kuvan.

Suorita ohjelma uudestaan. Jos nyt puolestaan piirtoikkuna on väärän kokoinen, voit vaihtaa sen kokoa muuttamalla size-komennon parametrejä. Kuvan tarkan koon näet vilkaisemalla kuvan asetuksia.

Tekstiä mukaan!

Vaihe 6
Lisää ohjelmaasi mouseClicked-osa, jonka sisältö suoritetaan aina, kun klikkaat hiirtäsi piirtoikkunan päällä (painat pohjaan ja päästät ylös).

Lisää mouseClicked-osaan text-komento, joka kirjoittaa haluamasi tekstin piirtoikkunaan satunnaiseen kohtaan. Kokeile ohjelmaasi. Tekstin pitäisi ilmestyä uuteen kohtaan aina hiirtä klikattaessa

Teksti on todennäköisesti hyvin pientä. Säädä tekstin koko sopivaksi lisäämällä textSize-komento setup-osaan. 

Voit vaihtaa tekstin värin lisäämällä mukaan fill-komennon. Fill-komennon on turvallisinta olla ennen text-komentoa mouseClicked-osassa. Jos vaihdat väriä muualla ohjelmassa myöhemmin toiseksi, vaihtuu se näin aina ennen tekstin kirjoittamista haluamaksesi.
PImage tausta;

void setup() {
  size(586, 774);
  loadImage("tausta.jpg");
  image(tausta, 0, 0);
  // Tekstin kooksi 40.
  textSize(40);
}

void draw() {
  
}
// mouseClicked-osan komennot suoritetaan aina kerran silloin, kun hiirtä klikataan.
void mouseClicked(){
  // Vaihdetaan tekstin väri valkoiseksi. 'fill(255)' ajaa saman asian.
  fill(255, 255, 255);
  // Lisätään teksti "Moi!" satunnaiseen kohtaan piirtoikkunaa. Koordinaatit osoittavat tekstilaatikon vasemman yläkulman.
  text("Moi!", random(0, 586), random(0, 774));
}
Vaihe 7
Nyt kaikki aiempi teksti jää näkyviin kuvan päälle. Lähdetään tekemään runogeneraattoria, joka näyttää aina vain viimeisimmäksi lisätyn tekstin.

Lisää image-komento mouseCliked-osan alkuun. Nyt uusi kuva lisätään aina kaiken aiemman päälle hiirtä klikattessa. Vasta tämän jälkeen kuvan päälle lisätään uusi teksti. Siksi näkyvillä on vain yksi sana kerrallaan.
    PImage tausta;

    void setup() {
      size(586, 774);
      tausta = loadImage("tausta.jpg");
      image(tausta, 0, 0);
      textSize(40);
    }

    void draw() {
      
    }

    void mouseClicked(){
      // Lisätään kaiken aiemman päälle aina uusi kuva, kun hiirtä klikataan.
      image(tausta, 0, 0);
      fill(255, 255, 255);
      text("Moi!", random(0, 586), random(0, 774));
    }

Sanalistan muodostaminen

Seuraavaksi käyttöön otetaan listat (Array). Muodostamme sanoista listan, minkä jälkeen voimme arpoa listasta sanoja ja lisätä niitä piirtoikkunaan. Listoja voisi sanojen lisäksi tehdä myös esimerkiksi numeroista tai kuvista. Listat ovat osa kaikenlaista ohjelmointia ja datankäsittelyä.

Vaikka et ymmärtäisikään listojen toimintaa läpikotaisin tämän harjoituksen aikana, sen ei tarvitse hidastaa sinua visiosi toteuttamisessa. Valmiin koodin hyödyntäminen on osa häkkäämisen henkeä, ja tärkeintä on, että seuraavan kerran ohjelmoidessasi tiedät ainakin hieman enemmän aiheesta kuin aiemmin. Kysy silti, jos asiat tuntuvat liian epäselviltä!

Vaihe 8
Kopioi alla oleva koodi ja tutustu sen kommentteihin. 

Ylälaidassa luodaan sanoista lista. Muokkaa listan sanoja haluamiksesi! Koeta keksiä teoksesi tunnelmaan sopivia sanoja.

mouseClicked-osassa arvotaan listasta aina uusi sana, ja lisätään se haluttuun kohtaan piirtoikkunaa. Valitse haluamasi kohta muokkaamalla text-komennon parametrejä.
PImage tausta;
// Luodaan merkkijonoista (String) koostuva lista 'subjektit' ja tallennetaan siihen joukko sanoja.
// Sanat tallennetaan listaan erillisinä paketteina. 
// Esimerkiksi "hän" on nyt subjektit-listan ensimmäinen sana, ja siihen voi viitata kirjoittamalla subjektit[0]. 
// Vastaavasti "lapsi" on subjektit[1] ja "kissa" subjektit[2]. 
String[] subjektit = {"hän", "lapsi", "kissa", "kuu", "aurinko", "päivä", "ilta", "ilmastonmuutos", "historia"};

void setup() {
  size(586, 774);
  tausta = loadImage("tausta.jpg");
  image(tausta, 0, 0);
  textSize(40);
}

void draw() {
      
}

void mouseClicked(){               
  fill(255, 255, 255);     
  // Luodaan kokonaislukuuttuja 'sub' ja tallennetaan siihen satunnaisluku, joka on maksimissaan sanojen määrä subjektit-listassa. 
  // Satunnaisluku on desimaalimuotoinen, ja siitä tehdään kokonaisluku int-komennolla.
  int sub = int(random(subjektit.length));
  // Valitaan sub-muuttujan avulla satunnainen sana listasta ja lisätään se kohtaan (400, 400)
  text(subjektit[sub], 400, 400);
}

Sanoista lauseiksi

Vaihe 9
Lisää mukaan ainakin kaksi uutta sanalistaa. Alla on luotu malliksi listat 'verbit' ja 'adverbit', mutta voit pohtia myös muunlaisia lauserakenteita. Runoudessa sanat luovat merkityksiä, vaikka ne eivät muodostaisikaan lauseita perinteisessä mielessä.

Arvo näistä sanalistoista sanat ruudulle aina hiirtä klikattaessa. 

Asettele sanat piirtoikkunaasi siten, että ne muodostavat yhdessä jonkinlaisen lauseen, merkityksen tai sommitelman.
Haiku, meemi, juliste vai mikä?
Satunnaisesti generoidun viestin ja kuvan yhdistäminen voi sopia monenlaisiin tyylilajeihin. Työsi tunnelmaan vaikuttaa paljon valitsemasi tausta. Jos käytät harrasta maisemamaalausta, saattaa se viedä työtä vertauskuvalliseen tai vaikka (kansallis)romanttiseen suuntaan. Jos teoksessa on eläin, ihminen tai jokin muu hahmo, saatetaan se helposti tulkita tekstin puhujaksi. Tällöin teos saa helposti sarjakuvamaisia tai meemimäisiä piirteitä. Myös tekstin asettelulla ja erilaisilla tekstin persoonamuodoilla voi ohjata tulkintaa.

PImage tausta;
String[] subjektit = {"hän", "lapsi", "kissa", "kuu", "aurinko", "päivä", "ilta", "ilmastonmuutos", "historia"};
// Luodaan samalla periaatteella kaksi muuta sanalistaa, verbit ja adverbit.
String[] verbit = {"juoksee", "roikkuu", "pohtii", "hamuaa", "kaipaa", "etsii", "löytää", "muistaa", "hyppii", "oppii"};
String[] adverbit = {"kauniisti", "etsien", "jo", "yhä", "lopullisesti", "raskaasti", "vauhdilla", "määrätietoisesti", "empien"};

void setup() {
  size(586, 774);
  tausta = loadImage("tausta.jpg");
  image(tausta, 0, 0);
  textSize(40);
}

void draw() {
      
}

void mouseClicked(){   
  image(tausta, 0, 0);     
  // Asetetaan tekstiä varten täyttöväriksi valkoinen.        
  fill(255, 255, 255);     
  int sub = int(random(subjektit.length));
  text(subjektit[sub], 400, 400);
  // Arvotaan myös verbeistä ja adverbeistä yksi sana ruutuun. 
  // Verbi ilmestyy kohtaan (400, 450) ja adverbi sen alle kohtaan (400, 500).
  int ver = int(random(verbit.length));
  text(verbit[ver], 400, 450);
  int adv = int(random(adverbit.length)); 
  text(adverbit[adv], 400, 500);
}

Viimeistely ja ekstra

Joskus on kätevää ottaa kuvakaappauksia omista töistä. Tässä ohje! 

Vaihe 10

Lisää mouseClicked-metodin loppuun  komento saveFrame, joka tallentaa kuvakaappauksen työsi kansioon aina hiirtä klikattaessa. Löydät tallennetut kuvat tallentamasi Processing-työn kansiosta. Jos et ole varma missä työsi kansio on, katso Sketchbookin sijainti kohdasta File -> Preferences -> Sketchbook location.

Extra

Voit vaihtaa Processingissa tekstisi fonttia. Ihan hyvä ohjevideo täällä:
https://www.youtube.com/watch?v=CWlyzxnB-1g

Lisää mukaan häivytysefekti! Tämä on kätevintä hoitaa tekemällä kuvasta osittain läpinäkyvä tint-komennolla. Lisää draw-osaan seuraavat komennot. Nyt uusia kuvia ilmestyy ruutuun jatkuvasti, mutta ne ovat hyvin läpinäkyviä ja tuloksena on tekstien vähittäinen häipyminen!

tint(255, 5);        // Kuvan piirtoväri valkoinen (neutraali), peittävyysarvo 5.
image(tausta, 0, 0);

Ladatun kuvan pikseleiden kokoa ja värejä voi käsitellä Processingissa monella tapaa, ohjeita täällä:
https://www.youtube.com/watch?v=j-ZLDEnhT3Q
https://processing.org/tutorials/pixels/

Lisää hauska kuva jonkin aiemman kurssiharjoituksesi taustalle. Tai korvaa kolmannessa luvussa liikuttelemasi muoto pienennetyllä kuvalla. Kuvaa voi liikutella aivan samoin kuin vaikka ellipsiä tai suorakulmiotakin!

Jos haluat muodostaa kokonaisen tekstitiedoston sanoista listan Processingissa, löydät välineet siihen täällä linkatussa koodissa. Esimerkiksi Shakespearen tuotantoa löydät Public Domain -lisenssillä täältä. Kalevala puolestaan löytyy täältä, äläkä unohda esimerkiksi Finnasta löytyviä kirjallisia aineistoja!

Jos tekoälyn ja tietokoneen tuottaman tekstin tutkiminen kiinnostaa enemmän, niin löydät ohjeita siihen alta.

Extra: Tekoäly ja tekstin tuottaminen

Tässä projektissa olet arponut sanoja listoista ja asettanut niitä peräkkäin. Ylempänä linkatun koodin avulla voit muodostaa listoja jonkin valmiin tekstiaineiston sanoista. Vaikka tekisitkin tämän, on edessäsi kuitenkin seuraavanlaisia haasteita.

  • Miten tietokone voisi tunnistaa, onko sana substantiivi, verbi, pronomini vai adjektiivi?
  • Miten tietokone voisi tunnistaa, miten sanat lausutaan ja mitkä sanat rimmaavat keskenään?
  • Voisiko tietokone osata tulkita sanojen välittämää tunnetta ja esimerkiksi vaihtaa tekstin väriä tunnelman mukaan?
  • Voisiko tietokone tarvittaessa myös taivuttaa sanoja?

Yllä listatut asiat ovat ohjelmoinnin näkökulmasta jo huomattavasti mutkikkaampia kuin tämän projektin aikana ratkotut haasteet. Haasteita ei oikeastaan kannata lähteä ratkomaan itse tyhjästä alkaen. Huomattavasti järkevämpää on valita jokin valmis kirjasto, jossa on tarvittavia toimintoja. Kirjastolla tarkoitetaan ohjelmoinnissa joukkoa komentoja, jotka joku toinen on tehnyt valmiiksi.

Eräs hyvä kirjasto on RiTa – A software toolkit for computational literature. Alla olevasta linkistä löydät RiTa:n esittelysivuston.
https://rednoise.org/rita/

RiTa

RiTassa on oma kirjasto JavaSctiptille (rita.js), mutta myös Javalle. Koska Processing on Java-pohjainen kieli, tulee käyttää Java-kirjastoa. Lataa Java-kirjasto täältä:
https://rednoise.org/rita/download.php

Seuraavaksi sinun tulisi lisätä kirjasto eli rita.jar-tiedosto oikeaan paikkaan. Processingin kirjastot ovat samassa Sketchbookissa, johon työtkin tallentuvat. Niille on siellä oma libraries-kansionsa. Tarkista Sketchbookin sijainti valitsemalla File -> Preferences -> Sketchbook location.

Siirrä rita.jar-tiedosto libraries-kansioon. Luo libraries-kansioon rita-kansio ja sen sisälle vielä library-kansio. Tiedostopolun pitäisi siis olla seuraavanlainen: Sketchbook/libraries/rita/library/rita.jar

Tämän jälkeen voit valita Processingissa Sketch -> Import Library. rita-kirjaston pitäisi löytyä listasta. Klikkaa sitä.

Tutustu sitten Processing-esimerkkeihin RiTan Github-sivustolla täällä:
https://github.com/dhowe/RiTa/tree/master/examples/processing

Jokainen kansio on oma esimerkkinsä. Kansio sisältää .pde-päätteisen Processing-ohjelman, jonka koodin voi sellaisenaan kopioida Processingin editoriin. Tämän lisäksi kansio saattaa sisältää data-kansion, jossa on esimerkiksi käytettäviä tekstiaineistoja.

Monet esimerkit hyödyntävät valmiita tekstiaineistoja, kuten hupaisa Kafkan ja Wittgensteinin tuotantoa yhdistelevä Kafgenstein. Jos haluat kokeilla tätä esimerkkiä, sinun on varsinaisen koodin lisäksi kopioitava tekstiaineistot data-kansioon, aivan kuten teit mukaan tuomasi kuvankin kanssa.

Osa esimerkeistä ei kuitenkaan käytä tekstiaineistoja. Esimerkiksi rimmaavia sanoja etsivä RandomRhymes on katsomisen arvoinen!