Simpan plot ke file gambar alih-alih menampilkannya menggunakan Matplotlib

1150

Saya menulis skrip cepat dan kotor untuk membuat plot dengan cepat. Saya menggunakan kode di bawah ini (dari dokumentasi Matplotlib ) sebagai titik awal:

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

Saya tidak ingin menampilkan plot pada GUI, sebagai gantinya, saya ingin menyimpan plot ke file (katakanlah foo.png), sehingga, misalnya, dapat digunakan dalam skrip batch. Bagaimana aku melakukan itu?

Homunculus Reticulli
sumber
85
Sepertinya saya menemukan jawabannya: pylab.savefig ('foo.png')
Homunculus Reticulli
2
Tautan harus terhubung ke suatu tempat di matplotlib.org?
A.Dapat
40
Juga jika tidak menggunakan pylab, objek gambar memiliki savefigmetode juga. Jadi, Anda bisa menelepon fig = plt.figure()kemudian fig.savefig(...).
A.Dapat
27
Banyak jawaban di bawah yang menyebutkan halaman plt.close(fig)yang sangat penting dalam loop besar. Kalau tidak, angka-angka tetap terbuka dan menunggu dalam memori dan semua angka terbuka akan ditampilkan setelah mengeksekusiplt.show()
timctran
nb: matplotlib.pyplot lebih disukai: stackoverflow.com/questions/11469336/…
ErichBSchulz

Jawaban:

1441

Sementara pertanyaan telah dijawab, saya ingin menambahkan beberapa kiat bermanfaat saat menggunakan matplotlib.pyplot.savefig . Format file dapat ditentukan oleh ekstensi:

from matplotlib import pyplot as plt

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

Akan memberikan output rasterized atau vectorized masing-masing, keduanya dapat bermanfaat. Selain itu, Anda akan menemukan bahwa pylabmeninggalkan ruang putih yang murah hati, sering tidak diinginkan, di sekitar gambar. Hapus dengan:

savefig('foo.png', bbox_inches='tight')
Doyan
sumber
9
Apakah mungkin untuk mengubah dimensi gambar yang dihasilkan?
Llamageddon
43
@ Asmageddon Di plt.savefigAnda dapat mengubah dpi, lihat tautan di jawabannya. Dimensi dapat dikontrol saat membuat gambar, lihat figsizedi matplotlib.org/api/figure_api.html#matplotlib.figure.Figure
Hooked
5
@ MoTSCHIGGE Anda dapat menelepon plt.ioff()yang harus menonaktifkan interaktivitas dalam matplotlib.pyplotperintah.
rubenvb
5
@ STMohammed foo.png adalah jalannya. Anda dapat, misalnya, meletakkannya di direktori seperti ini savefig("mydir/foo.png").
Hooked
3
bbox_inches = 'tight' bekerja seperti jimat. Anda membuat hari saya
Catbuilts
205

Seperti yang dikatakan orang lain, plt.savefig()atau fig1.savefig()memang cara untuk menyimpan gambar.

Namun saya telah menemukan bahwa dalam kasus-kasus tertentu angka tersebut selalu ditampilkan . (mis. dengan Spyder memiliki plt.ion(): mode interaktif = Aktif.) Saya mengatasinya dengan memaksa penutupan jendela gambar di loop raksasa saya dengan plt.close(figure_object)(lihat dokumentasi ), jadi saya tidak memiliki satu juta angka terbuka selama 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

Anda harus dapat membuka kembali gambar nanti jika perlu dengan fig.show()(tidak menguji diri saya sendiri).

Demis
sumber
9
Anda juga dapat mengatur plt.ioff() # turn of interactive plotting mode, tetapi itu mungkin menonaktifkan perilaku yang ingin Anda gunakan seandainya kode Anda keluar dengan kesalahan.
Demis
2
Anda akan melihat masalah yang sama di notebook Jupyter. plt.close(fig)dipecahkan
intsco
163

Solusinya adalah:

pylab.savefig('foo.png')
Lukasz Czerwinski
sumber
89

Baru saja menemukan tautan ini pada dokumentasi MatPlotLib yang membahas masalah ini dengan tepat: http://matplotlib.org/faq/howto_faq.html#generate-images-without-having-a-window-appear

Mereka mengatakan bahwa cara termudah untuk mencegah angka muncul adalah dengan menggunakan backend non-interaktif (mis. Agg), melalui matplotib.use(<backend>), misalnya:

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

