Termin 6: Medienprogrammierung in Python Bildverarbeitung (3) Grundlagen der Informatik Wintersemester 2006/07 Prof. Bernhard Jung Übersicht Definition von Funktionen in Python Globale und lokale Namensräume von Variablen Parameterübergabe Rekursive Funktionen Medienprogrammierung mit Python / JES verschiedene einfachere Algorithmen (Rotieren, Spiegeln von Bildern) Kombinieren von Bildern, z.b. Bluescreening Vektorgrafikelemente zu Bitmaps hinzufügen 1
Beispiel für bildgebende Verfahren im Bereich Geo / Engineering: Georadar Alle Bilder: www.geosphereinc.com Nachweis von Benzintanks im Boden Aufruf von Funktionen Format des Ausrufs: funktion(arg1, arg2, ) Funktionen akzeptieren i.d.r. nur eine bestimmte Anzahl von Argumenten Die übergebenen Argumente müssen von einem bestimmten Typ sein Beispiel: Standardfunktion len() Länge von Strings, Listen, Tupeln, Dictionaries Fehlerhafte Aufrufe len(1) 1 ist eine Zahl und besitzt keine Länge len("eins", "zwei") Die Funkionlen() akzeptiert nur ein Argument Korrekte Aufrufe len("wort") 4 len([1,2,3,4]) 4 len("sha" + 4 * "la") 11 (Auswertung des Ausdrucks ergibt String) len( (1, 2, (3,4) ) ) 3 (Tupel mit 3 Elementen) Manche Funktionen akzeptieren eine variable Anzahl von Parametern z.b. min(1,2,3,4,5) 1 2
Definition von Funktionen Funktionskopf Schlüsselwort def, Funktionsname, Parameterliste in Klammern, Doppelpunkt Funktionskörper Anweisungsblock, d.h. Folge von Anweisungen def funktionsname(arg1, arg2, ): anweisungsblock eingerückt! mit Schlüsselwert return kann ein Rückgabewert festgelegt werden Rückgabewert kann auch Tupel, Liste oder anderes Objekt sein def summierebis(n): sum = 0 for i in range(1,n+1): sum = sum + i return sum def sumandmultiplyto(n): sum = 0 prod = 1 for i in range(1,n+1): sum = sum + i prod = prod * i return (sum,prod) Ausführung von Funktionen - Globale und lokale Namensräume Definition einer lokalen Variable x Definition globaler Variablen x, y lokale Variablen sind nur innerhalb der Funktionsdefinition sichtbar, d.h. können außerhalb nicht verwendet werden innerhalb von Funktionen sind lokale und globale Variablen sichtbar bei Namensgleichheit einer lokalen mit einer globalen Variable wird die lokale Variable ausgewertet def f(): x = 2 print "x in Funktion f(): ", x print "y in Funktion f(): ", y # Hauptprogramm x = 1 y = 1 f() print "x in Hauptprogramm: ", x print "y in Hauptprogramm: ", y x in Funktion f(): 2 y in Funktion f(): 1 x in Hauptprogramm: 1 y in Hauptprogramm: 1 3
Ausführung von Funktionen - Globale und lokale Namensräume def f(): x = 2 print "Globaler Namensraum von f(): ", globals() print "Lokaler Namensraum von f(): ", locals() Standardfunktionen # Hauptprogramm x = y = 1 f() Globaler Namensraum von f(): {'f': <function f at 0x00B45830>, ' builtins ': <module ' builtin ' (built-in)>, 'x': 1, 'y': 1, ' name ': ' main ', ' doc ': None} Lokaler Namensraum von f(): {'x': 2} In JES enthält globaler Namensraum eine Vielzahl weiterer Funktionen! Ausführung von Funktionen - Globale und lokale Namensräume Innerhalb von Funktionen können globale Variablen gelesen, aber nicht ohne Weiteres verändert werden Zur Veränderung einer globalen Variable innerhalb einer Funktion dient die global-anweisung (teilt Python mit, dass Zuweisung an eine globale Variable erfolgen soll) def verdopple(): global x x = x * 2 # Hauptprogramm x = 10 verdopple() print x 20 4
Ausführung von Funktionen - Parameterübergabe (1) Auf formale Parameter, d.h. Namen der Parameter im Funktionskopf, kann im Funktionskörper wie auf lokale Variablen zugegriffen werden Bei Aufruf der Funktion halbiere() wird der Parameter innerhalb der Funktion an eine andere Variable gebunden Sind die als Parameter übergebene Objekte unveränderbar z.b. Zahlen, Strings, Tupel dann haben Veränderungen innerhalb der Funktion keine Auswirkungen auf Objekte außerhalb def halbiere(zahl): zahl = float(zahl) zahl = zahl / 2 return zahl n = 5 halbiere(n) 2.5 n # n bleibt unverändert 5 n = halbiere(n) print n 2.5 Ausführung von Funktionen - Parameterübergabe (2) Veränderbare Objekte, z.b. Listen, können, wenn sie als Argumente einer Funktion übergeben werden, in dieser Funktion modifiziert werden (die Veränderungen sind auch außerhalb der Funktion wirksam)! z.b. auch Bilder in JES! def quadriere(l): for i in range( len(l) ): l[i] = l[i] * l[i] # Hauptprogramm liste = [1,2,3,4,5] print liste quadriere( liste ) print liste Programmlauf: [1, 2, 3, 4, 5] [1, 4, 9, 16, 25] 5
(Wiederholung): Die wichtigsten Datentypen in Python Datentypen Zahlen Kollektionen bool True, False NoneType None Ganze Zahlen float complex 12.852 1+2j Sequenzen Mengen Abbildungen int Unveränderbaderbar Verän- set dict 123 set( [1,2]) ( A :65, B :66) long str unicode tuple list frozenset 123456789L Wort u Wort (1, a, [2]) [1, a, [2]] frozenset( [1,2]) Voreingestellte Parameter Manche Funktionen haben optionale Parameter, die bei Funktionsaufruf weggelassen werden können In der Funktionsdefinition werden für diese Default-Werte angegeben: def funktionsname(arg1=wert1, arg2=wert2, ): def wertetabelle(anzahl=3, schritt=0.5): x = 0.0 for i in range(anzahl): print x, ' ', x*x x = x + schritt wertetabelle() 0.0 0.0 0.5 0.25 1.0 1.0 wertetabelle(3,1) 0.0 0.0 1.0 1.0 2.0 4.0 wertetabelle(5) 0.0 0.0 0.5 0.25 1.0 1.0 1.5 2.25 2.0 4.0 6
Schlüsselwort-Argumente Bisher: Aufruf von Funktionen mit Positionsargumenten Reihenfolge der Argumente bei Aufruf entsprechend Funktionsdefinition In Python auch möglich: Aufruf mittels Schlüsselwort-Argumente der Form funktionsname(arg1=wert1, arg2=wert2, ) def wertetabelle(anzahl=3, schritt=0.5): x = 0.0 for i in range(anzahl): print x, ' ', x*x x = x + schritt wertetabelle(schritt=0.1) 0.0 0.0 0.1 0.01 0.2 0.04 wertetabelle(schritt=0.1, anzahl=5) 0.0 0.0 0.1 0.01 0.2 0.04 0.3 0.09 0.4 0.16 Rekursive Funktionen Rekursive Funktion: Funktion, die sich selbst aufruft z.b. Fakultät: n! = 1 * 2 * * n rekursive Formulierung der Fakultätsfunktion: 1! = 1 n! = n * (n-1)!, n > 1 def fak(n): if n == 1: return 1 else: 120 3628800 2432902008176640000 return n * fak(n-1) # Hauptprogramm print fak(5) print fak(10) print fak(20) 7
Rekursive Funktionen Fibonacci-Folge: 1, 1, 2, 3, 5, 8, 13, Rekursive Formulierung Basisfall: fib(1) = 1 Basisfall: fib(2) = 1 Rekursionsfall (n>2): fib(n) = fib(n-1) + fib(n-2) def fib(n): if n == 1 or n==2: return 1 else: return fib(n-1) + fib(n-2) mit Rückgabe als Liste: def fib1(n): if n == 1: return [1] elif n== 2: return [1,1] else: bisher = fib1(n-1) i = bisher[n-2] + bisher[n-3] return bisher + [i] Dokumentation von Funktionen - Docstrings Unterhalb des Funktionskopfes sollte ein Kommentar in dreifachen Anführungszeichen angebracht werden Dieser Docstring der Funktion kann im interaktiven Modus mit der help()-funktion zum Vorschein gebracht werden def fak(n): """Berechnung der Fakultaet einer Zahl. Eingabe: eine Zahl n Ausgabe: Fakultaet n! der Zahl Autor: Bernhard Jung, 15.11.2005 """ if n == 1: return 1 else: return n * fak(n-1) help(fak) Help on function fak in module main : fak(n) Berechnung der Fakultaet einer Zahl. Eingabe: eine Zahl n Ausgabe: Fakultaet n! der Zahl Autor: Bernhard Jung, 15.11.2005 8
Bildverarbeitung mit JES Einige Funktionen getwidth(pic), getheight(pic) liefern Breite, Höhe eines Bilds makepicture(filename) erzeugt Bild aus Dateinamen (.jpg) makeemptypicture(width, heigth) erzeugt leeres (schwarzes) Bild getpixel(pix,x,y) liefert Pixel an Position (x,y) getcolor(pixel) liefert Farbe des Pixels setcolor(pixel, color) setzt Farbe eines Pixels Transponieren von Bildern Idee: Pixel (x,y) wird an Position (y,x) im neuen Bild kopiert Rotation + Spiegelung def transposepicture(origpic): w = getwidth(origpic) h = getheight(origpic) newpic = makeemptypicture(h,w) for x in range(1, w+1): for y in range(1, h+1): pixel1 = getpixel(origpic, x, y) color = getcolor(pixel1) pixel2 = getpixel(newpic, y, x) setcolor(pixel2, color) return newpic 9
Vertikales "Spiegeln" Berechne Mitte des Bildes in x-richtung (mirrorpoint) Für jede Bildzeile: kopiere Pixel an (mirrorpoint + offset, y) nach (mirrorpoint offset, y) Vertikales "Spiegeln" def mirrorvertical(source): mirrorpoint = int(getwidth(source) / 2) for y in range(1, getheight(source)): for xoffset in range(1, mirrorpoint): pright = getpixel(source, xoffset + mirrorpoint, y) pleft = getpixel(source, mirrorpoint - xoffset, y) c = getcolor(pright) setcolor(pleft, c) return source 10
Horizontales "Spiegeln" def mirrorhorizontal(source): mirrorpoint = int(getheight(source) / 2) for yoffset in range(1, mirrorpoint): for x in range(1, getwidth(source)): pbottom = getpixel(source, x, yoffset + mirrorpoint) ptop = getpixel(source, x, mirrorpoint - yoffset) setcolor(pbottom, getcolor(ptop)) return source Kombinieren von Bildern z.b. alle bläulichen Pixel eines Bildes durch Hintergrund ersetzen def bluescreen(source,bg): for p in getpixels(source): if (getred(p)+getgreen(p) < getblue(p)): x = getx(p) y = gety(p) pixel = getpixel(bg,x,y) col = getcolor(pixel) setcolor(p,col) return source 11
Bitmaps und Vektorgrafik Bisher: Bitmap-Bilder (Rastergrafik) Bild ist Matrix von Pixeln.jpg,.bmp,.png,.gif, Digitalkamera, Scanner Vektorgrafik Anweisungen zum Zeichnen verschiedener einfacher Formen Linien, Rechtecke, Text, z.b. Freehand, Ilustrator, CorelDraw, Postscript, TrueType Fonts, Vorteil z.b. stufenlose Skalierung möglich Bitmaps können um Vektorgrafik-Elemente angereichert werden Grafikbibliotheken wandeln Vektorgrafik in Pixeldarstellung um JES: addtext(pic,x,y,string) addline(x1,y1,x2,y2) addrect(x,y,w,h) addrectfilled(x,y,w,h,color) Vektorgrafikelemente Pixel einzeln setzen: def verticallines(pic): for x in range(1,getwidth(pic),5): for y in range(1,getheight(pic)+1): setcolor(getpixel(pic,x,y),black) oder Linien (Vektorgrafik) zeichnen def verticallines(pic): for x in range(1,getwidth(pic),5): addline(pic, x, 1, x, getheight(pic)) def horizontallines(pic): for y in range(1,getheight(pic),5): addline(pic, 1, y, getwidth(pic), y) 12
Vektorgrafikelemente def title(pic,string): addtext(pic,40,15,string) pic = makepicture(file) title(pic, "Willkommen in Freiberg") show(pic) Vektorgrafikelemente def coolpic(): pic = makeemptypicture(250,250) for i in range(25,1,-1): color = makecolor(i*10,i*5,i) addrectfilled(pic,0,0,i*10,i*10,color) return pic 13
Vektorgrafikelemente def makewhitepicture(width=640, height=480): pic = makeemptypicture(width,height) for p in getpixels(pic): setcolor(p,white) return pic def coolpic2(): pic = makewhitepicture(640,480) for i in range(25,1,-1): addrect(pic, i, i, i*3, i*4) addrect(pic, 100+i*4, 100+i*3, i*8, i*10) return pic 14