Сохранить график в файл изображения вместо того, чтобы отображать его с помощью Matplotlib


1152

Я пишу быстрый и грязный скрипт для создания графиков на лету. Я использую код ниже (из документации 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), чтобы, например, его можно было использовать в пакетных сценариях. Как я могу это сделать?


85
Похоже, я нашел ответ: его pylab.savefig ('foo.png')
Homunculus Reticulli

2
Ссылка может быть ссылка на где-нибудь в matplotlib.org?
А.Ван

40
Также, если не используется pylab, у объекта figure тоже есть savefigметод. Так что вы можете позвонить fig = plt.figure()тогда fig.savefig(...).
А.Ван

27
Многие ответы внизу страницы упоминаются, plt.close(fig)что особенно важно в больших циклах. В противном случае фигуры остаются открытыми и ожидающими в памяти, и все открытые фигуры будут показаны после выполненияplt.show()
Тимктран

Примечание: matplotlib.pyplot является предпочтительным: stackoverflow.com/questions/11469336/…
ErichBSchulz

Ответы:


1441

Хотя на вопрос дан ответ, я хотел бы добавить несколько полезных советов при использовании 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
Можно ли изменить размеры получаемого изображения?
Лламагеддон

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(): interactive mode = On.) Я работаю над этим, заставляя закрывать окно рисунка в моем гигантском цикле с помощью 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
Вы увидите ту же проблему в ноутбуках Jupyter. 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

48

Если вам не нравится понятие «текущая» фигура, сделайте:

import matplotlib.image as mpimg

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

2
Разве это не просто копировать src.pngв out.png?
геррит

Это всего лишь пример, который показывает, что если у вас есть объект image ( img), вы можете сохранить его в файле с .imsave()методом.
wonder.mice

4
@ wonder.mice поможет показать, как создать изображение, не используя текущий рисунок.
scry

@ wonder.mice Спасибо за этот пример, это первый, который показал мне, как сохранить объект изображения в .png.
Артур Дент

@scry Вам не всегда нужно создавать изображения, иногда вы пробуете некоторый код и хотите визуальный вывод, это удобно в таких случаях.
Шютце

29

Другие ответы верны. Однако иногда я обнаруживаю, что хочу открыть объект рисунка позже. Например, я мог бы хотеть изменить размеры этикетки, добавить сетку или сделать другую обработку. В идеальном мире я бы просто перезапустил код, генерирующий сюжет, и изменил настройки. Увы, мир не идеален. Поэтому, помимо сохранения в PDF или PNG, я добавляю:

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

Таким образом, позже я могу загрузить объект рисунка и манипулировать настройками по своему усмотрению.

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

NB: будьте осторожны, так как иногда этот метод генерирует огромные файлы.


Разве не было бы легче сделать разработку в блокноте Jupyter, со встроенными фигурами? Таким образом, вы можете точно отслеживать историю и даже запускать ее заново.
Ciprian Tomoiagă

3
@CiprianTomoiaga Я никогда не генерирую рабочие графики из интерактивной оболочки Python (Jupyter или иным образом). Я строю все из сценариев.
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 закончить перед закрытием графика GUI. Таким образом, вы можете увидеть изображение заранее.

В качестве альтернативы, вы можете посмотреть на это, plt.show() затем закройте GUI и снова запустите скрипт, но на этот раз замените plt.show()наplt.savefig() .

Кроме того, вы можете использовать

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

2
получил неожиданный аргумент ключевого слова 'hold'
amitdatta

13

Если, как и я, вы используете Spyder IDE, вам необходимо отключить интерактивный режим с помощью:

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

В Jupyter Notebook вы должны удалить plt.show()и добавить plt.savefig()вместе с остальной частью plt-код в одну ячейку. Изображение все равно будет отображаться в вашем блокноте.


1
"удалить plt.show ()" .. это спасло мой день ...
Гуру

4

Учитывая, что сегодня (не было доступно, когда этот вопрос был задан) многие люди используют Jupyter Notebook в качестве консоли Python, существует чрезвычайно простой способ сохранить графики как .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вы должны сначала сохранить свой график, а затем закрыть его, используя следующие 2 строки:

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, которое вы отображаете. Или на другой ноте (если смотреть под другим углом), если вам когда-нибудь придется работать с open cv или если вы импортировали open cv, вы можете перейти к:

импорт cv2

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

Но это на всякий случай, если вам нужно работать с Open CV. В противном случае 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.