Enregistrer le tracé dans un fichier image au lieu de l'afficher à l'aide de Matplotlib


1150

J'écris un script rapide et sale pour générer des tracés à la volée. J'utilise le code ci-dessous (de la documentation Matplotlib ) comme point de départ:

from pylab import figure, axes, pie, title, show

# Make a square figure and axes
figure(1, figsize=(6, 6))
ax = axes([0.1, 0.1, 0.8, 0.8])

labels = 'Frogs', 'Hogs', 'Dogs', 'Logs'
fracs = [15, 30, 45, 10]

explode = (0, 0.05, 0, 0)
pie(fracs, explode=explode, labels=labels, autopct='%1.1f%%', shadow=True)
title('Raining Hogs and Dogs', bbox={'facecolor': '0.8', 'pad': 5})

show()  # Actually, don't show, just save to foo.png

Je ne veux pas afficher le tracé sur une interface graphique, au lieu de cela, je veux enregistrer le tracé dans un fichier (disons foo.png), afin que, par exemple, il puisse être utilisé dans des scripts de traitement par lots. Comment je fais ça?


85
On dirait que j'ai trouvé la réponse: son pylab.savefig ('foo.png')
Homunculus Reticulli

2
Le lien devrait peut-être renvoyer vers quelque part dans matplotlib.org?
A.Wan

40
De plus, si vous n'utilisez pas pylab, l'objet figure a également une savefigméthode. Vous pouvez donc appeler fig = plt.figure()alors fig.savefig(...).
A.Wan

27
Beaucoup de réponses en bas de la page mentionnent plt.close(fig)ce qui est particulièrement important dans les grandes boucles. Sinon, les chiffres restent ouverts et attendent en mémoire et tous les chiffres ouverts seront affichés lors de l'exécutionplt.show()
timctran

nb: matplotlib.pyplot est préféré: stackoverflow.com/questions/11469336/…
ErichBSchulz

Réponses:


1441

Bien que la question ait été répondue, je voudrais ajouter quelques conseils utiles lors de l'utilisation de matplotlib.pyplot.savefig . Le format de fichier peut être spécifié par l'extension:

from matplotlib import pyplot as plt

plt.savefig('foo.png')
plt.savefig('foo.pdf')

Donnera respectivement une sortie tramée ou vectorisée, les deux pouvant être utiles. De plus, vous constaterez que cela pylablaisse un espace généreux, souvent indésirable, autour de l'image. Retirez-le avec:

savefig('foo.png', bbox_inches='tight')

9
Est-il possible de changer les dimensions de l'image résultante?
Llamageddon

43
@Asmageddon Dans plt.savefigvous pouvez changer le dpi, voir le lien dans la réponse. Les dimensions peuvent être contrôlées lors de la création de la figure, voir figsizedans matplotlib.org/api/figure_api.html#matplotlib.figure.Figure
Hooked

5
@MoTSCHIGGE que vous pouvez appeler, plt.ioff()ce qui devrait désactiver l'interactivité dans les matplotlib.pyplotcommandes.
rubenvb

5
@STMohammed foo.png est le chemin. Vous pouvez, par exemple, le mettre dans un répertoire comme celui-ci savefig("mydir/foo.png").
accroché

3
bbox_inches = 'tight' fonctionne comme un charme. Tu as fait ma journée
Catbuilts

205

Comme d'autres l'ont dit, plt.savefig()ou fig1.savefig()est en effet le moyen de sauvegarder une image.

Cependant, j'ai trouvé que dans certains cas, le chiffre est toujours affiché . (par exemple avec Spyder ayant plt.ion(): mode interactif = On.) Je contourne cela en forçant la fermeture de la fenêtre de figure dans ma boucle géante avec plt.close(figure_object)(voir la documentation ), donc je n'ai pas un million de chiffres ouverts pendant la boucle:

import matplotlib.pyplot as plt
fig, ax = plt.subplots( nrows=1, ncols=1 )  # create figure & 1 axis
ax.plot([0,1,2], [10,20,3])
fig.savefig('path/to/save/image/to.png')   # save the figure to file
plt.close(fig)    # close the figure window

Vous devriez pouvoir rouvrir la figure plus tard si nécessaire avec fig.show()(je ne me suis pas testé).


