So konvertieren Sie ein NumPy-Array mithilfe der Matplotlib-Farbkarte in ein PIL-Bild

132

Ich habe ein einfaches Problem, aber ich kann keine gute Lösung dafür finden.

Ich möchte ein NumPy 2D-Array, das ein Graustufenbild darstellt, in ein RGB-PIL-Bild konvertieren, während ich einige der Matplotlib-Farbkarten anwende.

Ich kann eine vernünftige PNG-Ausgabe erhalten, indem ich den folgenden pyplot.figure.figimageBefehl verwende:

dpi = 100.0
w, h = myarray.shape[1]/dpi, myarray.shape[0]/dpi
fig = plt.figure(figsize=(w,h), dpi=dpi)
fig.figimage(sub, cmap=cm.gist_earth)
plt.savefig('out.png')

Obwohl ich dies anpassen könnte, um das zu bekommen, was ich will (wahrscheinlich bekomme ich mit StringIO das PIL-Bild), frage ich mich, ob es keinen einfacheren Weg gibt, dies zu tun, da es ein sehr natürliches Problem der Bildvisualisierung zu sein scheint. Sagen wir so etwas:

colored_PIL_image = magic_function(array, cmap)
Heltonbiker
quelle
Für voll funktionsfähigen Code können Sie Folgendes beachten: Gibt es eine gute Farbkarte, um Graustufenbilder mithilfe von Pythons PIL in bunte Bilder umzuwandeln?
Adam

Antworten:

220

Ein ziemlich beschäftigter Einzeiler, aber hier ist es:

  1. Stellen Sie zunächst sicher, dass Ihr NumPy-Array myarraymit dem Maximalwert bei normalisiert ist 1.0.
  2. Wenden Sie die Farbkarte direkt auf an myarray.
  3. In den 0-255Bereich skalieren .
  4. Konvertieren Sie mit in ganze Zahlen np.uint8().
  5. Verwenden Sie Image.fromarray().

Und du bist fertig:

from PIL import Image
from matplotlib import cm
im = Image.fromarray(np.uint8(cm.gist_earth(myarray)*255))

mit plt.savefig():

Geben Sie hier die Bildbeschreibung ein

mit im.save():

Geben Sie hier die Bildbeschreibung ein

fraxel
quelle
7
Der Teil "Farbkarte direkt anwenden auf myarray" schneidet direkt ins Herz! Ich wusste nicht, dass es möglich ist, danke!
Heltonbiker
34
Beim Studium der Dokumente zu LinearSegmentedColormap (von denen cm.gist_earth eine Instanz ist) stellte ich fest, dass es möglich ist, es mit einem "Bytes" -Argument aufzurufen, das es bereits in uint8 konvertiert. Dann wird der im = Image.fromarray(cm.gist_earth(myarray, bytes=True))
Einzeiler
1
@CiprianTomoiaga, die Form des Arrays sollte den gewünschten Bildabmessungen entsprechen. Beispielsweise würde ein VGA-Bild aus einem Array mit Form (1024.768) erzeugt. Sie sollten beachten, dass dies für monochrome Bilder gilt. Dies ist wichtig, da normalerweise beim Konvertieren eines RGB-Bilds in ein Array die Form beispielsweise (1024.768.3) beträgt, da es drei Kanäle hat.
Heltonbiker
5
Ich NameError: name 'cm' is not defined
erhalte
10
@msofrom matplotlib import cm
Quantum7
10
  • input = numpy_image
  • np.unit8 -> konvertiert in ganze Zahlen
  • konvertieren ('RGB') -> konvertiert in RGB
  • Image.fromarray -> gibt ein Bildobjekt zurück

    from PIL import Image
    import numpy as np
    
    PIL_image = Image.fromarray(np.uint8(numpy_image)).convert('RGB')
    
    PIL_image = Image.fromarray(numpy_image.astype('uint8'), 'RGB')
Aravinda_gn
quelle
5
Hoffe, es wird das Problem lösen, aber bitte fügen Sie eine Erklärung Ihres Codes hinzu, damit der Benutzer ein perfektes Verständnis dafür erhält, was er wirklich will.
Jaimil Patel
1
Gute, aktualisierte Antwort. Die vorherigen stammen von vor einigen Jahren.
Catalina Chircu
7

Die in der akzeptierten Antwort beschriebene Methode hat bei mir auch nach Anwendung der in den Kommentaren genannten Änderungen nicht funktioniert. Aber der folgende einfache Code hat funktioniert:

import matplotlib.pyplot as plt
plt.imsave(filename, np_array, cmap='Greys')

np_array kann entweder ein 2D-Array mit Werten von 0..1 Floats o2 0..255 uint8 sein, und in diesem Fall benötigt es cmap. Bei 3D-Arrays wird cmap ignoriert.

Shital Shah
quelle