Bild-Tutorial#

Ein kurzes Tutorial zur Darstellung von Bildern mit Matplotlib.

Startbefehle#

Zuerst starten wir IPython. Es ist eine ausgezeichnete Erweiterung der Standard-Python-Eingabeaufforderung und passt besonders gut zu Matplotlib. Starten Sie IPython entweder direkt in einer Shell oder mit dem Jupyter Notebook (wo IPython als laufender Kernel fungiert).

Wenn IPython gestartet ist, müssen wir uns nun mit einer GUI-Ereignisschleife verbinden. Dies teilt IPython mit, wo (und wie) Diagramme angezeigt werden sollen. Um sich mit einer GUI-Schleife zu verbinden, führen Sie den magischen Befehl %matplotlib in Ihrer IPython-Eingabeaufforderung aus. Weitere Details dazu finden Sie in der Dokumentation von IPython zur GUI-Ereignisschleifenunterstützung.

Wenn Sie Jupyter Notebook verwenden, sind dieselben Befehle verfügbar, aber üblicherweise wird ein bestimmtes Argument für den %matplotlib-Befehl verwendet.

In [1]: %matplotlib inline

Dies aktiviert die Inline-Darstellung, bei der Plot-Grafiken in Ihrem Notebook erscheinen. Dies hat wichtige Auswirkungen auf die Interaktivität. Bei der Inline-Darstellung wirken sich Befehle in Zellen unterhalb der Zelle, die einen Plot ausgibt, nicht auf den Plot aus. Beispielsweise ist es nicht möglich, die Farbkarte von Zellen aus zu ändern, die sich unterhalb der Zelle befinden, die den Plot erstellt. Für andere Backends wie Qt, die ein separates Fenster öffnen, ändern Zellen unterhalb derjenigen, die den Plot erstellen, den Plot – es ist ein Live-Objekt im Speicher.

Dieses Tutorial verwendet die implizite Plotting-Schnittstelle von Matplotlib, pyplot. Diese Schnittstelle verwaltet den globalen Zustand und ist sehr nützlich für schnelles und einfaches Experimentieren mit verschiedenen Plot-Einstellungen. Die Alternative ist die explizite Schnittstelle, die sich besser für die Entwicklung großer Anwendungen eignet. Eine Erklärung der Kompromisse zwischen der impliziten und der expliziten Schnittstelle finden Sie unter Matplotlib Application Interfaces (APIs) und im Schnellstart-Leitfaden für die Verwendung der expliziten Schnittstelle. Vorerst bleiben wir bei der impliziten Methode.

from PIL import Image

import matplotlib.pyplot as plt
import numpy as np

Importieren von Bilddaten in Numpy-Arrays#

Matplotlib stützt sich auf die Pillow-Bibliothek zum Laden von Bilddaten.

Hier ist das Bild, mit dem wir spielen werden

../_images/stinkbug.png

Es ist ein 24-Bit-RGB-PNG-Bild (8 Bit für jedes R, G, B). Je nachdem, woher Ihre Daten stammen, sind die anderen Bildtypen, denen Sie am wahrscheinlichsten begegnen werden, RGBA-Bilder, die Transparenz ermöglichen, oder einfarbige Graustufenbilder (Luminanz). Laden Sie stinkbug.png für den Rest dieses Tutorials auf Ihren Computer herunter.

Wir verwenden Pillow, um ein Bild zu öffnen (mit PIL.Image.open) und konvertieren das PIL.Image.Image-Objekt sofort in ein 8-Bit-Numpy-Array (dtype=uint8).

