Bild-Tutorial #

Ein kurzes Tutorial zum Plotten von Bildern mit Matplotlib.

Startbefehle #

Lassen Sie uns zuerst IPython starten. Es ist eine hervorragende Erweiterung der Standard-Python-Eingabeaufforderung und passt besonders gut zu Matplotlib. Starten Sie IPython entweder direkt an einer Shell oder mit dem Jupyter Notebook (wobei IPython als laufender Kernel).

Wenn IPython gestartet ist, müssen wir uns jetzt mit einer GUI-Ereignisschleife verbinden. Dies teilt IPython mit, wo (und wie) Plots angezeigt werden sollen. Um eine Verbindung zu einer GUI-Schleife herzustellen, führen Sie die %matplotlib- Magie an Ihrer IPython-Eingabeaufforderung aus. Weitere Einzelheiten darüber, was dies genau bewirkt, finden Sie in der IPython-Dokumentation zu GUI-Ereignisschleifen .

Wenn Sie Jupyter Notebook verwenden, sind die gleichen Befehle verfügbar, aber die Leute verwenden normalerweise ein bestimmtes Argument für die %matplotlib-Magie:

In [1]: %matplotlib inline

Dadurch wird das Inline-Plotting aktiviert, bei dem Plotgrafiken in Ihrem Notizbuch angezeigt werden. Dies hat wichtige Auswirkungen auf die Interaktivität. Beim Inline-Plotten wirken sich Befehle in Zellen unterhalb der Zelle, die einen Plot ausgibt, nicht auf den Plot aus. Beispielsweise ist es nicht möglich, die Farbtabelle von Zellen unterhalb der Zelle zu ändern, die ein Diagramm erstellt. Bei anderen Backends wie Qt, die ein separates Fenster öffnen, ändern Zellen unter denen, die das Diagramm erstellen, jedoch das Diagramm - es ist ein Live-Objekt im Speicher.

Dieses Tutorial verwendet die implizite Plotschnittstelle von Matplotlib, pyplot. Diese Schnittstelle behält den globalen Zustand bei und ist sehr nützlich, um schnell und einfach mit verschiedenen Ploteinstellungen zu experimentieren. Die Alternative ist die explizite, die besser für die Entwicklung großer Anwendungen geeignet ist. Eine Erläuterung der Kompromisse zwischen den impliziten und expliziten Schnittstellen finden Sie unter Matplotlib-Anwendungsschnittstellen (APIs) und in der Schnellstartanleitung , um mit der Verwendung der expliziten Schnittstelle zu beginnen. Lassen Sie uns zunächst mit dem impliziten Ansatz fortfahren:

import matplotlib.pyplot as plt
import matplotlib.image as mpimg

Bilddaten in Numpy-Arrays importieren #

Matplotlib verlässt sich auf die Pillow -Bibliothek, um Bilddaten zu laden.

Hier ist das Bild, mit dem wir spielen werden:

../../_images/stinkbug.png

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

Und es geht los...

img = mpimg.imread('../../doc/_static/stinkbug.png')
print(img)
[[[0.40784314 0.40784314 0.40784314]
  [0.40784314 0.40784314 0.40784314]
  [0.40784314 0.40784314 0.40784314]
  ...
  [0.42745098 0.42745098 0.42745098]
  [0.42745098 0.42745098 0.42745098]
  [0.42745098 0.42745098 0.42745098]]

 [[0.4117647  0.4117647  0.4117647 ]
  [0.4117647  0.4117647  0.4117647 ]
  [0.4117647  0.4117647  0.4117647 ]
  ...
  [0.42745098 0.42745098 0.42745098]
  [0.42745098 0.42745098 0.42745098]
  [0.42745098 0.42745098 0.42745098]]

 [[0.41960785 0.41960785 0.41960785]
  [0.41568628 0.41568628 0.41568628]
  [0.41568628 0.41568628 0.41568628]
  ...
  [0.43137255 0.43137255 0.43137255]
  [0.43137255 0.43137255 0.43137255]
  [0.43137255 0.43137255 0.43137255]]

 ...

 [[0.4392157  0.4392157  0.4392157 ]
  [0.43529412 0.43529412 0.43529412]
  [0.43137255 0.43137255 0.43137255]
  ...
  [0.45490196 0.45490196 0.45490196]
  [0.4509804  0.4509804  0.4509804 ]
  [0.4509804  0.4509804  0.4509804 ]]

 [[0.44313726 0.44313726 0.44313726]
  [0.44313726 0.44313726 0.44313726]
  [0.4392157  0.4392157  0.4392157 ]
  ...
  [0.4509804  0.4509804  0.4509804 ]
  [0.44705883 0.44705883 0.44705883]
  [0.44705883 0.44705883 0.44705883]]

 [[0.44313726 0.44313726 0.44313726]
  [0.4509804  0.4509804  0.4509804 ]
  [0.4509804  0.4509804  0.4509804 ]
  ...
  [0.44705883 0.44705883 0.44705883]
  [0.44705883 0.44705883 0.44705883]
  [0.44313726 0.44313726 0.44313726]]]

