Comment convertir un tableau numpy en (et afficher) une image?


228

J'ai ainsi créé un tableau:

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

Ce que je veux faire, c'est afficher un seul point rouge au centre d'une image 512x512. (Au moins pour commencer ... je pense que je peux comprendre le reste à partir de là)


1
Voir aussi stackoverflow.com/questions/902761/… bien que celui-ci imposait la contrainte que PIL ne pouvait pas être utilisé.
Peter Hansen

Pourriez-vous envisager de changer la réponse acceptée à celle de Peter ? Cela évite à la fois la nécessité d'enrouler un objet autour du tableau numpy et évite d'écrire un fichier temporaire pour afficher l'image.
Josiah Yoder

Réponses:


225

Vous pouvez utiliser PIL pour créer (et afficher) une image:

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()

3
Il semble qu'il y ait un bug. Vous créez un tableau avec une taille (w,h,3), mais cela devrait l'être (h,w,3), car l'indexation dans PIL diffère de l'indexation dans numpy. Il y a une question connexe: stackoverflow.com/questions/33725237/…
fdermishin

1
@ user502144: Merci d'avoir signalé mon erreur. J'aurais dû créer un tableau de formes (h,w,3). (Il est maintenant fixe, ci-dessus.) La longueur du premier axe peut être considérée comme le nombre de lignes dans le tableau, et la longueur du deuxième axe, le nombre de colonnes. (h, w)Correspond donc à un tableau de "hauteur" het "largeur" w. Image.fromarrayconvertit ce tableau en une image de hauteur het de largeur w.
unutbu

1
img.show()ne fonctionne pas dans le cahier ipython. img_pil = Image.fromarray(img, 'RGB') display(img_pil.resize((256,256), PIL.Image.LANCZOS))
mrgloom

@unutbu cette méthode semble déformer les images ... stackoverflow.com/questions/62293077/…
Ludovico Verniani

285

Les éléments suivants devraient fonctionner:

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

Si vous utilisez le cahier / laboratoire Jupyter, utilisez cette commande en ligne avant d'importer matplotlib:

%matplotlib inline 

3
C'est plus précis que PIL. PIL redimensionne / normalise les valeurs du tableau, tandis que pyplot utilise les valeurs RVB réelles telles quelles.
GaryO

21
Peut-être bon à savoir: si vous souhaitez afficher des images en niveaux de gris, il est conseillé d'appeler plt.gray()une fois dans votre code pour basculer tous les graphiques suivants en niveaux de gris. Pas ce que l'OP veut mais bon à savoir quand même.
Cerno

2
Comment l'enregistrer?
user334639

Fichier "<ipython-input-29-29c784f62838>", ligne 39 plt.show () ^ SyntaxError: syntaxe non valide
Mona Jalal

1
@Cerno De plus, les images en niveaux de gris doivent avoir une forme (h, w) plutôt que (h, w, 1). Vous pouvez utiliser squeeze()pour éliminer la troisième dimension:plt.imshow(data.squeeze())
Josiah Yoder

51

Le chemin le plus court est d'utiliser scipy, comme ceci:

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

Cela nécessite également l'installation de PIL ou d'oreiller.

Une approche similaire nécessitant également PIL ou Pillow mais qui peut invoquer une visionneuse différente est:

from scipy.misc import imshow
imshow(data)

Cette méthode est donc incompatible avec python 3.5 ...?
Christopher

@bordeo, pourquoi serait-il incompatible avec 3.5? C'est juste une importation et quelques appels de fonction.
Peter Hansen

PIL est incompatible avec 3.5 (ne s'installe pas)
Christopher

1
Ftr: vous pouvez encore raccourcir cela en utilisant directement scipy.misc.imshow(data).
dtk

3
toimagea été déconseillé dans scipy-1.0.0 et supprimé dans 1.2.0, en faveur de Pillow's Image.fromarray.
Sid

4

En utilisant pygame , vous pouvez ouvrir une fenêtre, obtenir la surface sous forme de tableau de pixels et manipuler comme vous le souhaitez à partir de là. Vous devrez cependant copier votre tableau numpy dans le tableau de surface, ce qui sera beaucoup plus lent que d'effectuer des opérations graphiques réelles sur les surfaces de pygame elles-mêmes.


3

Comment afficher des images stockées dans un tableau numpy avec un exemple (fonctionne dans le cahier Jupyter)

Je sais qu'il existe des réponses plus simples, mais celle-ci vous permettra de comprendre comment les images sont réellement noyées à partir d'un tableau numpy.

Exemple de chargement

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

Afficher le tableau d'une image

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.]])

Créez des sous-tracés vides de 10 x 10 pour visualiser 100 images

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

Tracer 100 images

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

Résultat:

entrez la description de l'image ici

Que fait axes.flat-il? Il crée un énumérateur numpy afin que vous puissiez itérer sur l'axe afin de dessiner des objets dessus. Exemple:

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

2

Utilisation de fromarray d'oreiller, par exemple:

from PIL import Image
from numpy import *

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


0

Supplément pour le faire avec matplotlib. Je l'ai trouvé pratique pour effectuer des tâches de vision par ordinateur. Disons que vous avez des données avec 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))
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.