img = np.asarray(Image.open('../../doc/_static/stinkbug.png'))
print(repr(img))
array([[[104, 104, 104],
        [104, 104, 104],
        [104, 104, 104],
        ...,
        [109, 109, 109],
        [109, 109, 109],
        [109, 109, 109]],

       [[105, 105, 105],
        [105, 105, 105],
        [105, 105, 105],
        ...,
        [109, 109, 109],
        [109, 109, 109],
        [109, 109, 109]],

       [[107, 107, 107],
        [106, 106, 106],
        [106, 106, 106],
        ...,
        [110, 110, 110],
        [110, 110, 110],
        [110, 110, 110]],

       ...,

       [[112, 112, 112],
        [111, 111, 111],
        [110, 110, 110],
        ...,
        [116, 116, 116],
        [115, 115, 115],
        [115, 115, 115]],

       [[113, 113, 113],
        [113, 113, 113],
        [112, 112, 112],
        ...,
        [115, 115, 115],
        [114, 114, 114],
        [114, 114, 114]],

       [[113, 113, 113],
        [115, 115, 115],
        [115, 115, 115],
        ...,
        [114, 114, 114],
        [114, 114, 114],
        [113, 113, 113]]], shape=(375, 500, 3), dtype=uint8)

Jede innere Liste repräsentiert ein Pixel. Hier gibt es bei einem RGB-Bild 3 Werte. Da es sich um ein Schwarzweißbild handelt, sind R, G und B alle ähnlich. Ein RGBA-Bild (wobei A für Alpha oder Transparenz steht) hat 4 Werte pro innerer Liste, und ein einfaches Luminanzbild hat nur einen Wert (und ist somit nur ein 2D-Array, kein 3D-Array). Für RGB- und RGBA-Bilder unterstützt Matplotlib die Datentypen float32 und uint8. Für Graustufen unterstützt Matplotlib nur float32. Wenn Ihre Array-Daten nicht einer dieser Beschreibungen entsprechen, müssen Sie sie neu skalieren.

Numpy-Arrays als Bilder darstellen#

Sie haben also Ihre Daten in einem Numpy-Array (entweder durch Importieren oder Generieren). Lassen Sie es uns rendern. In Matplotlib wird dies mit der Funktion imshow() durchgeführt. Hier greifen wir auf das Plot-Objekt zu. Dieses Objekt bietet eine einfache Möglichkeit, den Plot von der Eingabeaufforderung aus zu manipulieren.

images

Sie können auch jedes Numpy-Array darstellen.

Pseudofarbschemata auf Bildplots anwenden#

Pseudofarbe kann ein nützliches Werkzeug sein, um den Kontrast zu verbessern und Ihre Daten leichter zu visualisieren. Dies ist besonders nützlich, wenn Sie Ihre Daten auf Projektoren präsentieren – deren Kontrast ist typischerweise recht schlecht.

Pseudofarbe ist nur für einfarbige Graustufen-Luminanzbilder relevant. Wir haben derzeit ein RGB-Bild. Da R, G und B alle ähnlich sind (sehen Sie selbst oben oder in Ihren Daten), können wir einfach einen Kanal unserer Daten mithilfe von Array-Slicing auswählen (mehr dazu erfahren Sie im Numpy-Tutorial).

images

Mit einem Luminanzbild (2D, keine Farbe) wird die Standard-Farbkarte (auch Lookup-Tabelle, LUT genannt) angewendet. Die Standardeinstellung heißt viridis. Es gibt viele weitere zur Auswahl.

plt.imshow(lum_img, cmap="hot")
images

Beachten Sie, dass Sie Farbpaletten auch bei vorhandenen Plot-Objekten mit der Methode set_cmap() ändern können.

images

Hinweis

Denken Sie jedoch daran, dass Sie im Jupyter Notebook mit dem Inline-Backend keine Änderungen an bereits gerenderten Plots vornehmen können. Wenn Sie `imgplot` hier in einer Zelle erstellen, können Sie `set_cmap()` in einer späteren Zelle nicht aufrufen und erwarten, dass sich der frühere Plot ändert. Stellen Sie sicher, dass Sie diese Befehle zusammen in einer Zelle eingeben. `plt`-Befehle ändern keine Plots aus früheren Zellen.

Es gibt viele weitere verfügbare Farbschemata. Sehen Sie sich die Liste und Bilder der Farbpaletten an.

Farbskala-Referenz#

