Salva la trama nel file di immagine invece di visualizzarla utilizzando Matplotlib


1150

Sto scrivendo uno script veloce e sporco per generare trame al volo. Sto usando il codice seguente (dalla documentazione di Matplotlib ) come punto di partenza:

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

Non voglio visualizzare la trama su una GUI, invece, voglio salvare la trama in un file (diciamo foo.png), in modo che, ad esempio, possa essere utilizzata negli script batch. Come lo faccio?


85
Sembra che abbia trovato la risposta: its pylab.savefig ('foo.png')
Homunculus Reticulli

2
Il link dovrebbe forse essere linkato da qualche parte in matplotlib.org?
A.Wan

40
Inoltre, se non si utilizza pylab, anche l'oggetto figura ha un savefigmetodo. Quindi puoi chiamare fig = plt.figure()allora fig.savefig(...).
A.Wan

27
Molte delle risposte nella parte inferiore della pagina menzionano ciò plt.close(fig)che è particolarmente importante nei grandi loop. Altrimenti le figure restano aperte e attendono in memoria e tutte le figure aperte verranno mostrate al momento dell'esecuzioneplt.show()
timctran

nb: matplotlib.pyplot è preferito: stackoverflow.com/questions/11469336/...
ErichBSchulz

Risposte:


1441

Mentre alla domanda è stata data una risposta, vorrei aggiungere alcuni suggerimenti utili quando si utilizza matplotlib.pyplot.savefig . Il formato del file può essere specificato dall'estensione:

from matplotlib import pyplot as plt

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

Fornirà rispettivamente un output rasterizzato o vettorizzato, entrambi utili. Inoltre, troverai che pylablascia uno spazio generoso, spesso indesiderabile, intorno all'immagine. Rimuovilo con:

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

9
È possibile cambiare le dimensioni dell'immagine risultante?
Llamageddon,

43
@Asmageddon In plt.savefigpuoi modificare il dpi, vedi il link nella risposta. Le dimensioni possono essere controllate durante la creazione della figura, vedere figsizein matplotlib.org/api/figure_api.html#matplotlib.figure.Figure
Hooked

5
@MoTSCHIGGE è possibile chiamare per plt.ioff()disabilitare l'interattività nei matplotlib.pyplotcomandi.
rubenvb,

5
@STMohammed foo.png è il percorso. Ad esempio, potresti inserirlo in una directory come questa savefig("mydir/foo.png").
Agganciato il

3
bbox_inches = 'tight' funziona come un incantesimo. Mi hai reso
felice

205

Come altri hanno già detto, plt.savefig()o fig1.savefig()è davvero il modo di salvare un'immagine.

Tuttavia ho scoperto che in alcuni casi la figura è sempre mostrata . (es. con Spyder con plt.ion(): modalità interattiva = Attivo.) Mi aggiro forzando la chiusura della finestra della figura nel mio loop gigante con plt.close(figure_object)(vedi documentazione ), quindi non ho un milione di figure aperte durante il loop:

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

Dovresti essere in grado di riaprire la figura in seguito, se necessario, con fig.show()(non ho testato me stesso).


9
È inoltre possibile impostare plt.ioff() # turn of interactive plotting mode, ma ciò potrebbe disabilitare il comportamento che si desidera utilizzare se il codice esce con un errore.
Demis,

2
Vedrai lo stesso problema nei notebook Jupyter. plt.close(fig)risolto
intsco il


89

Ho appena trovato questo link nella documentazione di MatPlotLib che risolve esattamente questo problema: http://matplotlib.org/faq/howto_faq.html#generate-images-without-having-a-window-appear

Dicono che il modo più semplice per impedire alla figura di spuntare sia usare un backend non interattivo (es. Agg), tramite matplotib.use(<backend>), ad es .:

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

Personalmente preferisco ancora usare plt.close( fig ), da allora hai la possibilità di nascondere determinate figure (durante un ciclo), ma visualizzare comunque le figure per l'elaborazione dei dati post-ciclo. Probabilmente è più lento della scelta di un backend non interattivo - sarebbe interessante se qualcuno lo provasse.

AGGIORNAMENTO : per Spyder, di solito non è possibile impostare il backend in questo modo (poiché Spyder di solito carica matplotlib in anticipo, impedendoti di utilizzarlo matplotlib.use()).

Invece, usa plt.switch_backend('Agg')o Disattiva " abilita supporto " nelle preferenze di Spyder ed esegui matplotlib.use('Agg')tu stesso il comando.

Da questi due suggerimenti: uno , due


1
Funziona davvero bene in situazioni in cui non hai un display impostato. L'uso di un altro backend con .plot()genererà un errore se os.environ['DISPLAY']non impostato correttamente.
economia

1
Grazie. funziona e risulta molto utile per i server di produzione in cui non esiste una connessione Internet e per installare eventuali pacchetti è necessario l'amministratore di sistema.
Leon,

Mi piace il tutorial del sito matplotlib per la descrizione / definizione di "backend": matplotlib.org/tutorials/introductory/…
Tanner Strunk,

47

Se non ti piace il concetto della figura "attuale", fai:

import matplotlib.image as mpimg

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

2
Questo non basta copiare src.pnga out.png?
Gerrit,

Questo è solo un esempio, che mostra se hai un oggetto immagine ( img), quindi puoi salvarlo in un file con il .imsave()metodo.
wonder.mice,

4
@ wonder.mice aiuterebbe a mostrare come creare un'immagine senza usare la figura corrente.
scriva il

