Billedmanipulation - Processing

I programmeringsmiljøet processing er det forholdsvist enkelt at loade og manipulere billeder. Det er et sandkassemiljø baseret på java udviklet som undervisningsmiljø til studerende i kommunikation, kunst, design m.m. Den danske kunstner Mogens Jacobsen har skrevet en fin, dansk introduktion til miljøet.

Når man har styr på basal processing, kan man gå videre med nedenståen opgaver, hvor man trin for trin ændrer på og laver filtrer der manipulerer et billede. Start med at downloade og afprøve programmet, gå i gang med opgaverne en efter en og slip til sidst fantasien løs og lave dine helt egne, vilde billedfiltre!

billedprogramStart.pde

Processing

The Nature of Code: Gratis, interaktiv bog målrettet niveauet efter basal programmering. Den introducer vektorer & objekter i processing og går derefter videre til emner som Fysiske love; Oscillation; Fraktaler m.m.

FYProcessing: Samling af særligt spændende projekter lavet i processing.

Funprogramming: Videoer der introducerer programmering i processing med fokus på det visuelle.

Javabog.dk: Klassisk introduktion til Java på dansk fra betingelser helt til flertrådet programmering… Kan også bruges i uddrag til javabaserede miljøer som Processing og Greenfoot…

Processing & Arduino: Bibliotek til programmering af arduino via processing



Opstart

Optimering af funktioners start

  1. Opret de to indbyggede funktioner void mouseClicked(){} og void mouseMoved(){}
  2. Klip forgreningen ud der starter filtre i draw, og kopier den ind i de to funktioner.
  3. Noter hvordan filteret støj ændrer sig - hvornår kører det nu?
  4. Skriv en forklaring på hvorfor det sker og hvorfor der er bedre end bare at lade dem kører i draw().
  5. Slet funktionerne i mouseMoved, hvor der ikke sker en ny beregning (nyt billede) når musen flyttes
PImage billed;
int aktueltFilter = -1;
 
void setup() {
  billed = loadImage("langbold2.jpg");
  size(billed.width, billed.height+50);
}
 
void draw() {  
    knap(0,"Stoej");
    knap(1,"Pixelering"); 
    knap(2,"Lys"); 
    knap(3,"Motionblur"); 
 
    if(aktueltFilter == 0){
      stoej();
    }else if(aktueltFilter == 1){
      pixelering();
    }else if(aktueltFilter == 2){
      lys();
    }else if(aktueltFilter == 3){
      motionBlur();
    }else{
      image(billed, 0, 0);
    }
}

Knapper

Tilpas knapperne

  • Ændr på farve
  • Ændre på størrelse
  • Ændr på form

Tilføj knap/filter

  1. Gå ind i Draw og indsæt en fjerde ekstra knap, der hedder "Meget støj".
  2. Ændr herefter forgreningen lige nedenunder, så funktionen "megetStoej()"startes når aktueltFilter er 4.
  3. Lav nu en kopi af filteret Stoej() og indsæt det lige nedenunder.
  4. Ændr det navn til megetStoej() og ændr random fra 10 til 20.

For mange knapper/lidt bredde?

Sørg for at knapperne sættes i to eller flere rækker.

  1. Lav en betingelse så kun de første 5 knapper laves som før
  2. De næste knapper lægges eks. 20 ekstra til knapY
  3. Afprøv og du vil se at knapperne tegnes nedenfor
  • Står knapperne forkert?
    • Tegnes de for langt inde, så sørg for at trække fra variablen aktueltFilter
    • Tegnes de udenfor skærmbilledets højde - så juster size() i Setup()
  • Virker de nye knapper ikke?
    • Har du husket at gange variablen nr på betingelsen i mousePressed()?
void knap(int nr, String tekst){
  int knapBredde=70;
  int knapHoejde=20;
  int knapY=billed.height+10;
 
   fill(50);
   rect(nr * knapBredde+5, knapY, knapBredde, knapHoejde); 
 
   fill(255);
   text(tekst, nr * knapBredde+10, knapY+15);
 
   if(mousePressed == true
      && nr * knapBredde < mouseX 
      && mouseX < (nr+1) * knapBredde 
      && knapY < mouseY           
      && mouseY < knapY+knapHoejde)
   { 
     aktueltFilter = nr; 
   }
}

Filtre: pixels placering

Støj

  • Ændre mængden af støj
  • Udvid så der også er støj iforhold til y-akse
  • Lav støjniveau følge mus' position
  • Håndter kanter: hvad skal der ske, hvis random() giver en positon uden for billedet?

Spejl

Indsæt pixels i modsatte rækkefølge i forhold til bredden

  1. Kopier koden for stoej.
  2. Giv den et nyt navn og tilføj knap i draw
  3. Ændr koden, så nyX sættes til billedets bredde - x
void stoej(){
 
  for(int y = 0; y < billed.height; y = y + 1){
 
    for(int x = 0; x < billed.width; x = x + 1){
 
      int nyX = x + int(random(10));
      color hentFarve = billed.get(nyX, y);
      set(x, y, hentFarve);
 
    }
  }
}
  • Sørg for at spejlingen kun sker når musen er over billedets midte
  • Lav flip, hvor det er y-aksen der byttes om på.
  • Kombiner spejl og flip, så der spejlvendes og/eller flippes efter musens position

Symmetrisk spejl