Beachten Sie dort den dtype - float32. Matplotlib hat die 8-Bit-Daten von jedem Kanal in Fließkommadaten zwischen 0,0 und 1,0 neu skaliert. Nebenbei bemerkt, der einzige Datentyp, mit dem Pillow arbeiten kann, ist uint8. Matplotlib-Plotten kann Float32 und uint8 verarbeiten, aber das Lesen/Schreiben von Bildern für andere Formate als PNG ist auf uint8-Daten beschränkt. Warum 8 Bit? Die meisten Displays können nur eine Farbabstufung von 8 Bit pro Kanal wiedergeben. Warum können sie nur 8 Bit/Kanal rendern? Denn das ist alles, was das menschliche Auge sehen kann. Mehr hier (aus fotografischer Sicht): Tutorial zur Bittiefe von Luminous Landscape .

Jede innere Liste repräsentiert ein Pixel. Hier gibt es bei einem RGB-Bild 3 Werte. Da es sich um ein Schwarz-Weiß-Bild handelt, sind R, G und B alle ähnlich. Ein RGBA (wobei A Alpha oder Transparenz ist) hat 4 Werte pro innerer Liste, und ein einfaches Luminanzbild hat nur einen Wert (und ist daher nur ein 2-D-Array, kein 3-D-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 keine dieser Beschreibungen erfüllen, 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 imshow()Funktion durchgeführt. Hier greifen wir das Plot-Objekt. Dieses Objekt bietet Ihnen eine einfache Möglichkeit, den Plot von der Eingabeaufforderung aus zu manipulieren.

Bilder

Sie können auch jedes numpy-Array plotten.

Anwenden von Pseudofarbschemata auf Bildplots #

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

Pseudofarbe ist nur für Einkanal-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 nur einen Kanal unserer Daten auswählen:

lum_img = img[:, :, 0]

# This is array slicing.  You can read more in the `Numpy tutorial
# <https://numpy.org/doc/stable/user/quickstart.html>`_.

plt.imshow(lum_img)
Bilder
<matplotlib.image.AxesImage object at 0x7f2cdd608610>

Jetzt wird bei einem Luminanzbild (2D, keine Farbe) die Standardfarbkarte (auch bekannt als Nachschlagetabelle, LUT) angewendet. Der Standard heißt viridis. Es gibt viele andere zur Auswahl.

plt.imshow(lum_img, cmap="hot")
Bilder
<matplotlib.image.AxesImage object at 0x7f2cddcc2aa0>

Beachten Sie, dass Sie mit der folgenden Methode auch Colormaps auf vorhandenen Plotobjekten ändern können set_cmap():

Bilder

Notiz

Denken Sie jedoch daran, dass Sie im Jupyter Notebook mit dem Inline-Back-End keine Änderungen an bereits gerenderten Plots vornehmen können. Wenn Sie hier in einer Zelle imgplot erstellen, können Sie in einer späteren Zelle nicht set_cmap() darauf 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 Diagramme von früheren Zellen.

Es sind viele andere Farbschemata verfügbar. Sehen Sie sich die Liste und Bilder der Farbkarten an .

Farbskalenreferenz #

Es ist hilfreich, eine Vorstellung davon zu haben, welchen Wert eine Farbe darstellt. Wir können das tun, indem wir Ihrer Figur einen Farbbalken hinzufügen:

Bilder
<matplotlib.colorbar.Colorbar object at 0x7f2cdf5297e0>

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 nicht stark variieren oder keine Rolle spielen. Ein gutes Hilfsmittel, um interessante Regionen zu finden, ist das Histogramm. Um ein Histogramm unserer Bilddaten zu erstellen, verwenden wir die hist()Funktion.

plt.hist(lum_img.ravel(), bins=256, range=(0.0, 1.0), fc='k', ec='k')
Bilder
(array([2.000e+00, 2.000e+00, 3.000e+00, 3.000e+00, 2.000e+00, 2.000e+00,
       3.000e+00, 1.000e+00, 7.000e+00, 9.000e+00, 7.000e+00, 2.000e+00,
       7.000e+00, 1.000e+01, 1.100e+01, 1.500e+01, 1.400e+01, 2.700e+01,
       2.100e+01, 2.400e+01, 1.400e+01, 3.100e+01, 2.900e+01, 2.800e+01,
       2.400e+01, 2.400e+01, 4.000e+01, 2.600e+01, 5.200e+01, 3.900e+01,
       5.700e+01, 4.600e+01, 8.400e+01, 7.600e+01, 8.900e+01, 8.000e+01,
       1.060e+02, 1.130e+02, 1.120e+02, 9.000e+01, 1.160e+02, 1.090e+02,
       1.270e+02, 1.350e+02, 9.800e+01, 1.310e+02, 1.230e+02, 1.110e+02,
       1.230e+02, 1.160e+02, 1.010e+02, 1.170e+02, 1.000e+02, 1.010e+02,
       9.000e+01, 1.060e+02, 1.260e+02, 1.040e+02, 1.070e+02, 1.110e+02,
       1.380e+02, 1.000e+02, 1.340e+02, 1.210e+02, 1.400e+02, 1.320e+02,
       1.390e+02, 1.160e+02, 1.330e+02, 1.180e+02, 1.080e+02, 1.170e+02,
       1.280e+02, 1.200e+02, 1.210e+02, 1.100e+02, 1.160e+02, 1.180e+02,
       9.700e+01, 9.700e+01, 1.140e+02, 1.070e+02, 1.170e+02, 8.700e+01,
       1.070e+02, 9.800e+01, 1.040e+02, 1.120e+02, 1.110e+02, 1.180e+02,
       1.240e+02, 1.340e+02, 1.200e+02, 1.410e+02, 1.520e+02, 1.360e+02,
       1.610e+02, 1.380e+02, 1.620e+02, 1.570e+02, 1.350e+02, 1.470e+02,
       1.690e+02, 1.710e+02, 1.820e+02, 1.980e+02, 1.970e+02, 2.060e+02,
       2.160e+02, 2.460e+02, 2.210e+02, 2.520e+02, 2.890e+02, 3.450e+02,
       3.620e+02, 3.760e+02, 4.480e+02, 4.630e+02, 5.170e+02, 6.000e+02,
       6.200e+02, 6.410e+02, 7.440e+02, 7.120e+02, 8.330e+02, 9.290e+02,
       1.061e+03, 1.280e+03, 1.340e+03, 1.638e+03, 1.740e+03, 1.953e+03,
       2.151e+03, 2.290e+03, 2.440e+03, 2.758e+03, 2.896e+03, 3.384e+03,
       4.332e+03, 5.584e+03, 6.197e+03, 6.422e+03, 6.404e+03, 7.181e+03,
       8.196e+03, 7.968e+03, 7.474e+03, 7.926e+03, 8.460e+03, 8.091e+03,
       9.148e+03, 8.563e+03, 6.747e+03, 6.074e+03, 6.328e+03, 5.291e+03,
       6.472e+03, 6.268e+03, 2.864e+03, 3.760e+02, 1.620e+02, 1.180e+02,
       1.270e+02, 9.500e+01, 7.600e+01, 8.200e+01, 6.200e+01, 6.700e+01,
       5.600e+01, 5.900e+01, 4.000e+01, 4.200e+01, 3.000e+01, 3.400e+01,
       3.200e+01, 4.300e+01, 4.200e+01, 2.300e+01, 2.800e+01, 1.900e+01,
       2.200e+01, 1.600e+01, 1.200e+01, 1.800e+01, 9.000e+00, 1.000e+01,
       1.700e+01, 5.000e+00, 2.100e+01, 1.300e+01, 8.000e+00, 1.200e+01,
       1.000e+01, 8.000e+00, 8.000e+00, 5.000e+00, 1.300e+01, 6.000e+00,
       3.000e+00, 7.000e+00, 6.000e+00, 2.000e+00, 1.000e+00, 5.000e+00,
       3.000e+00, 3.000e+00, 1.000e+00, 1.000e+00, 1.000e+00, 5.000e+00,
       0.000e+00, 1.000e+00, 3.000e+00, 0.000e+00, 1.000e+00, 1.000e+00,
       2.000e+00, 1.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00,
       0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00,
       0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00,
       0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00,
       0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00,
       0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00,
       0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00]), array([0.        , 0.00390625, 0.0078125 , 0.01171875, 0.015625  ,
       0.01953125, 0.0234375 , 0.02734375, 0.03125   , 0.03515625,
       0.0390625 , 0.04296875, 0.046875  , 0.05078125, 0.0546875 ,
       0.05859375, 0.0625    , 0.06640625, 0.0703125 , 0.07421875,
       0.078125  , 0.08203125, 0.0859375 , 0.08984375, 0.09375   ,
       0.09765625, 0.1015625 , 0.10546875, 0.109375  , 0.11328125,
       0.1171875 , 0.12109375, 0.125     , 0.12890625, 0.1328125 ,
       0.13671875, 0.140625  , 0.14453125, 0.1484375 , 0.15234375,
       0.15625   , 0.16015625, 0.1640625 , 0.16796875, 0.171875  ,
       0.17578125, 0.1796875 , 0.18359375, 0.1875    , 0.19140625,
       0.1953125 , 0.19921875, 0.203125  , 0.20703125, 0.2109375 ,
       0.21484375, 0.21875   , 0.22265625, 0.2265625 , 0.23046875,
       0.234375  , 0.23828125, 0.2421875 , 0.24609375, 0.25      ,
       0.25390625, 0.2578125 , 0.26171875, 0.265625  , 0.26953125,
       0.2734375 , 0.27734375, 0.28125   , 0.28515625, 0.2890625 ,
       0.29296875, 0.296875  , 0.30078125, 0.3046875 , 0.30859375,
       0.3125    , 0.31640625, 0.3203125 , 0.32421875, 0.328125  ,
       0.33203125, 0.3359375 , 0.33984375, 0.34375   , 0.34765625,
       0.3515625 , 0.35546875, 0.359375  , 0.36328125, 0.3671875 ,
       0.37109375, 0.375     , 0.37890625, 0.3828125 , 0.38671875,
       0.390625  , 0.39453125, 0.3984375 , 0.40234375, 0.40625   ,
       0.41015625, 0.4140625 , 0.41796875, 0.421875  , 0.42578125,
       0.4296875 , 0.43359375, 0.4375    , 0.44140625, 0.4453125 ,
       0.44921875, 0.453125  , 0.45703125, 0.4609375 , 0.46484375,
       0.46875   , 0.47265625, 0.4765625 , 0.48046875, 0.484375  ,
       0.48828125, 0.4921875 , 0.49609375, 0.5       , 0.50390625,
       0.5078125 , 0.51171875, 0.515625  , 0.51953125, 0.5234375 ,
       0.52734375, 0.53125   , 0.53515625, 0.5390625 , 0.54296875,
       0.546875  , 0.55078125, 0.5546875 , 0.55859375, 0.5625    ,
       0.56640625, 0.5703125 , 0.57421875, 0.578125  , 0.58203125,
       0.5859375 , 0.58984375, 0.59375   , 0.59765625, 0.6015625 ,
       0.60546875, 0.609375  , 0.61328125, 0.6171875 , 0.62109375,
       0.625     , 0.62890625, 0.6328125 , 0.63671875, 0.640625  ,
       0.64453125, 0.6484375 , 0.65234375, 0.65625   , 0.66015625,
       0.6640625 , 0.66796875, 0.671875  , 0.67578125, 0.6796875 ,
       0.68359375, 0.6875    , 0.69140625, 0.6953125 , 0.69921875,
       0.703125  , 0.70703125, 0.7109375 , 0.71484375, 0.71875   ,
       0.72265625, 0.7265625 , 0.73046875, 0.734375  , 0.73828125,
       0.7421875 , 0.74609375, 0.75      , 0.75390625, 0.7578125 ,
       0.76171875, 0.765625  , 0.76953125, 0.7734375 , 0.77734375,
       0.78125   , 0.78515625, 0.7890625 , 0.79296875, 0.796875  ,
       0.80078125, 0.8046875 , 0.80859375, 0.8125    , 0.81640625,
       0.8203125 , 0.82421875, 0.828125  , 0.83203125, 0.8359375 ,
       0.83984375, 0.84375   , 0.84765625, 0.8515625 , 0.85546875,
       0.859375  , 0.86328125, 0.8671875 , 0.87109375, 0.875     ,
       0.87890625, 0.8828125 , 0.88671875, 0.890625  , 0.89453125,
       0.8984375 , 0.90234375, 0.90625   , 0.91015625, 0.9140625 ,
       0.91796875, 0.921875  , 0.92578125, 0.9296875 , 0.93359375,
       0.9375    , 0.94140625, 0.9453125 , 0.94921875, 0.953125  ,
       0.95703125, 0.9609375 , 0.96484375, 0.96875   , 0.97265625,
       0.9765625 , 0.98046875, 0.984375  , 0.98828125, 0.9921875 ,
       0.99609375, 1.        ]), <BarContainer object of 256 artists>)

Meistens befindet sich der "interessante" Teil des Bildes um die Spitze herum, und Sie können zusätzlichen Kontrast erzielen, indem Sie die Bereiche über und/oder unter der Spitze beschneiden. In unserem Histogramm sieht es so aus, als gäbe es im oberen Bereich nicht viele nützliche Informationen (nicht viele weiße Dinge im Bild). Lassen Sie uns die Obergrenze anpassen, sodass wir einen Teil des Histogramms effektiv „heranzoomen“. Dazu übergeben wir das clim-Argument an imshow. Sie können dies auch tun, indem Sie die set_clim()Methode des Bildplotobjekts aufrufen, aber stellen Sie sicher, dass Sie dies in derselben Zelle tun wie Ihr Plotbefehl, wenn Sie mit Jupyter Notebook arbeiten – es werden Plots von früheren Zellen nicht geändert.

Sie können das Klima im Aufruf an angeben plot.

imgplot = plt.imshow(lum_img, clim=(0.0, 0.7))
Bilder

Sie können das Klima auch mit dem zurückgegebenen Objekt angeben

fig = plt.figure()
ax = fig.add_subplot(1, 2, 1)
imgplot = plt.imshow(lum_img)
ax.set_title('Before')
plt.colorbar(ticks=[0.1, 0.3, 0.5, 0.7], orientation='horizontal')
ax = fig.add_subplot(1, 2, 2)
imgplot = plt.imshow(lum_img)
imgplot.set_clim(0.0, 0.7)
ax.set_title('After')
plt.colorbar(ticks=[0.1, 0.3, 0.5, 0.7], orientation='horizontal')
Vorher Nachher
<matplotlib.colorbar.Colorbar object at 0x7f2cdf75fa30>

Array-Interpolationsschemata #

Die Interpolation berechnet nach verschiedenen mathematischen Schemata, was die Farbe oder der Wert eines Pixels sein "sollte". Ein häufiger Ort, an dem dies passiert, ist, wenn Sie die Größe eines Bildes ändern. Die Anzahl der Pixel ändert sich, aber Sie möchten die gleichen Informationen. Da Pixel diskret sind, fehlt Platz. Durch Interpolation füllen Sie diesen Raum aus. Aus diesem Grund sehen Ihre Bilder manchmal verpixelt aus, wenn Sie sie in die Luft jagen. Der Effekt ist ausgeprägter, 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 einige wenige. Wenn wir es jetzt plotten, werden diese Daten auf die Größe auf Ihrem Bildschirm vergrößert. Die alten Pixel sind nicht mehr vorhanden, und der Computer muss Pixel einzeichnen, um diesen Raum zu füllen.

Wir verwenden die Pillow-Bibliothek, mit der wir das Bild geladen haben, auch, um die Größe des Bildes zu ändern.

from PIL import Image

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

Hier haben wir die Standardinterpolation, bilinear, da wir kein imshow()Interpolationsargument angegeben haben.

Lassen Sie uns einige andere versuchen. Hier ist "nächster", der keine Interpolation durchführt.

imgplot = plt.imshow(img, interpolation="nearest")
Bilder

und bikubisch:

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

Die bikubische Interpolation wird oft beim Vergrößern von Fotos verwendet - die Leute bevorzugen eher verschwommen als pixelig.

Gesamtlaufzeit des Skripts: ( 0 Minuten 8.344 Sekunden)

Galerie generiert von Sphinx-Gallery