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 , особливо на тему Сокири, Вісь та Художник.


4
ні, я все ще маю невеликий прозорий кордон, і те, що я хочу, це взагалі не кордон , чистий образ
Якуб М.

5
Якщо ви вручну встановите параметри wі hв, fig.set_size_inches(w,h)і dpiпараметр fig.savefig(fname, dpi)таким чином, що він приведе до 24 пікселів на 24 пікселів, він повинен працювати нормально. Наприклад, w = h = 1іdpi = 24
matehat

5
Мені довелося поєднати і цю, і відповідь нижче Мостафи Пакпарвара. Вам потрібно не тільки вимкнути осі, але вам потрібно встановити_видимий на false, щоб переконатися, що пробіл зникає. (wtf?)
Bryce Guinta

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

2
Це правильний підхід. ax = plt.Axes(fig, [0., 0., 1., 1.])це те, що змушує це працювати.
greatvovan

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,

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.03.18

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 () не існують. Будь-яка ідея, чому це могло статися?
Jacob Malachowski

Створіть об'єкт axes (), потім використовуйте ax.xaxis та ax.yaxis
perigon

Помилка повідомлення про те, що об'єкт "список" не має атрибута "get_xaxis"
Haozhe Xie

7

Цей працює для мене

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

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

Для тих, хто намагається зробити це в Юпітері

 plt.axis('off')

 spec = plt.imshow

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

2

Хоча наведені вище відповіді стосуються видалення полів та відступів, вони не спрацювали для мене при видаленні міток. Ось що вдалося для тих, хто пізніше натрапить на це питання:

Якщо припустити, що вам потрібна сітка розмірів 2х2 із чотирьох зображень, що зберігаються в 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 (будь-який колір призвів до позбавлення від білого кордону). Сподіваюся, це допомагає.

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
OS Windows 10

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.