Secara pribadi saya masih lebih suka menggunakan plt.close( fig ), sejak itu Anda memiliki opsi untuk menyembunyikan angka-angka tertentu (selama satu lingkaran), tetapi masih menampilkan angka untuk pemrosesan data pasca-loop. Ini mungkin lebih lambat daripada memilih backend non-interaktif sekalipun - akan menarik jika seseorang mengujinya.

UPDATE : untuk Spyder, Anda biasanya tidak dapat mengatur backend dengan cara ini (Karena Spyder biasanya memuat matplotlib lebih awal, mencegah Anda menggunakan matplotlib.use()).

Alih-alih, gunakan plt.switch_backend('Agg'), atau Nonaktifkan " aktifkan dukungan " di Prefers Spyder dan jalankan matplotlib.use('Agg')perintah itu sendiri.

Dari dua petunjuk ini: satu , dua

Demis
sumber
1
Ini bekerja sangat baik untuk situasi di mana Anda tidak memiliki tampilan yang ditetapkan. Menggunakan backend dengan yang lain .plot()akan menimbulkan kesalahan jika os.environ['DISPLAY']tidak disetel dengan benar.
ekonomi
1
Terima kasih. ini berfungsi dan sangat membantu untuk server produksi di mana tidak ada koneksi internet dan memerlukan admin sistem untuk menginstal paket apa pun.
Leon
Saya suka tutorial yang dimiliki situs matplotlib untuk deskripsi / definisi "backends": matplotlib.org/tutorials/introductory/…
Tanner Strunk
47

Jika Anda tidak menyukai konsep gambar "saat ini", lakukan:

import matplotlib.image as mpimg

img = mpimg.imread("src.png")
mpimg.imsave("out.png", img)
wonder.mice
sumber
2
Apakah ini tidak hanya menyalin src.pngke out.png?
gerrit
Itu hanya sebuah contoh, yang menunjukkan jika Anda memiliki objek gambar ( img), maka Anda dapat menyimpannya ke dalam file dengan .imsave()metode.
wonder.mice
4
@ wonder.mice akan membantu menunjukkan cara membuat gambar tanpa menggunakan gambar saat ini.
scry
@ wonder.mice Terima kasih untuk contoh ini, ini adalah yang pertama yang menunjukkan kepada saya bagaimana cara menyimpan objek gambar ke .png.
Arthur Dent
@scry Anda tidak selalu harus membuat gambar, kadang-kadang Anda mencoba beberapa kode dan ingin output visual, itu berguna dalam situasi seperti itu.
Schütze
29

Jawaban lainnya benar. Namun, saya terkadang menemukan bahwa saya ingin membuka objek gambar nanti. Misalnya, saya mungkin ingin mengubah ukuran label, menambahkan kisi, atau melakukan pemrosesan lainnya. Di dunia yang sempurna, saya hanya akan menjalankan kembali kode yang menghasilkan plot, dan menyesuaikan pengaturan. Sayangnya, dunia ini tidak sempurna. Karena itu, selain menyimpan ke PDF atau PNG, saya menambahkan:

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

Seperti ini, nanti saya bisa memuat objek gambar dan memanipulasi pengaturan sesuka saya.

Saya juga menulis tumpukan dengan kode-sumber dan locals()kamus untuk setiap fungsi / metode dalam tumpukan, sehingga nantinya saya bisa tahu persis apa yang dihasilkan gambar tersebut.

NB: Hati-hati, karena terkadang metode ini menghasilkan file besar.

gerrit
sumber
bukankah akan lebih mudah untuk melakukan pengembangan di notebook jupyter, dengan angka-angka yang sesuai? Dengan cara ini Anda dapat melacak dengan tepat sejarah, dan bahkan memutarnya kembali.
Ciprian Tomoiagă
3
@CiprianTomoiaga Saya tidak pernah membuat plot produksi dari shell Python interaktif (Jupyter atau lainnya). Saya plot semua dari skrip.
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()
Victor Juliet
sumber
28

Setelah menggunakan plot () dan fungsi lain untuk membuat konten yang Anda inginkan, Anda bisa menggunakan klausa seperti ini untuk memilih antara memplot ke layar atau ke 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()
Tandai p.
sumber
Ada yang bilang fig = plt.figure(figuresize=4, 5)bisafig = plt.figure(figsize=(4, 5)) #figure sizes in inches
pengguna
24

Saya menggunakan yang berikut ini:

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

