Einführung - Fraunhofer MEVIS

Werbung
SommerAkademie 2011
Mathematik für die Medizin
Eine sehr kurze Einführung in Python und MyImage
richard rascher-friesenhausen
[email protected]
Dies ist eine sehr, sehr kurze Einführung zu Python und den Möglichkeiten, vermittels des
Moduls MyImage zweidimensionale Grauwertbilder zu bearbeiten.
Python ist eine interpretierte objektorientierte Programmiersprache. D.h. insbesondere, dass
man sie direkt und ohne Übersetzer und Binder interaktiv verwenden kann. (Anders als bei
C++ oder Java.)
Ihr wird nachgesagt, eine leicht verständliche und erlernbare Syntax zu besitzen. Und es gibt
viele vorgefertigte Module, die einem eine Menge Programmierarbeit für spezielle Anwendungen abnehmen.
Python kann frei aus dem Internet heruntergeladen werden. Die in dieser Veranstaltung verwendete Distribution findet man bei www.pythonxy.com mit allen hier verwendeten Modulen.
Die Programmiersprache ist gut dokumentiert und es findet sich jede Menge Hilfe zu Python
frei im Internet. Ich empfehle insbesondere das Python-Tutorial (auf englisch):
http://docs.python.org/tutorial/
Und auf deutsch findet man eine ältere Version unter
http://starship.python.net/crew/gherman/publications/tut-de/tut-de-21.pdf
Wir verwenden im weiteren die Python-Entwicklungsumgebung ‚IDLE‘. Daneben gibt es auch
noch die alternativen Entwicklungsumgebungen ‚Spyder‘ und ‚Eclipse‘.
1 Erste Python Schritte
Aufgabe
Ruft ‚IDLE‘ über das Windows-Startmenu auf. Sucht dazu den Eintrag
PythonXY in der Startleiste und wählt darin den Eintrag ‚IDLE‘ aus.
Es öffnet sich das Fenster der Python-Shell in dem
der Python Interpreter auf Eingaben wartet. Diese
werden hinter dem Prompt >>> eingetippt und mit
der Eingabetaste abgeschlossen. Danach wertet Python
die Eingabe aus und liefert das zugehörige Ergebnis auf die Konsole zurück.
Arbeitszettel 1
1
prof. dr. richard rascher-friesenhausen
SommerAkademie 2011
Mathematik für die Medizin
Wir spielen jetzt einige einfache Berechnungen durch:
>>> 1 + 1
2
>>> -42 + 27
-15
>>>
Python antwortet mit einer Ausgabe des Rechenergebnisses auf einer neuen Zeile und fordert
zu neuen Eingaben auf.
Bisher haben wir mit ganzen Zahlen gerechnet. Und haben dabei auch stets ein ganzahliges
Ergebniss erhalten. Hier muss man bei der Division vorsichtig sein:
>>> 1/2
0
Es wird auch ganzzahlig dividiert! Will man mit Dezimalzahlen arbeiten, so muss man das
Python explizit sagen und den Zahlen einen Dezimalpunkt spendieren:
>>> 1./2.
0.5
Will man ‚schwierige‘ Mathematik rechnen, so benötigt man die üblichen mathematischen
Funktionen und Konstanten. Diese sind nicht direkt eingebaut sondern müssen ‚nachgeladen‘
werden. Das Modul math stellt einem folgende Funktionen und Konstanten zur Verfügung:
’acos’, ’acosh’, ’asin’, ’asinh’, ’atan’, ’atan2’, ’atanh’, ’ceil’,
’copysign’, ’cos’, ’cosh’, ’degrees’, ’e’, ’exp’, ’fabs’, ’factorial’,
’floor’, ’fmod’, ’frexp’, ’fsum’, ’hypot’, ’isinf’, ’isnan’, ’ldexp’, ’log’,
’log10’, ’log1p’, ’modf’, ’pi’, ’pow’, ’radians’, ’sin’, ’sinh’, ’sqrt’,
’tan’, ’tanh’, ’trunc’
Diese werden alle nachgeladen über
>>> from math import *
Man kann bspw. jetzt Wurzeln ziehen:
>>> sqrt(4.)
2.0
>>> 2.0**2
4.0
Oben bedeutet ** das Potenzieren.
Aufgabe
Arbeitszettel 1
Wie kann man mit der **-Schreibweise auch die Wurzel ziehen?
2
prof. dr. richard rascher-friesenhausen
SommerAkademie 2011
Mathematik für die Medizin
Mit der Funktion help kann man Python befragen, was eine Funktion bedeutet, etwa
>>> help(sqrt)
Help on built-in function sqrt in module math:
sqrt(...)
sqrt(x)
Return the square root of x.
Aufgabe
Bekommt heraus, was die Funktion pow berechnet und wie.
Eine formatierte Tabelle einiger trigonometrischer Funktionen bekommen wir über
>>> for x in [0.,pi/6.,pi/4.,pi/3.,pi/2.,pi]:
print "%f, %+f, %f" % (x, cos(x), sin(x))
0.000000,
0.523599,
0.785398,
1.047198,
1.570796,
3.141593,
+1.000000,
+0.866025,
+0.707107,
+0.500000,
+0.000000,
-1.000000,
0.000000
0.500000
0.707107
0.866025
1.000000
0.000000
Beachtet die Einrückung des print Befehls. Wir haben hier ein Beispiel für eine PythonKontrollstruktur, nämlich die for Schleife. Darüberhinaus wird auch mit einer Variablen x
gearbeitet.
Man kann Variablen anlegen durch Vergabe eines Namens und Zuweisung eines Wertes. Etwa
>>> x = 42
>>> print x
42
>>> y = 0.815
>>> print y
0.815
>>> s = "Hallo"
>>> print s
Hallo
Hier wurde den Variablen x, y und s eine ganze Zahl, ein Dezimalzahl und ein String zugewiesen und wieder abgefragt.
Neben diesen einfachen Datentypen benötigen wir in Python noch sehr häufig den Typ der
Liste:
Arbeitszettel 1
3
prof. dr. richard rascher-friesenhausen
SommerAkademie 2011
Mathematik für die Medizin
>>> L = [x, y, s]
>>> print L
[42, 0.81499999999999995, ’Hallo’]
>>>
Hier kann man erkennen, dass das Binärsystem eines Computer nicht alle Dezimalzahlen exakt
darstellen kann.
An einzelne Listenelemente kommt man über einen Index, der bei Null beginnt.
>>> print L[0]
42
>>> print L[1]
0.815
>>> L[1] = 47.11
>>> print L[1]
47.11
>>> print L[2]
Hallo
Es ist möglich, eigene Funktionen in Python zu definieren. Machen wir das mal vor für eine
Quadratfunktion:
>>> def quadrat(x):
return x*x
>>> print quadrat(4)
16
>>> y = quadrat(-1.2)
>>> print y
1.44
Oben steht die Definiton der Funktion quadrat und einige Aufrufe dieser Funktion. Ein Aufruf
mit einem String geht schief!
>>> print quadrat(’hi’)
Traceback (most recent call last):
File "<pyshell#35>", line 1, in <module>
print quadrat(’hi’)
File "<pyshell#31>", line 2, in quadrat
return x*x
TypeError: can’t multiply sequence by non-int of type ’str’
Aufgabe
Lest das Tutorial zu Python von der Python-Dokumentations-Webseite
http://docs.python.org/ und arbeitet es einmal bis Abschnitt 8 durch.
Arbeitszettel 1
4
prof. dr. richard rascher-friesenhausen
SommerAkademie 2011
Mathematik für die Medizin
2 Python Programdateien
Sobald man also jetzt ans Programmieren kommt, ist es sinnvoll, die Python-Befehle in eine
eigene Datei abzulegen. Öffnet dazu in der IDLE ds Menu ‚File‘ und wählt ‚New Window‘
aus. Es öffnet sich ein neues Fenster, dsa einem jetzt als ASCII-Editor dient. Gebt darin jetzt
die folgenden Zeilen Python-Code ein (ohne Zeilennummerierung)
1 def quadrat(x):
2
return x*x
4 x = 12.0
5 y = quadrat(x)
6 z = quadrat(y)
8 print x, y, z
eins.py
Speichert den Inhalt in einer Datei eins.py in Eurem Heimatverzeichnis in einem Unterverzeichnis python. (Bspw. C:\Users\richard\Documents\Python) Da kommen dann auch alle
weiteren Python-Programme hinein. Wir können nun dieses Skript ablaufen lassen, indem wir
in dem Menu ‚Run‘ und Run Module auswählen, oder die Taste F5 drücken. Die Ergebnisse
werden im dem Fenster der Python Shell ausgegeben.
Sollten noch Syntaxfehler in dem Programm stecken, so werden diese ebenfalls (in Rot) im
dem Fenster der Python Shell ausgegeben.
Arbeitszettel 1
5
prof. dr. richard rascher-friesenhausen
SommerAkademie 2011
Mathematik für die Medizin
Aufgabe
Schreibt eine Funktion c2f(), die eine Temperatur in Celsius umrechnet
nach Fahrenheit und eine Funktion f2c(), die umgekehrt eine Temperatur in Fahrenheit
umrechnet nach Celsius. Testet beide Funktionen aus.
3 Das MyImage Modul
In Python gibt es verschiedene Bibliotheken, die auf Bildern arbeiten. Da ist zum einen das
Image Modul, das eine ausgereifte Sammlung von Objekten zur Manipulation von 2D-Bildern
zur Verfügung stellt.
Für die medizinische Bildverarbeitung existiert mit ITK eine große Sammlung von Algorithmen, die nativ in C++ codiert sind. Viele Teile davon sind auch für Python verfügbar und
können mit dem Modul itk in ein Pythonprogramm importiert werden.
Beide angesprochenen Module sind in der Python(x,y)-Distribution enthalten bzw. können
nachgeladen werden.
Als eine weitere sehr einfache Alternative steht mit dem Modul MyImage ein Bilderklasse
und einige sinnvolle Funktionen zur Verfügung, um pixelweise Bildverarbeitung auf 2DGrauwertbildern zu implementieren.
Jedes Pythonprogramm, welches die MyImage-Objekte nutzen will, muss die Objekte importieren, also
from MyImage import *
In der Klasse MyImage (Vorsicht! Gleicher Name wie das Modul.) stecken nun die Bildobjekte.
Ein Bild aus einer Datei, bevorzugt .png (Portable Newtork Graphic), lässt sich wie folgt
einlesen
img = MyImage(’clown.png’)
Dazu muss natürlich die Datei clown.png im aktuellen Arbeitsverzeichnis liegen. Und dann
schauen wir uns das Bild einmal an mit
img.show()
Es öffnet sich ein neues Fenster mit unserem Bild.
Arbeitszettel 1
6
prof. dr. richard rascher-friesenhausen
SommerAkademie 2011
Mathematik für die Medizin
Man kann nun das Bild nach einigen seiner Eigenschaften befragen, etwa nach seiner Breite
und Höhe:
print img.getWidth(), img.getHeight()
320 200
Wir haben es mit einem Bild mit 320 Spalten und 200 Zeilen zu tun. Die Spalten- und
Zeilenzählung beginnt bei 0! Eine ähnliche Ausgabe hätten wir auch mit dem Befehl
print img.getSize()
(320, 200)
erhalten. Wir werden nun die ganze Spalte x = 42 des Bildes auf weiß, also 255, setzen. Das
Bild wird koordinatenweise angesprochen, wobei die erste Koordinate, die x Koordinate, für die
Spalten steht und die zweite Koordinate, die y Koordinate, für die Zeile. Der Programmcode
dazu verfläuft nun wie folgt
x = 42
for y in range(img.getHeight()):
img[x,y] = 255
Und danach kann man sich das neue Bild anschauen vermittels
img.show()
Damit ist es also möglich, existierende Bilder zu lesen, zu manipulieren, anzuschauen und
auch wieder zu speichern:
img.save(’myclown.png’)
Auf der Festplatte sollte sich jetzt im aktuellen Verzeichnis eine neue Datei myclown.png
befinden, in der das von uns veränderte Bild gespeichert ist.
Ein schwarzes Bild mit gegebener Breite w und Höhe h kann wie folgt neu angelegt werden
w, h = 100, 80
Img = MyImage(w, h, 0)
Arbeitszettel 1
7
prof. dr. richard rascher-friesenhausen
SommerAkademie 2011
Mathematik für die Medizin
und danach pixelweise verändert werden. Beipielsweise lassen sich darauf 100 zufällige Pixelpositionen mit zufälligen Grauwerten zwischen 0 (schwarz) und 255 (weiß) belegen. Der Zufall
wird durch das Modul random zur Verfügung gestellt:
import random
for i in range(100):
x = random.randrange(0,w)
y = random.randrange(0,h)
g = random.randrange(0,256)
Img[x,y] = g
Aufgabe
links.
Erzeugt ein 256 × 256 Grauwertbild wie in der unten stehenden Abbildung
256
256
100
256
100
256
Die beiden Grauwerte sollen 0 (Schwarz) und 255 (Weiss) sein. Speichert das Bild unter
quadrat.png ab.
Wie kann man einen Kreis (mit Radius 50) wie in der Abbildung rechts erzeugen? Speichert
diesen unter circle.png ab.
Aufgabe
Erzeugt ein 512 × 512 Bild mit vertikalen Grauwertstreifen der Stärke 50,
100, 150, 200 und jeweiliger Breite von 128 Pixel. Speichert das Bild unter dem Namen
stripes1.png ab.
Verändert die Grauwerte zu 20, 40, 60 und 80 und speichert unter stripes2.png ab.
Arbeitszettel 1
8
prof. dr. richard rascher-friesenhausen
SommerAkademie 2011
Mathematik für die Medizin
Erzeugen eines Bildobjektes aus einer Bilddatei:
img = MyImage(dateiname)
dateiname: Name einer existierenden Bilddatei, String
Erzeugen eines Bildobjektes mit konstantem Grauwert und gegebener Dimension:
img = MyImage(breite, hoehe, wert)
breite: Anzahl der Spalten des Bildes, Integer größer Null
hoehe: Anzahl der Zeilen des Bildes, Integer größer Null
wert: Konstanter Grauwert des Bildes, Integer zwischen 0 und 255
Erzeugen einer Kopie eines schon angelegten Bildobjektes:
img = MyImage(bild)
bild: Bildobjekt der Klasse MyImage
Anzeigen eines Bildobjektes:
img.show()
Speichern eines Bildeobjektes:
img.save(dateiname)
dateiname: Name der neuen Bilddatei, String
Auslesen der Breite eines Bildobjektes:
breite = img.getWidth()
Auslesen der Höhe eines Bildobjektes:
hoehe = img.getHeight()
Auslesen eine Pixels eines Bildobjektes:
g = img[x,y]
x: Spaltenindex des Pixels, Integer
y: Zeilenindex des Pixels, Integer
g: Grauwert des Pixels, Integer
Setzen eines Pixels eines Bildobjektes:
img[x,y] = g
x: Spaltenindex des Pixels, Integer
y: Zeilenindex des Pixels, Integer
g: Grauwert des Pixels, Integer
Für weitere Informationen zu den Methoden eines MyImage-Objektes siehe man direkt in der
Python-Datei MyImage.py nach.
Arbeitszettel 1
9
prof. dr. richard rascher-friesenhausen
Herunterladen