HOWTO · Matplotlib
NumPy-Array in PIL-Bild konvertieren in Python
Dieses Tutorial erklärt, wie wir ein NumPy-Array in ein PIL-Bild konvertieren können, indem wir die Funktion Image.fromarray() aus dem PIL-Paket verwenden.
Auf dieser Seite
Mit Pillow’s Image.fromarray() erstellen Sie aus einem NumPy-Array ein PIL-Bild. Ein zweidimensionales Array stellt Graustufenpixel dar; Arrays mit der Form (height, width, 3) oder (height, width, 4) stehen für RGB- beziehungsweise RGBA-Pixel. Auch Datentyp und Werte des Arrays sind wichtig. Prüfen Sie beides vor der Umwandlung. PIL ist der vertraute Importname, Pillow die gepflegte Bibliothek.
Für ein RGB-Bild erstellen Sie ein Array mit drei Kanälen und dem Datentyp uint8 und übergeben es an Image.fromarray(). Die Ausgabe zeigt den Bildmodus, die Größe in (width, height) und den Pixel oben links.
Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.
import numpy as np
from PIL import Image
pixels = np.array(
[[[255, 0, 0], [0, 255, 0]], [[0, 0, 255], [255, 255, 255]]],
dtype=np.uint8,
)
image = Image.fromarray(pixels)
print(image.mode, image.size, image.getpixel((0, 0)))
RGB (2, 2) (255, 0, 0)
Das resultierende Bild ist ein Pillow-Objekt im Arbeitsspeicher. Sie können Modus und Abmessungen prüfen, es in einer Umgebung mit Bildvorschau anzeigen oder in einer Datei speichern.
Ein NumPy-Array mit Image.fromarray() in ein PIL-Bild umwandeln
Image.fromarray(array) leitet den Bildmodus aus Form und Datentyp des Arrays ab. Für Graustufendaten verwenden Sie ein zweidimensionales Array mit der Form (height, width). Für RGB-Daten ist die Form (height, width, 3) erforderlich; ein optionaler vierter Kanal ergibt RGBA. Die ersten beiden Dimensionen stehen für Zeilen und Spalten. Ein Array mit 40 Zeilen und 60 Spalten ergibt daher ein Bild mit 60 Pixeln Breite und 40 Pixeln Höhe.
Verwenden Sie np.uint8 für gewöhnliche 8-Bit-Bildwerte, wenn diese bereits als Ganzzahlen zwischen 0 und 255 vorliegen. Wandeln Sie den Datentyp nicht ungeprüft um: Beim Umwandeln von Gleitkommazahlen gehen Nachkommastellen verloren, und Werte außerhalb des darstellbaren Bereichs können überlaufen. Bei Daten mit einer anderen Skala müssen Sie vor der Umwandlung festlegen, wie sie auf die Anzeigeintensität abgebildet werden sollen. Werte im Intervall 0–1 können beispielsweise mit 255 multipliziert und gerundet werden. Bei anderen Wertebereichen ist eine explizite Normalisierung erforderlich, die sich nach der Bedeutung der Daten richtet.
Form, Datentyp und Wertebereich des Arrays vorbereiten
Ein Array mit der Form (height, width) ist ein Graustufenbild. RGB- und RGBA-Arrays haben zusätzlich eine letzte Kanal-Dimension mit drei beziehungsweise vier Werten pro Pixel. Die Form (height, width, 1) entspricht nicht der üblichen zweidimensionalen Form für Graustufen. Wenn die einzelne letzte Achse Graustufen darstellt, entfernen Sie sie mit array[..., 0]. Prüfen Sie vor der Umwandlung array.shape, array.dtype sowie Minimal- und Maximalwert. Das Array muss ein regelmäßiges rechteckiges Raster enthalten; verschachtelte Listen mit unterschiedlich langen Zeilen sind keine Bilddaten.
Hier sehen Sie eine eigenständige Umwandlung in Graustufen. Die Werte liegen direkt im 8-Bit-Bereich, daher ist keine Skalierung nötig. Das resultierende Bild hat den Graustufenmodus L und die Größe (3, 2).
Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.
import numpy as np
from PIL import Image
gray = np.array([[0, 64, 128], [32, 160, 255]], dtype=np.uint8)
image = Image.fromarray(gray)
print(image.mode, image.size)
L (3, 2)
Wenn Ihr Ausgangsarray Gleitkommawerte zwischen 0 und 1 enthält, wandeln Sie diese gezielt mit np.round(array * 255).astype(np.uint8) um. Das ist nur dann passend, wenn die Werte normalisierte Intensitäten darstellen. Bei Messwerten wie Temperaturen oder beliebigen Punktzahlen wählen Sie aussagekräftige Unter- und Obergrenzen, begrenzen oder normalisieren Sie die Werte auf dieses Intervall und dokumentieren Sie die Abbildung. Andernfalls können Kontrast und Pixelwerte irreführend sein.
Vor dem Erstellen eines PIL-Bilds eine Matplotlib-Colormap anwenden
Verwenden Sie eine Matplotlib-Colormap, wenn die Quelle ein zweidimensionales Skalarfeld ist und Farben dessen Werte darstellen sollen. Normalisieren Sie die Daten auf das für die gewählte Colormap erwartete Intervall und wandeln Sie anschließend das Ergebnis der Colormap in ein 8-Bit-RGB- oder RGBA-Array um. Die Colormap plasma liefert normalisierte Rot-, Grün-, Blau- und Alphakanäle. Mit [..., :3] entfernen Sie den Alphakanal und erhalten ein RGB-Array. Dieser Schritt ist von Image.fromarray() getrennt: Die Colormap erzeugt die Farben, Pillow verpackt diese Pixel als Bild.
Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.
import numpy as np
import matplotlib
from PIL import Image
values = np.array([[0.0, 0.25], [0.75, 1.0]])
colors = matplotlib.colormaps["plasma"](values)[..., :3]
rgb = np.round(colors * 255).astype(np.uint8)
image = Image.fromarray(rgb)
print(image.mode, image.size)
RGB (2, 2)
Dieses Beispiel setzt voraus, dass values bereits auf den Bereich 0 bis 1 normalisiert ist. Weicht der tatsächliche Skalarwertebereich davon ab, normalisieren Sie die Werte vor Anwendung der Colormap anhand geeigneter Datengrenzen. Eine Colormap eignet sich zur Visualisierung, wandelt aber Skalarwerte in Anzeigefarben um. Wenn Sie die ursprünglichen Messwerte für Analysen benötigen, behalten Sie diese bei. Das resultierende Bild ist ein RGB-Bild mit der Größe (2, 2).
Das PIL-Bild skalieren und speichern
Skalieren Sie das Bild nach der Umwandlung mit image.resize((width, height)). Pillow erwartet die neue Größe in der Reihenfolge Breite, dann Höhe. Speichern und Anzeigen sind getrennte Vorgänge: show() öffnet eine Vorschau in der lokalen Umgebung, während save() eine Bilddatei schreibt. Wählen Sie eine Dateiendung, die zum gewünschten Format passt, beispielsweise .png für verlustfreie Ausgabe oder .jpg für JPEG.
Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.
import numpy as np
from PIL import Image
pixels = np.zeros((20, 30, 3), dtype=np.uint8)
pixels[:, :15] = [255, 80, 0]
pixels[:, 15:] = [20, 90, 220]
image = Image.fromarray(pixels)
resized = image.resize((60, 40))
resized.save("resized-image.png")
print(resized.size)
Das Beispiel erstellt seine Eingabe im Arbeitsspeicher und speichert resized-image.png im aktuellen Arbeitsverzeichnis. Verwenden Sie in einer Anwendung einen Pfad, der zu Ihrem Ausgabeort passt. Das Speichern verändert das NumPy-Array nicht; durch die Größenänderung ändern sich die Pixelabmessungen des Pillow-Bildes.
Häufige Probleme bei der Umwandlung
- Unerwarteter Modus oder nicht unterstützte Form: Prüfen Sie
array.shape. Verwenden Sie(height, width)für Graustufen und drei oder vier Kanäle in der letzten Dimension für RGB beziehungsweise RGBA. Entfernen Sie einen unbeabsichtigten einzelnen Kanal oder ordnen Sie die Kanäle neu an, wenn Ihre Quelle eine andere Konvention verwendet. - Falsche Helligkeit oder Farben: Prüfen Sie vor der Umwandlung den Wertebereich. Als Gleitkommazahlen gespeicherte Werte zwischen 0 und 1 müssen für ein 8-Bit-Bild gezielt skaliert werden. Werte zwischen 0 und 255 dürfen nicht nochmals mit 255 multipliziert werden. Normalisieren Sie andere Wertebereiche auf dokumentierte Grenzen.
- Unerwarteter Datentyp: Prüfen Sie
array.dtypeund entscheiden Sie, wie Sie ihn umwandeln. Eine reine Typumwandlung skaliert die Daten nicht. Bewahren Sie eine Kopie der Quelle auf, wenn die ursprüngliche Genauigkeit wichtig ist. - Unerwartetes Ergebnis der Colormap: Prüfen Sie, ob die Skalar-Eingabe wie beabsichtigt normalisiert wurde und ob das Ergebnis drei RGB- oder vier RGBA-Kanäle hat. Wandeln Sie die normalisierten Farbkanäle vor dem Erstellen des Bildes in
uint8um. - Bilddatei wird nicht erstellt: Rufen Sie
save()mit einem beschreibbaren Pfad und einer unterstützten Dateiendung auf. Verwenden Sieshow()nur für eine Vorschau; damit wird das Bild nicht gespeichert.