Saya menemukan sangat penting untuk menggunakan plt.show setelah menyimpan gambar, jika tidak maka tidak akan berfungsi. angka yang diekspor dalam png

Cristian Muñoz
sumber
2
maaf, ada apa dalam hal ini? file gambar diplot? f= plt.savefig('data.png')
Morse
14

Anda dapat melakukan:

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

dan ingat untuk membiarkan savefig menyelesaikan sebelum menutup plot GUI. Dengan cara ini Anda dapat melihat gambar sebelumnya.

Atau, Anda dapat melihatnya dengan plt.show() Kemudian tutup GUI dan jalankan kembali skrip, tetapi kali ini ganti plt.show()dengan plt.savefig().

Atau, Anda dapat menggunakan

fig, ax = plt.figure(nrows=1, ncols=1)
plt.plot(...)
plt.show()
fig.savefig('out.pdf')
Alat pemecah buah keras
sumber
2
mendapat argumen kata kunci tak terduga 'tahan'
amitdatta
13

Jika, seperti saya, Anda menggunakan Spyder IDE, Anda harus menonaktifkan mode interaktif dengan:

plt.ioff()

(perintah ini diluncurkan secara otomatis dengan startup ilmiah)

Jika Anda ingin mengaktifkannya lagi, gunakan:

plt.ion()

Covich
sumber
12

Solusinya :

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

Jika Anda ingin menampilkan gambar serta menyimpan penggunaan gambar:

%matplotlib inline

setelah import matplotlib

Durgesh satam
sumber
9

Menurut pertanyaan Matplotlib (pyplot) savefig menampilkan gambar kosong .

Satu hal yang harus diperhatikan: jika Anda menggunakan plt.showdan setelah itu plt.savefig, atau Anda akan memberikan gambar kosong.

Contoh terperinci:

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

masukkan deskripsi gambar di sini

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

Di Jupyter Notebook Anda harus menghapus plt.show()dan menambahkan plt.savefig(), bersama dengan sisa kode plt dalam satu sel. Gambar masih akan muncul di buku catatan Anda.

Punnerud
sumber
1
"hapus plt.show ()" .. ini menyelamatkan hari saya ...
Guru
4

Mengingat hari ini (tidak tersedia ketika pertanyaan ini dibuat) banyak orang menggunakan Notebook Jupyter sebagai konsol python, ada cara yang sangat mudah untuk menyimpan plot .png, seperti panggil kelas matplotlib' pylabdari Jupyter Notebook, plot gambar' inline sel jupyter, lalu seret gambar / gambar itu ke direktori lokal. Jangan lupa %matplotlib inlinedi baris pertama!

Hamidreza
sumber
1
itu ide yang bagus, hanya perlu mencatat dampak pada filesize jika gambar dibiarkan tertanam di notebook ..
prusswan
3

Selain yang di atas, saya menambahkan __file__nama sehingga gambar dan file Python mendapatkan nama yang sama. Saya juga menambahkan beberapa argumen untuk membuatnya terlihat lebih baik:

# 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'
kembali
sumber
2

Saat menggunakan matplotlib.pyplot, Anda harus terlebih dahulu menyimpan plot Anda dan kemudian menutupnya menggunakan 2 baris ini:

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
Es Hening
sumber
1

Seperti yang disarankan sebelumnya, Anda dapat menggunakan:

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

Untuk menyimpan gambar IPhython apa pun yang Anda tampilkan. Atau pada catatan yang berbeda (melihat dari sudut yang berbeda), jika Anda pernah dapat bekerja dengan cv terbuka, atau jika Anda telah cv terbuka yang diimpor, Anda dapat menggunakan:

impor cv2

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

Tetapi ini hanya untuk berjaga-jaga jika Anda perlu bekerja dengan Open CV. Kalau tidak, plt.savefig () harus cukup.

Aditya Bhattacharya
sumber
0

Anda dapat menyimpan gambar Anda dengan ekstensi apa pun (png, jpg, dll.) Dan dengan resolusi yang Anda inginkan. Inilah fungsi untuk menyimpan gambar Anda.

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' adalah nama tempat Anda ingin menyimpan gambar Anda. Semoga bermanfaat :)

Rudresh Dixit
sumber
0

Anda bisa melakukannya seperti ini:

def plotAFig():
  plt.figure()
  plt.plot(x,y,'b-')
  plt.savefig("figurename.png")
  plt.close()
Mark90
sumber