Es ist hilfreich, eine Vorstellung davon zu haben, welchen Wert eine Farbe darstellt. Dies können wir tun, indem wir Ihrer Abbildung eine Farbleiste hinzufügen.

images

Untersuchen eines bestimmten Datenbereichs#

Manchmal möchten Sie den Kontrast in Ihrem Bild verbessern oder den Kontrast in einem bestimmten Bereich erweitern, während Sie die Details in Farben opfern, die sich nicht viel ändern oder die nicht wichtig sind. Ein gutes Werkzeug, um interessante Bereiche zu finden, ist das Histogramm. Um ein Histogramm unserer Bilddaten zu erstellen, verwenden wir die Funktion hist().

plt.hist(lum_img.ravel(), bins=range(256), fc='k', ec='k')
images

Am häufigsten befindet sich der "interessante" Teil des Bildes um den Spitzenwert herum, und Sie können zusätzlichen Kontrast erzielen, indem Sie die Bereiche oberhalb und/oder unterhalb des Spitzenwerts abschneiden. In unserem Histogramm scheint es nicht viele nützliche Informationen im oberen Bereich zu geben (nicht viele weiße Dinge im Bild). Lassen Sie uns die obere Grenze anpassen, damit wir einen Teil des Histogramms effektiv "heranzoomen". Dies erreichen wir, indem wir *clim* (die Grenzwerte der Farbkarte) einstellen.

Dies kann durch Übergabe eines `clim`-Schlüsselwortarguments im Aufruf von imshow erfolgen.

plt.imshow(lum_img, clim=(0, 175))
images

Dies kann auch durch Aufruf der Methode set_clim() des zurückgegebenen Bild-Plot-Objekts erfolgen, aber stellen Sie sicher, dass Sie dies in derselben Zelle wie Ihren Plot-Befehl tun, wenn Sie mit dem Jupyter Notebook arbeiten – es wird keine Plots aus früheren Zellen ändern.

images

Array-Interpolationsschemata#

Interpolation berechnet, wie die Farbe oder der Wert eines Pixels gemäß verschiedenen mathematischen Schemata "sein sollte". Ein häufiger Ort, an dem dies geschieht, ist, wenn Sie ein Bild in der Größe ändern. Die Anzahl der Pixel ändert sich, aber Sie möchten dieselben Informationen. Da Pixel diskret sind, gibt es fehlenden Platz. Interpolation ist, wie Sie diesen Platz füllen. Deshalb sehen Ihre Bilder manchmal verpixelt aus, wenn Sie sie vergrößern. Der Effekt ist stärker ausgeprägt, wenn der Unterschied zwischen dem Originalbild und dem erweiterten Bild größer ist. Nehmen wir unser Bild und verkleinern es. Wir verwerfen effektiv Pixel und behalten nur wenige ausgewählte. Wenn wir es dann darstellen, werden diese Daten auf die Größe Ihres Bildschirms aufgeblasen. Die alten Pixel sind nicht mehr da, und der Computer muss Pixel zeichnen, um diesen Platz zu füllen.

Wir werden die Pillow-Bibliothek, die wir auch zum Laden des Bildes verwendet haben, zum Ändern der Bildgröße verwenden.

img = Image.open('../../doc/_static/stinkbug.png')
img.thumbnail((64, 64))  # resizes image in-place
imgplot = plt.imshow(img)
images

Hier verwenden wir die Standardinterpolation ("nearest"), da wir imshow() kein Interpolationsargument übergeben haben.

Versuchen wir einige andere. Hier ist "bilinear"

imgplot = plt.imshow(img, interpolation="bilinear")
images

und bicubic

imgplot = plt.imshow(img, interpolation="bicubic")
images

Die bikubische Interpolation wird oft beim Aufblasen von Fotos verwendet – Menschen bevorzugen tendenziell verschwommen gegenüber verpixelt.

Gesamtlaufzeit des Skripts: (0 Minuten 8,955 Sekunden)

Galerie generiert von Sphinx-Gallery