Som spejl men lad, den ene halvdel tegnes almindelig, mens den anden spejles…


Filtre: form

Pixelering

  • Ændre graden af pixelering ved at gøre størrelsen større/mindre
  • Lad graden af pixelering følge mus' position - divider ned, hvis det er for følsomt
  • Håndter kanter: hvad skal der ske, hvis de ydereste pixels går ud over billedets størrelse?
  • Lad bredde afhænge af mouseX og højde af mouseY
  • Surprise - der tegnes kun, hvor musen har været over…
  • Reel pixelering: udregn og vis gennemsnitte af farveværdierne i stedet for blot at forstørre den første pixel.
void pixelering(){
  int stoerrelse = 10;
  for(int y = 0; y < billed.height; y = y + stoerrelse){
    for(int x = 0; x < billed.width; x = x + stoerrelse){
      fill(billed.get(x, y));
      stroke(billed.get(x, y));
      rect(x, y, stoerrelse, stoerrelse);      
    }
  }
}

Linier

  1. Kopier pixelering(), giv den et nyt navn og tilføj knap i draw()
  2. Slet x-forløkken
  3. Hent farve fra 0, y
  4. Tegn en linje i billedets bredde

Andre former

Kopier pixelering() og ændr den så der tegnes cirkler, trekanter… i stedet


Filtre: pixels farve

Justering af lys

  • Lad lysniveau følge mus' position
  • Animer dagens gang

Farvefiltre

Vis kun udvalgte farver fra et billede

  1. Kopier koden for lys.
  2. Giv den et nyt navn og tilføj knap i draw().
  3. Ændr koden, så der kun vises én af farvetonerne - sæt de andre til nul
  • Farveblind - vis gennemsnittet af rød og grøn i rød og grøn—-
  • Gråtonefilter - vis et gennemsnit af de tre farver
  • Lav andre farvefiltre som sepia, tusmørke, solopgang… ved at gange de tre farvetoner med tal mellem 0 og 1
  • Lav et filter der farvetoner efter mus position
void lys(){
  float lys = 0.5;
 
  for(int y = 0;y < billed.height; y = y + 1){
    for(int x = 0;x < billed.width; x = x + 1){
      color hentFarve = billed.get(x, y);
 
      float nyRoed = red(hentFarve)*lys;
      float nyGroen = green(hentFarve)*lys;
      float nyBlaa = blue(hentFarve)*lys;
 
      color nyFarve = color(nyRoed, nyGroen, nyBlaa);
 
      set(x, y, nyFarve);
    }
  }
}

Gennemsigtighed

Læg to billeder sammen og divider med 2

  1. Kopier koden for lys(), giv nyt navn og tilføj knap i draw
  2. Sørg for at der oprettes og loades et ekstra billede i setup
  3. Ændr koden for lys, så der hentes farve fra begge billeder
  4. Ændr koden, så farverne i de to billeder lægges sammen og divideres med 2
  • Lav en WARP - glidende overgang mellem de to billeder - enten animeret eller efter mus' position
  • Lav en funktion der kombinere en eller to af billedernes - hvad med rød fra et billede, grønt fra et andet og blåtfra et tredje?

Filtre: foldningsmatrix

Motionblur

Øg antallet af pixels der bruges til 5 - overvej hvad der skal hentes når filteret når til kanten af billedet

  1. Lav en variable antalPixels
  2. Opret de tre variabler til farver som før men sæt dem til 0 fra start.
  3. Lav en forløkke, der kører antalPixels gange
  4. I forløkken hentes farveværdien for x + antalPixels, og de tre farver tælles op med den aktuelle værdi
  5. Efter forløkken sættes nyFarve til de optalte farveværdier / antalPixels
  6. Den aktuelle pixel sættes til den ny farveværdi
  • Lad variablen antalPixel afhænge af mouseX - juster evt. følsomhed ved at dividere ned

Lodret motionblur

  1. Kopier koden for motionBlur(), giv nyt navn og tilføj knap i draw().
  2. Ændr' koden til at arbejde på y istedet for x

Andre foldningsmatricer

Som motionBlur, kan de andre filtre beskrevet i foldningsmatricer implementeres

void motionBlur(){
  for(int y = 0;y < billed.height; y = y + 1){
    for(int x = 0;x < billed.width; x = x + 1){
      color hentFarve = billed.get(x, y);
      color hentFarveV1 = billed.get(x-1, y);
      color hentFarveH1 = billed.get(x+1, y);
 
      float nyRoed   = (red(hentFarve)   + red(hentFarveV1)   + red(hentFarveH1))/3;
      float nyGroen  = (green(hentFarve) + green(hentFarveV1) + green(hentFarveH1))/3;
      float nyBlaa   = (blue(hentFarve)  + blue(hentFarveV1)  + blue(hentFarveH1))/3;
 
      color nyFarve = color(nyRoed, nyGroen, nyBlaa);
 
      set(x, y, nyFarve);
    }
  }
}

Optimering

Brug den indbyggede pixel-tabel - pixels[blurPixel] - til at optimere hastigheden med. Alt efter filter, billedstørrelse & computer øger det hastigheden med 20-40%. - Ved foldningsmatrix, skal du bruge billede.width til udregne, hvor de omkringstående pixels er.

Medmindre andet er angivet, er indholdet af denne side licenseret under Creative Commons Attribution-NonCommercial 3.0 License