Termin 5: Medienprogrammierung in Python Bildverarbeitung (2) Grundlagen der Informatik Wintersemester 2006/07 Prof. Bernhard Jung Übersicht Medienprogrammierung mit Python / JES z.b. Erzeugung von Negativen, Grauwertkonvertierung, Jes-Debugger for-schleifen in Python if-anweisung in Python Hauptlernziele: Verstehen zentraler Kontrollstrukturen der imperativen Programmierung for Schleife if else (bedingte Anweisung) Digitale Medien: Verständnis von Farb-, Grauwert-, und Binärbildern 1
Wiederholung Beispiel: Ändern von Pixel-Werten >>> filename = pickafile() >>> mypic = makepicture(filename) >>> show(mypic) >>> setcolor(getpixel(mypic, 10, 100),yellow) >>> setcolor(getpixel(mypic, 11, 100),yellow) >>> setcolor(getpixel(mypic, 12, 100),yellow) >>> setcolor(getpixel(mypic, 13, 100),yellow) >>> setcolor(getpixel(mypic, 14, 100),yellow) >>> setcolor(getpixel(mypic, 15, 100),yellow) >>> repaint(mypic) jetzt 6 gelbe Pixel hier Bildverarbeitung mit Schleifen - Definition eines Python-Skripts def decreasered(picture): value = getred(p) setred(p, value * 0.5) Verringerung des Rot-Anteils in jedem Pixel des Bilds for-schleife 2
Schleifen in Python Aufbau von Schleifen for Schlüsselwort, Name der Anweisung Indexvariable p Name der Variable kann frei gewählt werden in Schlüsselwort, fester Teil der Anweisung Eine Sequenz bzw. Ausdruck der eine Sequenz liefert getpixels(picture) liefert Liste aller Pixel zur Erinnerung (Vorlesung 3): Sequenz = Liste, String, oder Tupel Doppelpunkt ':' Rumpf der Schleife eingerückt hier besteht der Rumpf aus 2 Anweisungen Schleifen in Python for <variable> in <sequenz>: <anweisungen> for i in ['a','b','c']: print i 1. Schleifendurchlauf: i = 'a' Ausgabe: a 2. Schleifendurchlauf: i = 'b' Ausgabe: b 3. Schleifendurchlauf: i = 'c' Ausgabe: c 3
Schleifen in Python for <variable> in <sequenz>: <anweisungen> for i in [4,6,9]: print i 1. Schleifendurchlauf: i = 4 Ausgabe: 4 2. Schleifendurchlauf: i = 6 Ausgabe: 6 3. Schleifendurchlauf: i = 9 Ausgabe: 9 Der JES-Watcher (Debugger) Start des Watchers Hinzufügen einer zu beobachtenden Variablen (hier: i) 4
Beispiel Bildverarbeitung Generierung von Sonnenuntergängen Idee: Blau- und Grün-Anteile im Bild reduzieren (Rot wird so dominanter) def makesunset(picture): value=getblue(p) setblue(p,value*0.7) value=getgreen(p) setgreen(p,value*0.7) Beispiel Bildverarbeitung Generierung von Sonnenuntergängen die zuvor definierte Funktion makesunset() ist natürlich auf beliebige Bilder anwendbar dazu muss nur die Funktion nur mit einem anderen Input-Parameter aufgerufen werden def makesunset(picture): value=getblue(p) setblue(p,value*0.7) value=getgreen(p) setgreen(p,value*0.7) tu-baf.jpg 5
Die range()-funktion range()-funktion Generierung von Listen mit Elementen zwischen den beiden Input-Parametern optionaler dritter Input-Parameter bestimmt Inkrement >>> print range(1,4) [1, 2, 3] >>> print range(-1,3) [-1, 0, 1, 2] >>> print range(1,10,2) [1, 3, 5, 7, 9] Beispiel: range()-funktion 6
Indizierung von Pixeln Bild: Matrix von Pixeln Breite von Bildern: w = getwidth(picture) Höhe von Bildern: h = getheight(picture) Pixel können über ihren Index (x,y) referenziert werden pixel = getpixel( picture, x, y) Bildverarbeitung mittels geschachtelte Schleifen Geschachtelte Schleifen Schachtelung von Schleifen: Rumpf einer Schleife ist wiederum eine Schleife def increasered2(picture): for x in range(1, getwidth(picture)+1 ): for y in range(1, getheight(picture)+1 ): px = getpixel(picture,x,y) value = getred(px) setred(px, value*1.1) hier: spaltenweise Bearbeitung der Pixel Verarbeitungsreihenfolge der Indices (1,1), (1,2), (1,3). (2,1), (2,2), (2,3), (3,1), (3,2), 7
Farbersetzung in Teilbereichen von Bildern def increaseredinrange(picture, xmin, ymin, xmax, ymax): for x in range(xmin, xmax+1): for y in range(ymin, ymax+1): px = getpixel(picture,x,y) value = getred(px) setred(px, value*1.2) >>> increaseredinrange(pic2, 78, 41, 158, 59) Auswahl des Bildbereichs mittels MediaTools Beispiel Bildverarbeitung Erzeugung von Negativen R, G, B-Werte im Bereich 0.. 255 Negativ eines Pixels, z.b. (5,10,25): (255-5, 255-10, 255-25) = (250, 245, 230) Negativ eines Bilds: Negativ aller Pixel def negative(picture): for px in getpixels(picture): red=getred(px) green=getgreen(px) blue=getblue(px) negcolor=makecolor( 255-red, 255-green, 255-blue) setcolor(px,negcolor) 8
Grauwertbilder Farbbilder: Drei Farbkanäle (RGB) 8 Bit = 1 Byte (0 255) pro Kanal Darstellung von insgesamt 2 24 Farben Grauwertbilder 1 Farbkanal zu 8 Bit = 1 Byte d.h. Darstellung von 2 8 = 256 Grauwerten Konvertierung Farb- Grauwertbild z.b. Luminanz = Konvertierung zu Grauwertbildern in JES Echte Grauwertbilder: Pro Pixel 1 Farbwert In JES: setze R,G,B auf denselben Farbwert, z.b. def grayscale(picture): intensity = (getred(p) + getgreen(p) + getblue(p)) / 3 setcolor(p,makecolor(intensity,intensity,intensity)) 9
Konvertierung zu Grauwertbildern Bisherige Methode zur Berechnung des Grauwerts von Pixeln ist nicht optimal Psychologische Experimente legen nahe, dass Wahrnehmung von Farben bzgl. Luminanz unterschiedlich ist z.b. wird blau als "dunkler" wahrgenommen als rot auch bei gleicher physikalischer Lichtintensität Grauwert-Konvertierung mit wahrnehmungspsychologisch fundierter Gewichtung: def grayscaleweighted(picture): for px in getpixels(picture): newred = getred(px) * 0.299 newgreen = getgreen(px) * 0.587 newblue = getblue(px) * 0.114 luminance = newred+newgreen+newblue setcolor(px,makecolor(luminance,luminance,luminance)) Grauwertkonvertierung einfache Grauwertkonvertierung gewichtete Grauwertkonvertierung 10
Beispiel: Farbauffrischung für Dächer - Bedingtes Verändern von Pixelwerten Ziel: Intensivierung des Rot-Anteils von Dächern Idee: Erhöhung des Rotanteils von Pixeln aber nur wenn diese schon rötlich sind if-anweisung def intensifyred(picture): value=getred(p) if ( value > 180 ): setred(p,value*1.5) Python: If-Anweisung vgl. Programmablaufplan (VL 2) if ( <Bedingung> ): <Anweisungen> if ( <Bedingung> ): <Anweisungen> else: <Anweisungen> ja A1 B A2 nein Aufbau: if Schlüsselwort Bedingung kann zu True oder False evaluiert werden auch komplexe Bedingungen, z.b. verknüpft mit and if ( a >5 and a <10): Doppelpunkt Anweisungen, die ausgeführt werden, falls Bedingung gilt optionaler else-teil 11
Beispiel: if else Ziel: Überprüfung, welche Pixel bei der beabsichtigten bedingten Pixeleinfärbung überhaupt eingefärbt werden wurden Zeichne ursprüngl. "rötliche" Pixel weiß, alle anderen schwarz Resultierendes Bild hat nur noch zwei Farben (schwarz/weiß) "Binärbild" def intensifyred3(picture): value=getred(p) if ( value > 180 ): setcolor(p, white) else: setcolor(p, black) alle Dächer, aber nicht nur! bessere Bedingung für Dachpixel??? "Posterisierung" Reduktion der Anzahl der Farben in einem Bild 12
"Posterisierung" - Methode Ganze Bereiche von Farb-Anteilen werden auf einen bestimmten Farbanteil abgebildet z.b. falls Rotanteil < 64 dann setze Rotanteil = 31 z.b. falls Rotanteil zwischen 64 und 128 dann Rotanteil = 95 Implementierung durch Reihe von if-anweisungen Resultierendes Bild hat deutlich weniger Farben "Posterisierung" def posterize(picture): #loop through the pixels #get the RGB values red = getred(p) green = getgreen(p) blue = getblue(p) #check and set red values if(red < 64): setred(p, 31) if(red > 63 and red < 128): setred(p, 95) if(red > 127 and red < 192): setred(p, 159) if(red > 191 and red < 256): setred(p, 223) #check and set green values if(green < 64): setgreen(p, 31) if(green > 63 and green < 128): setgreen(p, 95) if(green > 127 and green < 192): setgreen(p, 159) if(green > 191 and green < 256): setgreen(p, 223) #check and set blue values if(blue < 64): setblue(p, 31) if(blue > 63 and blue < 128): setblue(p, 95) if(blue > 127 and blue < 192): setblue(p, 159) if(blue > 191 and blue < 256): setblue(p, 223) 13
Kommentare in Python Programmzeilen, die mit '#' beginnen sind Kommentare #loop through the pixels Kommentare können auch in der Mitte von Programmzeilen beginnen setred(pixel, 255) # update Rot-Anteil des Pixels Kommentare in Programmen dienen der Dokumentation des Codes Kommentare werden vom Python-Interpreter nicht ausgewertet def getintensity(p): sum = getred(p) + getgreen(p) + getblue(p) average = float(sum) / 3 # Bereich 0.0.. 255.0 return average / 255 # Bereich 0.0.. 1.0 # pink = (255, 128, 128) # moduliere mit Intensität des Original-Pixels def makepinkish(p): i = getintensity(p) setred(p, int(255 * i * 3) ) setgreen(p, int( getgreen(p) * i * 3) ) setblue(p, int( getblue(p) * i * 3) ) und noch ein Beispiel (codiert mit viel Ausprobieren) def isgreenish(p): r = getred(p) g = getgreen(p) b = getblue(p) if g > r + 15 and g + 11 > b: return 1 return 0 def replacegreenishinrange(picture, xmin, xmax, ymin, ymax): for x in range(xmin,xmax): for y in range(ymin,ymax): pix = getpixel(picture,x,y) if isgreenish(pix): makepinkish(pix) return picture 14