Збережіть сюжет у файл зображення, а не відображайте його за допомогою Matplotlib


1150

Я пишу швидкий і брудний сценарій, щоб генерувати сюжети на льоту. Я використовую наведений нижче код (з документації Matplotlib ) як вихідний пункт:

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

Я не хочу відображати графік на графічному інтерфейсі, натомість я хочу зберегти графік у файл (скажімо foo.png), щоб, наприклад, його можна було використовувати в пакетних скриптах. Як це зробити?


84
Схоже, я знайшов відповідь: її pylab.savefig ('foo.png')
Homunculus Reticulli

2
Посилання має бути, можливо, посилання на десь на matplotlib.org?
A.Wan

40
Також якщо не використовується pylab, об'єкт фігури також має savefigметод. Тож можна зателефонувати fig = plt.figure()тоді fig.savefig(...).
A.Wan

27
Багато відповідей нижче на сторінці згадують, plt.close(fig)що особливо важливо для великих циклів. Інакше фігури залишаються відкритими і чекають у пам’яті, а всі відкриті фігури будуть показані після виконанняplt.show()
timctran

NB: matplotlib.pyplot є кращим: stackoverflow.com/questions/11469336 / ...
ErichBSchulz

Відповіді:


1438

Хоча на запитання відповіли, я хотів би додати кілька корисних порад під час використання matplotlib.pyplot.savefig . Формат файлу може бути визначений розширенням:

from matplotlib import pyplot as plt

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

Дасть відповідно растерізований або векторизований вихід, який може бути корисним. Крім того, ви побачите, що pylabзалишає щедрий, часто небажаний пробіл навколо зображення. Видаліть його за допомогою:

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

9
Чи можливо змінити розміри отриманого зображення?
Llamageddon

43
@Asmageddon Якщо plt.savefigви можете змінити dpi, дивіться посилання у відповіді. Розміри можна керувати, створюючи фігуру, дивіться figsizeна matplotlib.org/api/figure_api.html#matplotlib.figure.Figure
Зачеплений

5
@MoTSCHIGGE ви можете зателефонувати, plt.ioff()який повинен відключити інтерактивність у matplotlib.pyplotкомандах.
rubenvb

5
@STMohammed foo.png - шлях. Ви можете, наприклад, помістити його в такий каталог savefig("mydir/foo.png").
Зачепили

3
bbox_inches = 'тісний' працює як шарм. Ви зробили мій день
Catbuilts

205

Як казали інші, plt.savefig()чи fig1.savefig()це дійсно спосіб збереження зображення.

Однак я виявив, що в певних випадках фігура завжди відображається . (наприклад, зі Spyder, що має plt.ion(): інтерактивний режим = Увімкнено). Я працюю над цим, змушуючи закрити вікно фігури у своєму гігантському циклі plt.close(figure_object)(див. документацію ), тому у мене немає мільйона відкритих фігур під час циклу:

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

Ви повинні мати змогу знову відкрити фігуру пізніше, якщо потрібно fig.show()(не перевіряв себе).


9
Ви також можете встановити plt.ioff() # turn of interactive plotting mode, але це може відключити поведінку, яку ви хотіли б використати, якщо ваш код закриє помилку.
Деміс

2
Таку ж проблему ви побачите і в ноутбуках Юпітера. plt.close(fig)вирішив це
intsco


89

Щойно знайшли це посилання в документації MatPlotLib, що стосується саме цієї проблеми: http://matplotlib.org/faq/howto_faq.html#generate-images-without-having-a-window-appear

Вони кажуть, що найпростіший спосіб запобігти появі фігури - це використання неінтерактивного бекенда (наприклад, Agg) через matplotib.use(<backend>), наприклад:

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

Я все одно особисто віддаю перевагу використанню plt.close( fig ), оскільки тоді у вас є можливість приховати певні фігури (під час циклу), але все одно відображати фігури для обробки даних після циклу. Це, мабуть, повільніше, ніж вибирати неінтерактивний бекенд - було б цікаво, якби хтось це перевірив.

ОНОВЛЕННЯ : для Spyder ви зазвичай не можете встановити бекенд таким чином (оскільки Spyder зазвичай завантажує matplotlib рано, не даючи вам використовувати matplotlib.use()).

Натомість використовуйте plt.switch_backend('Agg')або вимкніть " увімкнути підтримку " у префіксах Spyder і запустіть matplotlib.use('Agg')команду самостійно.

З цих двох натяків: один , два


1
Це дуже добре працює в ситуаціях, коли у вас немає дисплея набору. Використання іншого сервера з .plot()викличе помилку, якщо os.environ['DISPLAY']вона встановлена ​​неправильно.
економіка

1
Дякую. це працює і дуже корисно для виробничих серверів, де немає підключення до Інтернету та потрібен системний адміністратор для встановлення будь-яких пакетів.
Леон

Мені подобається підручник, який має сайт matplotlib для опису / визначення "backends": matplotlib.org/tutorials/introductory/…
Tanner Strunk

47

Якщо вам не подобається концепція "поточної" фігури, зробіть:

import matplotlib.image as mpimg

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

2
Хіба це не просто скопіювати src.pngв out.png?
Герріт

Це лише приклад, який показує, якщо у вас є об'єкт зображення ( img), то ви можете зберегти його у файл .imsave()методом.
wonder.mice

4
@ wonder.mice допоможе показати, як створити зображення без використання поточної фігури.
перегляньте

