Wie konvertiere ich ein Numpy-Array in ein Bild (und zeige es an)?

227

Ich habe ein Array so erstellt:

import numpy as np
data = np.zeros( (512,512,3), dtype=np.uint8)
data[256,256] = [255,0,0]

Ich möchte, dass dies einen einzelnen roten Punkt in der Mitte eines 512x512-Bildes anzeigt. (Zumindest zu Beginn ... Ich denke, ich kann den Rest von dort herausfinden)

jlswint
quelle
1
Siehe auch stackoverflow.com/questions/902761/…, obwohl dieser die Einschränkung auferlegte, dass PIL nicht verwendet werden konnte.
Peter Hansen
Könnten Sie erwägen, die akzeptierte Antwort auf Peters zu ändern ? Beides vermeidet die Notwendigkeit, ein Objekt um das Numpy-Array zu wickeln, und vermeidet das Schreiben einer temporären Datei, um das Bild anzuzeigen.
Josiah Yoder

Antworten:

223

Sie können PIL verwenden, um ein Bild zu erstellen (und anzuzeigen):

from PIL import Image
import numpy as np

w, h = 512, 512
data = np.zeros((h, w, 3), dtype=np.uint8)
data[0:256, 0:256] = [255, 0, 0] # red patch in upper left
img = Image.fromarray(data, 'RGB')
img.save('my.png')
img.show()
unutbu
quelle
3
Es scheint, dass es einen Fehler gibt. Sie erstellen ein Array mit einer Größe (w,h,3), dies sollte jedoch der Fall sein (h,w,3), da sich die Indizierung in PIL von der Indizierung in numpy unterscheidet. Es gibt verwandte Frage: stackoverflow.com/questions/33725237/…
fdermishin
1
@ user502144: Danke, dass du auf meinen Fehler hingewiesen hast. Ich hätte eine Reihe von Formen erstellen sollen (h,w,3). (Es ist jetzt oben festgelegt.) Die Länge der ersten Achse kann als Anzahl der Zeilen im Array und die Länge der zweiten Achse als Anzahl der Spalten betrachtet werden. Entspricht also (h, w)einem Array von "Höhe" hund "Breite" w. Image.fromarraykonvertiert dieses Array in ein Bild mit Höhe hund Breite w.
Unutbu
1
img.show()funktioniert nicht in ipython notebook. img_pil = Image.fromarray(img, 'RGB') display(img_pil.resize((256,256), PIL.Image.LANCZOS))
Mrgloom
@unutbu Diese Methode scheint Bilder zu verzerren ... stackoverflow.com/questions/62293077/…
Ludovico Verniani
284

Folgendes sollte funktionieren:

from matplotlib import pyplot as plt
plt.imshow(data, interpolation='nearest')
plt.show()

Wenn Sie Jupyter Notebook / Lab verwenden, verwenden Sie diesen Inline-Befehl, bevor Sie matplotlib importieren:

%matplotlib inline 
Steve Tjoa
quelle
3
Dies ist genauer als PIL. PIL skaliert / normalisiert die Array-Werte neu, während Pyplot die tatsächlichen RGB-Werte unverändert verwendet.
GaryO
20
Vielleicht gut zu wissen: Wenn Sie Graustufenbilder anzeigen möchten, ist es ratsam, plt.gray()einmal in Ihrem Code aufzurufen , um alle folgenden Grafiken auf Graustufen umzustellen. Nicht was das OP will, aber trotzdem gut zu wissen.
Cerno
2
Wie speichere ich es?
user334639
Datei "<ipython-input-29-29c784f62838>", Zeile 39 plt.show () ^ SyntaxError: ungültige Syntax
Mona Jalal
1
@Cerno Außerdem sollten Graustufenbilder eher die Form (h, w) als (h, w, 1) haben. Sie können verwenden squeeze(), um die dritte Dimension zu beseitigen:plt.imshow(data.squeeze())
Josiah Yoder
51

Der kürzeste Weg ist scipywie folgt :

from scipy.misc import toimage
toimage(data).show()

