scipy: savefig без фреймов, осей, только содержимое


92

В numpy / scipy у меня есть изображение, хранящееся в массиве. Я могу отобразить его, я хочу сохранить его, используя savefig без границ, осей, меток, заголовков ... Просто чистое изображение, ничего больше.

Я хочу избегать таких пакетов, как PyPNGили scipy.misc.imsave, они иногда являются проблематичными (они не всегда устанавливаются хорошо, только базовые savefig()для меня

Ответы:


115

РЕДАКТИРОВАТЬ

Изменено aspect='normalна, aspect='auto'так как это было изменено в более поздних версиях matplotlib (спасибо @ Luke19).


Предполагая:

import matplotlib.pyplot as plt

Чтобы сделать фигуру без каркаса:

fig = plt.figure(frameon=False)
fig.set_size_inches(w,h)

Чтобы контент заполнял всю фигуру

ax = plt.Axes(fig, [0., 0., 1., 1.])
ax.set_axis_off()
fig.add_axes(ax)

Затем нарисуйте на нем свое изображение:

ax.imshow(your_image, aspect='auto')
fig.savefig(fname, dpi)

aspectПараметр изменяет размер пикселя , чтобы убедиться , что они заполняют размер фигуры , указанный в fig.set_size_inches(…). Чтобы понять, как играть с подобными вещами, прочтите документацию matplotlib , особенно по теме Axes, Axis и Artist.


4
нет, у меня все еще есть небольшая прозрачная рамка, и я хочу вообще без рамки , чистое изображение
Якуб М.

5
Если вручную установить wи hпараметры fig.set_size_inches(w,h)и dpiпараметр fig.savefig(fname, dpi)так , что в результате 24px на 24px, он должен работать нормально. Например, w = h = 1иdpi = 24
matehat

5
Мне пришлось объединить этот ответ и ответ Мостафы Пакпарвара ниже. Вам нужно не только отключить оси, но и установить для set_visible значение false, чтобы убедиться, что пустое пространство исчезло. (wtf?)
Брайс Гуинта

6
Просто попробовал это с помощью matplotlib v2.2.2, и он работал отлично (за исключением того, что imshowсинтаксис изменен на aspect='auto'вместо 'normal').
Luke19

2
Это правильный подход. ax = plt.Axes(fig, [0., 0., 1., 1.])это то, что заставляет его работать.
Великвован

73

Кажется, более легкое решение:

fig.savefig('out.png', bbox_inches='tight', pad_inches=0)

2
Это отлично сработало для меня. Кроме того, pad_inches можно легко изменить до желаемого размера. Благодарность!
Curious2learn

27
У меня до сих пор белые поля.
Фабио Перес,

3
Я смог обновить это для более новых версий / проблемы с оставшимися полями, просто добавив transparent = True fig.savefig('out.png', bbox_inches='tight',transparent=True, pad_inches=0)
mdoc-2011,

2
Все еще есть топоры, отметки и все остальное с этим :(
BjornW

3
Это вообще ничего не делает. Это даст вам фигуру со всеми осями и метками.
1313e 05

27

Вы можете найти bbox изображения внутри оси (используя get_window_extent) и использовать bbox_inchesпараметр для сохранения только этой части изображения:

import numpy as np
import matplotlib.pyplot as plt

data=np.arange(9).reshape((3,3))
fig=plt.figure()
ax=fig.add_subplot(1,1,1)
plt.axis('off')
plt.imshow(data)

extent = ax.get_window_extent().transformed(fig.dpi_scale_trans.inverted())
plt.savefig('/tmp/test.png', bbox_inches=extent)

Я научился этому трюку от Джо Кингтона здесь .


6
просто plt.axis('off')помогло. Другие ответы не очень помогают.
imsrgadich 02

3
Это сработало очень хорошо. Однако в моем случае все еще есть небольшая белая рамка. Есть идеи, как удалить эту границу?
user3731622

@ user3731622, попробуйте plt.savefig('/temp/test.png', bbox_inches='tight', transparent=True, pad_inches=0)вместоplt.savefig('/tmp/test.png', bbox_inches=extent)
Cloud Cho

17

В моем случае я пробовал несколько вариантов, и лучшим решением было следующее:

fig.subplots_adjust(bottom = 0)
fig.subplots_adjust(top = 1)
fig.subplots_adjust(right = 1)
fig.subplots_adjust(left = 0)

затем сохраните свою фигуру с помощью savefig


1
Из всех этих решений это единственное, которое сработало для меня.
Puff

8

Я предлагаю ответ heron13 с небольшим дополнением, заимствованным отсюда, чтобы удалить отступы, оставшиеся после установки bbox в жесткий режим, поэтому:

axes = fig.axes()
axes.get_xaxis().set_visible(False)
axes.get_yaxis().set_visible(False)
fig.savefig('out.png', bbox_inches='tight', pad_inches=0)

Я получаю сообщение об ошибке: get_xaxis () и get_yaxis () не существуют. Есть идеи, почему это произошло?
Джейкоб Малаховски

Создайте объект axes (), затем используйте ax.xaxis и ax.yaxis
перигон

Получил сообщение об ошибке, что объект "список" не имеет атрибута "get_xaxis"
Haozhe Xie


3

У меня была такая же проблема при визуализации с использованием librosa, когда я хотел извлечь содержимое графика без какой-либо другой информации. Таков мой подход. unutbu ответ также помогает мне заставить работать.

    figure = plt.figure(figsize=(500, 600), dpi=1)
    axis = plt.subplot(1, 1, 1)
    plt.axis('off')
    plt.tick_params(axis='both', left='off', top='off', right='off', bottom='off', labelleft='off', labeltop='off',
                    labelright='off', labelbottom='off')

     # your code goes here. e.g: I used librosa function to draw a image
    result = np.array(clip.feature_list['fft'].get_logamplitude()[0:2])
    librosa.display.specshow(result, sr=api.Clip.RATE, x_axis='time', y_axis='mel', cmap='RdBu_r')


    extent = axis.get_window_extent().transformed(figure.dpi_scale_trans.inverted())
    plt.savefig((clip.filename + str("_.jpg")), format='jpg', bbox_inches=extent, pad_inches=0)
    plt.close()

Это привело меня на правильный путь, но у меня были две проблемы: 1) мне пришлось установить dpi на число больше 1, чтобы избежать ошибки шрифта в моем блокноте jupyter; и 2) все еще была небольшая граница, поэтому мне нужно вручную изменить размер Bbox на extent.get_points()*np.array([[1.1],[.9]]).
Боб Бэксли,