9
Vous pouvez également définir plt.ioff() # turn of interactive plotting mode, mais cela peut désactiver le comportement que vous souhaitez utiliser si votre code se termine avec une erreur.
Demis

2
Vous verrez le même problème dans les cahiers Jupyter. plt.close(fig)résolu
intsco


89

Je viens de trouver ce lien sur la documentation MatPlotLib traitant exactement ce problème: http://matplotlib.org/faq/howto_faq.html#generate-images-without-having-a-window-appear

Ils disent que le moyen le plus simple d'empêcher la figure d'apparaître est d'utiliser un backend non interactif (par exemple Agg), via matplotib.use(<backend>), par exemple:

import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
plt.plot([1,2,3])
plt.savefig('myfig')

Personnellement, je préfère toujours utiliser plt.close( fig ), car vous avez la possibilité de masquer certains chiffres (pendant une boucle), mais d'afficher toujours des chiffres pour le traitement des données après la boucle. Il est probablement plus lent que de choisir un backend non interactif - serait intéressant si quelqu'un le testait.

MISE À JOUR : pour Spyder, vous ne pouvez généralement pas définir le backend de cette manière (parce que Spyder charge généralement matplotlib tôt, vous empêchant d'utiliser matplotlib.use()).

À la place, utilisez plt.switch_backend('Agg')ou désactivez « activer le support » dans les préférences de Spyder et exécutez la matplotlib.use('Agg')commande vous-même.

De ces deux indices: un , deux


1
Cela fonctionne très bien pour les situations où vous n'avez pas d'affichage défini. L'utilisation d'un autre backend avec .plot()générera une erreur s'il os.environ['DISPLAY']n'est pas défini correctement.
économie

1
Merci. cela fonctionne et est très utile pour les serveurs de production où il n'y a pas de connexion Internet et qui ont besoin d'un administrateur système pour installer les packages.
Leon

J'aime le tutoriel du site matplotlib pour la description / définition des "backends": matplotlib.org/tutorials/introductory/…
Tanner Strunk

47

Si vous n'aimez pas le concept de la figure "actuelle", faites:

import matplotlib.image as mpimg

img = mpimg.imread("src.png")
mpimg.imsave("out.png", img)

2
N'est-ce pas juste copier src.png à out.png?
gerrit

C'est juste un exemple, qui montre que si vous avez un objet image ( img), vous pouvez l'enregistrer dans un fichier avec la .imsave()méthode.
wonder.mice

4
@ wonder.mice aiderait à montrer comment créer une image sans utiliser la figure actuelle.
scry

@ wonder.mice Merci pour cet exemple, c'est le premier qui m'a montré comment enregistrer un objet image en .png.
Arthur Dent

@scry Vous n'avez pas toujours besoin de créer une image, parfois vous essayez du code et souhaitez une sortie visuelle, c'est pratique dans de telles occasions.
Schütze

29

Les autres réponses sont correctes. Cependant, je trouve parfois que je veux ouvrir l' objet figure plus tard. Par exemple, je pourrais vouloir changer la taille des étiquettes, ajouter une grille ou effectuer un autre traitement. Dans un monde parfait, je relancerais simplement le code générant l'intrigue et j'adapterais les paramètres. Hélas, le monde n'est pas parfait. Par conséquent, en plus d'enregistrer au format PDF ou PNG, j'ajoute:

with open('some_file.pkl', "wb") as fp:
    pickle.dump(fig, fp, protocol=4)

Comme ça, je peux plus tard charger l'objet figure et manipuler les paramètres à ma guise.

J'écris également la pile avec le code source et le locals()dictionnaire pour chaque fonction / méthode de la pile, afin de pouvoir dire plus tard exactement ce qui a généré la figure.

NB: Attention, cette méthode génère parfois des fichiers volumineux.


ne serait-il pas plus facile de faire du développement dans un cahier jupyter, avec les chiffres en ligne? De cette façon, vous pouvez suivre exactement l'historique et même le réexécuter.
Ciprian Tomoiagă

3
@CiprianTomoiaga Je ne génère jamais de parcelles de production à partir d'un shell Python interactif (Jupyter ou autre). Je trace tout à partir de scripts.
gerrit

28
import datetime
import numpy as np
from matplotlib.backends.backend_pdf import PdfPages
import matplotlib.pyplot as plt

# Create the PdfPages object to which we will save the pages:
# The with statement makes sure that the PdfPages object is closed properly at
# the end of the block, even if an Exception occurs.
with PdfPages('multipage_pdf.pdf') as pdf:
    plt.figure(figsize=(3, 3))
    plt.plot(range(7), [3, 1, 4, 1, 5, 9, 2], 'r-o')
    plt.title('Page One')
    pdf.savefig()  # saves the current figure into a pdf page
    plt.close()

    plt.rc('text', usetex=True)
    plt.figure(figsize=(8, 6))
    x = np.arange(0, 5, 0.1)
    plt.plot(x, np.sin(x), 'b-')
    plt.title('Page Two')
    pdf.savefig()
    plt.close()

    plt.rc('text', usetex=False)
    fig = plt.figure(figsize=(4, 5))
    plt.plot(x, x*x, 'ko')
    plt.title('Page Three')
    pdf.savefig(fig)  # or you can pass a Figure object to pdf.savefig
    plt.close()

    # We can also set the file's metadata via the PdfPages object:
    d = pdf.infodict()
    d['Title'] = 'Multipage PDF Example'
    d['Author'] = u'Jouni K. Sepp\xe4nen'
    d['Subject'] = 'How to create a multipage pdf file and set its metadata'
    d['Keywords'] = 'PdfPages multipage keywords author title subject'
    d['CreationDate'] = datetime.datetime(2009, 11, 13)
    d['ModDate'] = datetime.datetime.today()

28

Après avoir utilisé plot () et d'autres fonctions pour créer le contenu que vous souhaitez, vous pouvez utiliser une clause comme celle-ci pour choisir entre le traçage à l'écran ou le fichier:

import matplotlib.pyplot as plt

fig = plt.figure(figsize=(4, 5))       # size in inches
# use plot(), etc. to create your plot.

# Pick one of the following lines to uncomment
# save_file = None
# save_file = os.path.join(your_directory, your_file_name)  

if save_file:
    plt.savefig(save_file)
    plt.close(fig)
else:
    plt.show()

Certains disent que cela fig = plt.figure(figuresize=4, 5)pourrait êtrefig = plt.figure(figsize=(4, 5)) #figure sizes in inches
utilisateur

24

J'ai utilisé ce qui suit:

import matplotlib.pyplot as plt

p1 = plt.plot(dates, temp, 'r-', label="Temperature (celsius)")  
p2 = plt.plot(dates, psal, 'b-', label="Salinity (psu)")  
plt.legend(loc='upper center', numpoints=1, bbox_to_anchor=(0.5, -0.05),        ncol=2, fancybox=True, shadow=True)

plt.savefig('data.png')  
plt.show()  
f.close()
plt.close()

J'ai trouvé très important d'utiliser plt.show après avoir enregistré la figure, sinon cela ne fonctionnera pas. figure exportée en png


2
désolé, qu'est-ce que c'est? fichier d'image tracé? f= plt.savefig('data.png')
Morse

14

Vous pouvez soit faire:

plt.show(hold=False)
plt.savefig('name.pdf')

et n'oubliez pas de laisser savefig se terminer avant de fermer le tracé de l'interface graphique. De cette façon, vous pouvez voir l'image à l'avance.

Alternativement, vous pouvez le regarder avec plt.show() Puis fermez l'interface graphique et réexécutez le script, mais cette fois remplacez plt.show()par plt.savefig().

Vous pouvez également utiliser

fig, ax = plt.figure(nrows=1, ncols=1)
plt.plot(...)
plt.show()
fig.savefig('out.pdf')

2
a obtenu un argument de mot clé inattendu 'hold'
amitdatta

13

Si, comme moi, vous utilisez Spyder IDE, vous devez désactiver le mode interactif avec:

plt.ioff()

(cette commande est lancée automatiquement avec le démarrage scientifique)

Si vous souhaitez le réactiver, utilisez:

plt.ion()


12

La solution :

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
matplotlib.style.use('ggplot')
ts = pd.Series(np.random.randn(1000), index=pd.date_range('1/1/2000', periods=1000))
ts = ts.cumsum()
plt.figure()
ts.plot()
plt.savefig("foo.png", bbox_inches='tight')

Si vous souhaitez afficher l'image ainsi que sauvegarder l'image, utilisez:

%matplotlib inline

après import matplotlib


9

Selon la question Matplotlib (pyplot) savefig affiche une image vierge .

Une chose doit noter: si vous utilisez plt.showet que cela devrait aprèsplt.savefig , ou vous donnerez une image vierge.

Un exemple détaillé:

import numpy as np
import matplotlib.pyplot as plt


def draw_result(lst_iter, lst_loss, lst_acc, title):
    plt.plot(lst_iter, lst_loss, '-b', label='loss')
    plt.plot(lst_iter, lst_acc, '-r', label='accuracy')

    plt.xlabel("n iteration")
    plt.legend(loc='upper left')
    plt.title(title)
    plt.savefig(title+".png")  # should before plt.show method

    plt.show()


def test_draw():
    lst_iter = range(100)
    lst_loss = [0.01 * i + 0.01 * i ** 2 for i in xrange(100)]
    # lst_loss = np.random.randn(1, 100).reshape((100, ))
    lst_acc = [0.01 * i - 0.01 * i ** 2 for i in xrange(100)]
    # lst_acc = np.random.randn(1, 100).reshape((100, ))
    draw_result(lst_iter, lst_loss, lst_acc, "sgd_method")


if __name__ == '__main__':
    test_draw()

entrez la description de l'image ici


6
import matplotlib.pyplot as plt
plt.savefig("image.png")

Dans Jupyter Notebook, vous devez supprimer plt.show()et ajouter plt.savefig(), avec le reste du code plt dans une cellule. L'image apparaîtra toujours dans votre carnet.


1
"remove plt.show ()" .. cela m'a sauvé la journée ...
Guru

4

Étant donné qu'aujourd'hui (n'était pas disponible lorsque cette question a été posée), de nombreuses personnes utilisent Jupyter Notebook comme console python, il existe un moyen extrêmement simple d'enregistrer les tracés car .png, il suffit d'appeler la classe matplotlib's à pylabpartir de Jupyter Notebook, de tracer la figure' en ligne 'jupyter cells, puis faites glisser cette figure / image vers un répertoire local. N'oubliez pas %matplotlib inlineen première ligne!


1
c'est une bonne idée, il suffit de prendre note de l'impact sur la taille du fichier si l'image est laissée intégrée dans le cahier ..
prusswan

3

En plus de ceux ci-dessus, j'ai ajouté __file__pour le nom afin que l'image et le fichier Python obtiennent les mêmes noms. J'ai également ajouté quelques arguments pour le rendre plus beau:

# Saves a PNG file of the current graph to the folder and updates it every time
# (nameOfimage, dpi=(sizeOfimage),Keeps_Labels_From_Disappearing)
plt.savefig(__file__+".png",dpi=(250), bbox_inches='tight')
# Hard coded name: './test.png'

2

Lors de l'utilisation matplotlib.pyplot, vous devez d'abord enregistrer votre tracé puis le fermer en utilisant ces 2 lignes:

fig.savefig('plot.png') # save the plot, place the path you want to save the figure in quotation
plt.close(fig) # close the figure window

1

Comme suggéré précédemment, vous pouvez utiliser:

import matplotlib.pyplot as plt
plt.savefig("myfig.png")

Pour enregistrer l'image IPhython que vous affichez. Ou sur une note différente (en regardant sous un angle différent), si jamais vous travaillez avec un cv ouvert, ou si vous avez importé un cv ouvert, vous pouvez opter pour:

importer cv2

cv2.imwrite ("myfig.png", image)

Mais c'est juste au cas où vous auriez besoin de travailler avec Open CV. Sinon, plt.savefig () devrait être suffisant.


0

Vous pouvez enregistrer votre image avec n'importe quelle extension (png, jpg, etc.) et avec la résolution que vous souhaitez. Voici une fonction pour enregistrer votre silhouette.

import os

def save_fig(fig_id, tight_layout=True, fig_extension="png", resolution=300):
    path = os.path.join(IMAGES_PATH, fig_id + "." + fig_extension)
    print("Saving figure", fig_id)
    if tight_layout:
        plt.tight_layout()
    plt.savefig(path, format=fig_extension, dpi=resolution)

'fig_id' est le nom sous lequel vous souhaitez enregistrer votre figure. J'espère que cela aide:)


0

Vous pouvez le faire comme ceci:

def plotAFig():
  plt.figure()
  plt.plot(x,y,'b-')
  plt.savefig("figurename.png")
  plt.close()
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.