Dazu muss auch PIL oder Pillow installiert sein.

Ein ähnlicher Ansatz, der auch PIL oder Pillow erfordert, aber möglicherweise einen anderen Betrachter aufruft, ist:

from scipy.misc import imshow
imshow(data)
Peter Hansen
quelle
Diese Methode ist also nicht mit Python 3.5 kompatibel ...?
Christopher
@bordeo, warum sollte es mit 3.5 nicht kompatibel sein? Es ist nur ein Import und ein paar Funktionsaufrufe.
Peter Hansen
PIL ist nicht kompatibel mit 3.5 (wird nicht installiert)
Christopher
1
Ftr: Sie können dies durch direkte Verwendung weiter verkürzen scipy.misc.imshow(data).
dtk
3
toimagewurde in scipy-1.0.0 veraltet und in 1.2.0 zugunsten von Pillow's entfernt Image.fromarray.
Sid
4

Mit Pygame können Sie ein Fenster öffnen, die Oberfläche als Array von Pixeln abrufen und von dort aus beliebig bearbeiten . Sie müssen Ihr Numpy-Array jedoch in das Oberflächen-Array kopieren, was viel langsamer ist als die eigentlichen Grafikoperationen auf den Pygame-Oberflächen selbst.

Stefan Kendall
quelle
3

So zeigen Sie Bilder, die in einem numpy-Array gespeichert sind, anhand eines Beispiels an (funktioniert im Jupyter-Notizbuch)

Ich weiß, dass es einfachere Antworten gibt, aber diese geben Ihnen ein Verständnis dafür, wie Bilder tatsächlich aus einem numpy-Array ertrinken.

Beispiel laden

from sklearn.datasets import load_digits
digits = load_digits()
digits.images.shape   #this will give you (1797, 8, 8). 1797 images, each 8 x 8 in size

Array eines Bildes anzeigen

digits.images[0]
array([[ 0.,  0.,  5., 13.,  9.,  1.,  0.,  0.],
       [ 0.,  0., 13., 15., 10., 15.,  5.,  0.],
       [ 0.,  3., 15.,  2.,  0., 11.,  8.,  0.],
       [ 0.,  4., 12.,  0.,  0.,  8.,  8.,  0.],
       [ 0.,  5.,  8.,  0.,  0.,  9.,  8.,  0.],
       [ 0.,  4., 11.,  0.,  1., 12.,  7.,  0.],
       [ 0.,  2., 14.,  5., 10., 12.,  0.,  0.],
       [ 0.,  0.,  6., 13., 10.,  0.,  0.,  0.]])

Erstellen Sie leere 10 x 10 Untergrundstücke zur Visualisierung von 100 Bildern

import matplotlib.pyplot as plt
fig, axes = plt.subplots(10,10, figsize=(8,8))

Plotten von 100 Bildern

for i,ax in enumerate(axes.flat):
    ax.imshow(digits.images[i])

Ergebnis:

Geben Sie hier die Bildbeschreibung ein

Was macht axes.flatdas Es wird ein Numpy-Enumerator erstellt, sodass Sie über die Achse iterieren können, um Objekte darauf zu zeichnen. Beispiel:

import numpy as np
x = np.arange(6).reshape(2,3)
x.flat
for item in (x.flat):
    print (item, end=' ')
Harvey
quelle
2

Verwenden Sie zum Beispiel Kissen aus dem Array:

from PIL import Image
from numpy import *

im = array(Image.open('image.jpg'))
Image.fromarray(im).show()
user3322286
quelle
0

Ergänzung dazu mit matplotlib. Ich fand es praktisch, Computer Vision-Aufgaben zu erledigen. Angenommen, Sie haben Daten mit dtype = int32

from matplotlib import pyplot as plot
import numpy as np

fig = plot.figure()
ax = fig.add_subplot(1, 1, 1)
# make sure your data is in H W C, otherwise you can change it by
# data = data.transpose((_, _, _))
data = np.zeros((512,512,3), dtype=np.int32)
data[256,256] = [255,0,0]
ax.imshow(data.astype(np.uint8))
user140536
quelle