спасибо за выполнение ответа, который может помочь кому-то другому.
GPrathap

3

Для всех, кто пытается сделать это в Jupyter

 plt.axis('off')

 spec = plt.imshow

 plt.savefig('spec',bbox_inches='tight',transparent=True, pad_inches=0)

2

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

Предположим, вам нужна сетка 2x2 подзаголовков из четырех изображений, хранящихся в images:

matplotlib.pyplot.figure(figsize = (16,12)) # or whatever image size you require
for i in range(4):
    ax = matplotlib.pyplot.subplot(2,2,i+1)
    ax.axis('off')
    imshow(images[i])
matplotlib.pyplot.savefig(path, bbox_inches='tight')

1

Я тоже пытался избавиться от границы, используя советы, но ничего не помогло. Немного возился, и я обнаружил, что изменение цвета лица не давало мне границ в jupyter labs (любой цвет приводил к избавлению от белой границы). Надеюсь это поможет.

def show_num(data):
data = np.rot90(data.reshape((16,16)), k=3)
data = np.fliplr(data)
fig = plt.figure(frameon=False, facecolor='white')
ax = plt.Axes(fig, [0., 0., 1., 1.])
ax.set_axis_off()
fig.add_axes(ax)
ax.imshow(data)
plt.show()

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



0

Для меня этот код сделал аналогичный размер входного изображения без рамки и осей из кодов matehat , unutbu и WHZW :

fig = plt.figure()
ax = fig.add_subplot(1,1,1)
plt.axis('off')
viridis = cm.get_cmap('gist_gray', 256)
plt.imshow(data, aspect='auto', cmap=viridis)
plt.tight_layout()
plt.savefig(out_file, bbox_inches='tight', transparent=True, pad_inches=0)

Среда выполнения:
Python 3.6.10
Matplotlib 3.2.1
ОС Windows 10

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.