@ wonder.mice Grazie per questo esempio, è il primo che mi ha mostrato come salvare un oggetto immagine in .png.
Arthur Dent,

@scry Non è sempre necessario creare un'immagine, a volte si prova un po 'di codice e si desidera un output visivo, è utile in tali occasioni.
Schütze,

29

Le altre risposte sono corrette. Tuttavia, a volte trovo che voglio aprire l' oggetto figura in un secondo momento. Ad esempio, potrei voler modificare le dimensioni dell'etichetta, aggiungere una griglia o eseguire altre elaborazioni. In un mondo perfetto, vorrei semplicemente rieseguire il codice che genera la trama e adattare le impostazioni. Purtroppo il mondo non è perfetto. Pertanto, oltre al salvataggio in PDF o PNG, aggiungo:

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

In questo modo, in seguito posso caricare l'oggetto figura e manipolare le impostazioni come preferisco.

Scrivo anche lo stack con il codice sorgente e il locals()dizionario per ogni funzione / metodo nello stack, in modo da poter dire in seguito esattamente cosa ha generato la figura.

NB: fai attenzione, poiché a volte questo metodo genera file di grandi dimensioni.


non sarebbe più facile fare lo sviluppo in un notebook jupyter, con le figure in linea? In questo modo puoi monitorare esattamente la cronologia e persino rieseguirla.
Ciprian Tomoiagă,

3
@CiprianTomoiaga Non ho mai generato grafici di produzione da una shell Python interattiva (Jupyter o altro). Traccio tutto dagli script.
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

Dopo aver utilizzato la trama () e altre funzioni per creare il contenuto desiderato, è possibile utilizzare una clausola come questa per selezionare tra la stampa sullo schermo o il file:

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

Alcuni dicono che fig = plt.figure(figuresize=4, 5)potrebbe esserefig = plt.figure(figsize=(4, 5)) #figure sizes in inches
utente

24

Ho usato il seguente:

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

Ho trovato molto importante usare plt.show dopo aver salvato la figura, altrimenti non funzionerà. figura esportata in png


2
scusa, cosa c'è in questo? file di immagine tracciato? f= plt.savefig('data.png')
Morse

14

Puoi fare:

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

e ricorda di lasciare che savefig finisca prima di chiudere il grafico della GUI. In questo modo puoi vedere l'immagine in anticipo.

In alternativa, puoi guardarlo con plt.show() Quindi chiudere la GUI ed eseguire nuovamente lo script, ma questa volta sostituirlo plt.show()con plt.savefig().

In alternativa, puoi usare

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

2
ho ricevuto un argomento inaspettato per la parola chiave "hold"
amitdatta il

13

Se, come me, usi Spyder IDE, devi disabilitare la modalità interattiva con:

plt.ioff()

(questo comando viene avviato automaticamente con l'avvio scientifico)

Se si desidera abilitarlo di nuovo, utilizzare:

plt.ion()


12

La soluzione :

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

Se si desidera visualizzare l'immagine e salvarla, utilizzare:

%matplotlib inline

dopo import matplotlib


9

Secondo la domanda Matplotlib (pyplot) savefig genera un'immagine vuota .

Una cosa dovrebbe notare: se si utilizza plt.showe dovrebbe dopoplt.savefig , o darai un'immagine vuota.

Un esempio dettagliato:

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

inserisci qui la descrizione dell'immagine


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

In Jupyter Notebook devi rimuovere plt.show()e aggiungere plt.savefig(), insieme al resto del codice plt in una cella. L'immagine verrà comunque visualizzata sul tuo blocco note.


1
"remove plt.show ()" .. questo mi ha salvato la giornata ...
Guru

4

Dato che oggi (non era disponibile quando la questione è stata fatta) un sacco di persone usano Jupyter Notebook come console di pitone, c'è un modo estremamente semplice per salvare le trame come .png, basta chiamare il matplotlib's pylabclasse da Jupyter notebook, tracciare la figura' inline 'jupyter, quindi trascina quella figura / immagine in una directory locale. Non dimenticare %matplotlib inlinein prima linea!


1
è una buona idea, basta prendere nota dell'impatto sulla dimensione del file se l'immagine viene lasciata incorporata nel notebook ..
prusswan

3

Oltre a quelli sopra, ho aggiunto __file__il nome in modo che l'immagine e il file Python ottengano gli stessi nomi. Ho anche aggiunto alcuni argomenti per renderlo migliore:

# 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

Quando si utilizza matplotlib.pyplot, è necessario prima salvare la trama e quindi chiuderla utilizzando queste 2 righe:

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

Come suggerito prima, puoi utilizzare:

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

Per salvare qualsiasi immagine IPhython che stai visualizzando. O su una nota diversa (guardando da una prospettiva diversa), se mai dovessi lavorare con open cv o se hai importato open cv, puoi scegliere:

import cv2

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

Ma questo è nel caso in cui devi lavorare con Open CV. Altrimenti plt.savefig () dovrebbe essere sufficiente.


0

Puoi salvare la tua immagine con qualsiasi estensione (png, jpg, ecc.) E con la risoluzione che desideri. Ecco una funzione per salvare la tua figura.

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' è il nome con cui vuoi salvare la tua figura. Spero che sia d'aiuto:)


0

Puoi farlo in questo modo:

def plotAFig():
  plt.figure()
  plt.plot(x,y,'b-')
  plt.savefig("figurename.png")
  plt.close()
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.