@ wonder.mice Спасибі за цей приклад, це перший, який показав мені, як зберегти об’єкт зображення до .png.
Артур Дент

@scry Не завжди потрібно створювати зображення, іноді випробовуєте якийсь код і хочете візуального виводу, це зручно в таких випадках.
Schütze

29

Інші відповіді правильні. Однак я іноді виявляю, що хочу відкрити фігурний об’єкт пізніше. Наприклад, я можу захотіти змінити розміри міток, додати сітку або зробити іншу обробку. У ідеальному світі я б просто перезапустив код, що генерує сюжет, і адаптував налаштування. На жаль, світ не ідеальний. Тому, крім збереження у форматі PDF або PNG, я додаю:

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

Так, я можу пізніше завантажити об'єкт фігури і маніпулювати налаштуваннями, як мені заманеться.

Я також виписую стек із вихідним кодом та locals()словником для кожної функції / методу в стеку, щоб згодом я міг точно сказати, що генерувало фігуру.

NB: Будьте обережні, оскільки іноді цей метод створює величезні файли.


чи не було б простіше зайнятися розробкою в зошиті з юпітером, з фігурами накресленими? Таким чином ви зможете точно відстежувати історію та навіть повторювати її.
Ciprian Tomoiagă

3
@CiprianTomoiaga Я ніколи не генерую виробничі сюжети з інтерактивної оболонки Python (Юпітер чи інше). Я будую все зі сценаріїв.
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

Використовуючи plot () та інші функції для створення потрібного вмісту, ви можете скористатись таким пунктом, щоб вибрати між графіком на екрані або подати файл:

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

Деякі кажуть, що це fig = plt.figure(figuresize=4, 5)може бутиfig = plt.figure(figsize=(4, 5)) #figure sizes in inches
користувач

24

Я використовував таке:

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

Мені було дуже важливо використовувати plt.show після збереження фігури, інакше це не працюватиме. цифра експортується в png


2
вибачте, що в цьому? графічний файл зображення? f= plt.savefig('data.png')
Морзе

14

Ви можете:

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

і не забудьте дозволити savefig закінчити перед тим, як закрити графічний графік. Таким чином ви можете побачити зображення заздалегідь.

Крім того, ви можете подивитися на це. plt.show() Потім закрийте GUI і запустіть сценарій ще раз, але цього разу замініть plt.show()на plt.savefig().

Як варіант, ви можете використовувати

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

2
отримав несподіваний аргумент ключового слова "утримувати"
amitdatta

13

Якщо ви, як і я, використовуєте ID Spyder, вам доведеться відключити інтерактивний режим за допомогою:

plt.ioff()

(Ця команда автоматично запускається при науковому запуску)

Якщо ви хочете ввімкнути його знову, використовуйте:

plt.ion()


12

Рішення :

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

Якщо ви хочете відобразити зображення, а також зберегти використання зображення:

%matplotlib inline

після import matplotlib


9

Відповідно до питання Matplotlib (pyplot) savefig видає порожнє зображення .

Слід зазначити одне: якщо ви користуєтесь цим plt.showі після цього plt.savefig, або ви дасте порожнє зображення.

Детальний приклад:

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

введіть тут опис зображення


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

У Блокноті Юпітера потрібно видалити plt.show()та додати plt.savefig()разом із рештою коду plt в одній комірці. Зображення все одно відображатиметься у вашому ноутбуці.


1
"видалити plt.show ()" .. це врятувало мені день ...
Гуру

4

З огляду на , що сьогодні (не був доступний , коли було зроблено це питання) багато людей використовують Jupyter ноутбук , як пітон консолі, є дуже простий спосіб , щоб зберегти ділянки , як .png, просто викличте matplotlib«s pylabклас від Jupyter Notebook, побудувати фігуру» інлайн 'клітини jupyter, а потім перетягніть цю фігуру / зображення в локальний каталог. Не забувайте %matplotlib inlineв першому рядку!


1
це гарна ідея, просто потрібно взяти до уваги вплив на розмір файлів, якщо зображення залишити вбудованим у ноутбук ..
prusswan

3

На додаток до вищезазначених, я додав __file__ім'я, щоб зображення та файл Python отримали однакові імена. Я також додав кілька аргументів, щоб зробити це краще:

# 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

Під час використання matplotlib.pyplotпотрібно спочатку зберегти свою ділянку, а потім закрити її за допомогою цих двох рядків:

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

Як було запропоновано раніше, ви можете використовувати:

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

Для збереження будь-якого зображення IPhython, що відображається. Або за іншою заміткою (дивлячись під іншим кутом), якщо ви коли-небудь працюєте з відкритим ревізором, або якщо у вас є імпортований відкритий реєстр, ви можете піти на:

імпорт cv2

cv2.imwrite ("myfig.png", зображення)

Але це про всяк випадок, якщо вам потрібно працювати з відкритим резюме. В іншому випадку plt.savefig () має бути достатнім.


0

Ви можете зберегти зображення з будь-яким розширенням (png, jpg тощо) та з потрібною роздільною здатністю. Ось функція збереження фігури.

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' - це ім'я, за допомогою якого ви хочете зберегти свою фігуру. Сподіваюся, це допомагає :)


0

Ви можете зробити це так:

def plotAFig():
  plt.figure()
  plt.plot(x,y,'b-')
  plt.savefig("figurename.png")
  plt.close()
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.