Видалення білого простору навколо збереженого зображення в matplotlib


172

Мені потрібно сфотографувати і зберегти його після деякого процесу. Фігура виглядає добре, коли я її відображаю, але після збереження фігури я отримав пробіл навколо збереженого зображення. Я спробував 'tight'варіант для savefigметоду, теж не працював. Код:

  import matplotlib.image as mpimg
  import matplotlib.pyplot as plt

  fig = plt.figure(1)
  img = mpimg.imread(path)
  plt.imshow(img)
  ax=fig.add_subplot(1,1,1)

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

  plt.axis('off') 
  plt.show()

Я намагаюся намалювати базовий графік, використовуючи NetworkX на фігурі, і зберегти його. Я зрозумів, що без графіку він працює, але, додавши графік, я отримую пробіл навколо збереженого зображення;

import matplotlib.image as mpimg
import matplotlib.pyplot as plt
import networkx as nx

G = nx.Graph()
G.add_node(1)
G.add_node(2)
G.add_node(3)
G.add_edge(1,3)
G.add_edge(1,2)
pos = {1:[100,120], 2:[200,300], 3:[50,75]}

fig = plt.figure(1)
img = mpimg.imread("C:\\images\\1.jpg")
plt.imshow(img)
ax=fig.add_subplot(1,1,1)

nx.draw(G, pos=pos)

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

plt.axis('off') 
plt.show()


Мені справді вдалося обрізати PDF за допомогою іншого інструменту, наприклад pdfcrop.
toliveira

Відповіді:


170

Я не можу стверджувати, що точно знаю, чому або як працює моє «рішення», але це те, що мені довелося зробити, коли я хотів скласти контур пари секцій аерофолів - без білих полів - у файл PDF. (Зверніть увагу, що я використовував matplotlib всередині ноутбука IPython із прапором -pylab.)

plt.gca().set_axis_off()
plt.subplots_adjust(top = 1, bottom = 0, right = 1, left = 0, 
            hspace = 0, wspace = 0)
plt.margins(0,0)
plt.gca().xaxis.set_major_locator(plt.NullLocator())
plt.gca().yaxis.set_major_locator(plt.NullLocator())
plt.savefig("filename.pdf", bbox_inches = 'tight',
    pad_inches = 0)

Я намагався деактивувати різні частини цього, але це завжди десь призводить до білого поля. Ви можете навіть змінити це, щоб жирові лінії не були витіснені від меж фігури від нестачі запасів.


6
Нарешті щось, що працює, велике дякую! До речі, в моєму випадку set_major_locatorпотрібні були лише два використовувані рядки .
Флоріан Брюкер

6
Я провів останню годину, пробуючи різні речі, і не міг позбутися від 1 px білої рамки. Це було єдине, що спрацювало - конкретно про те, pad_inches=0що інші відповіді не згадуються.
AnnanFay

1
set_major_locatorбула для мене ключовою.
kmac

16
pad_inchesмені допомогли.
Майлз Бейкер

5
matplotlib.ticker.NullLocator ()
Joop

200

Ви можете видалити порожній простір відступів шляхом установки bbox_inches="tight"в savefig:

plt.savefig("test.png",bbox_inches='tight')

Вам доведеться поставити аргумент bbox_inchesяк рядок, можливо, саме тому він не працював раніше для вас.


Можливі дублікати:

Сюжети Matplotlib: видалення осі, легенди та пробіли

Як встановити поля для фігури matplotlib?

Зменшити лівий і правий поля в графіку matplotlib


1
Якщо у вас є кілька субплот, і ви хочете зберегти кожен з них, ви можете використовувати і це fig.savefig(). ( plt.savefig()не буде працювати в такому випадку.)
Абраніл Дас

30
Це не зовсім правильно. Коли ви використовуєте цю bbox_inchesопцію, є інший за замовчуванням, який залишає деякий простір. Якщо ви дійсно хочете позбутися всього, вам також потрібно скористатися pad_inches=0.0. Звичайно, такі щільні накладки часто зрізають, наприклад, експоненти ...
Майк

5
Щоб також видалити чорний край, вам може знадобитися встановитиpad_inches=-0.1
lenhhoxung

10
Це просто не працює, ви все одно отримуєте пробіл навколо фігури. Встановлення прозорого варіанту (як згадується в деяких відповідях) теж не допомагає, пробіл все ще є, він лише прозорий.
BjornW

1
@piperchester - це гарне питання, але, ймовірно, його слід задати як нове запитання взагалі, щоб воно не загубилося в коментарях. Ви повинні пов’язати нове питання зі старим!
Повісити

21

Після спроби вищезазначених відповідей без успіху (і ряду інших ставок) те, що нарешті працювало для мене, було просто

plt.gca().set_axis_off()
plt.subplots_adjust(top = 1, bottom = 0, right = 1, left = 0, 
            hspace = 0, wspace = 0)
plt.margins(0,0)
plt.savefig("myfig.pdf")

Що важливо, це не включає аргументи bbox або padding.


4
Це має бути прийнятою відповіддю. Крім того, вам навіть не потрібно дзвонити set_axis_off. Це не впливає на збережене зображення, оскільки після того, subplots_adjustяк вісь лежить поза межами фігури, і хен не буде побудована. У ноутбуках Юпітера, однак, потрібно чітко відключити вісь, оскільки вбудований сервер замінює ці параметри.
MaxPowers

20

Я знайшов щось від Арвінда Перейра ( http://robotics.usc.edu/~ampereir/wordpress/?p=626 ) і, здається, працює для мене:

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

7
transparent=Trueбуде здаватися, що немає ніякої проблеми, але це просто приховає пробіл, розміри зображення не будуть нормальними.
Владі Веселінов

Дякуємо за згадування pad_inches! Я б хотів, щоб я знав про цей варіант раніше!
ingomueller.net

1
Це працює для більшості сюжетів, але це видалило правильну межу для моєї матриці плутанини. Просто додайте невелику підкладкуpad_inches=.25
YTZ

14

Наступна функція включає в себе відповідь johannes-s вище. Я перевірив його plt.figureі plt.subplots()з декількома осями, і він прекрасно працює.

def save(filepath, fig=None):
    '''Save the current image with no whitespace
    Example filepath: "myfig.png" or r"C:\myfig.pdf" 
    '''
    import matplotlib.pyplot as plt
    if not fig:
        fig = plt.gcf()

    plt.subplots_adjust(0,0,1,1,0,0)
    for ax in fig.axes:
        ax.axis('off')
        ax.margins(0,0)
        ax.xaxis.set_major_locator(plt.NullLocator())
        ax.yaxis.set_major_locator(plt.NullLocator())
    fig.savefig(filepath, pad_inches = 0, bbox_inches='tight')

Працював як шарм. Попередня відповідь була деякими необхідними командами в моєму експорті.
Кевін S

11

Я виявив, що наступні коди прекрасно працюють для цієї роботи.

fig = plt.figure(figsize=[6,6])
ax = fig.add_subplot(111)
ax.imshow(data)
ax.axes.get_xaxis().set_visible(False)
ax.axes.get_yaxis().set_visible(False)
ax.set_frame_on(False)
plt.savefig('data.png', dpi=400, bbox_inches='tight',pad_inches=0)

2
Як правило, відповіді набагато корисніші, якщо вони включають пояснення того, що призначений для виконання коду та чому це вирішує проблему, не вводячи інших.
Тім Дікманн

7

Я дотримувався цієї послідовності, і це працювало як шарм.

plt.axis("off")
fig=plt.imshow(image array,interpolation='nearest')
fig.axes.get_xaxis().set_visible(False)
fig.axes.get_yaxis().set_visible(False)
plt.savefig('destination_path.pdf',
    bbox_inches='tight', pad_inches=0, format='pdf', dpi=1200)

1
Власне, я знайшов цю відповідь простою та зручнішою у використанні.
sikisis

1
Цей працював на мене; прийнятої відповіді не стало.
Джо

3

Для всіх, хто хоче працювати в пікселях, а не в дюймах, це буде працювати.

Плюс звичайне вам також знадобиться

from matplotlib.transforms import Bbox

Тоді ви можете використовувати наступне:

my_dpi = 100 # Good default - doesn't really matter

# Size of output in pixels
h = 224
w = 224

fig, ax = plt.subplots(1, figsize=(w/my_dpi, h/my_dpi), dpi=my_dpi)

ax.set_position([0, 0, 1, 1]) # Critical!

# Do some stuff
ax.imshow(img)
ax.imshow(heatmap) # 4-channel RGBA
ax.plot([50, 100, 150], [50, 100, 150], color="red")

ax.axis("off")

fig.savefig("saved_img.png",
            bbox_inches=Bbox([[0, 0], [w/my_dpi, h/my_dpi]]),
            dpi=my_dpi)

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


Не потрібно вказувати dpi, fig.dpiзамість цього можна скористатись типовим
intsco

1

Набагато простішим підходом я став plt.imsave:

    import matplotlib.pyplot as plt
    arr = plt.imread(path)
    plt.imsave('test.png', arr)

Занижена відповідь. Це допомогло мені після довгих пошуків, як зберегти роздільну здатність і видалити пробіли plt.savefig().
nihal111

Це працює лише в тому випадку, якщо ви хочете зберегти масив (!) Як зображення. Це не дозволяє зберегти довільну цифру.
MaxPowers

Що ви маєте на увазі під довільним зображенням? Чи не зображення є масивом значень?
Parth92

0

Ви можете спробувати це. Це вирішило моє питання.

import matplotlib.image as mpimg
img = mpimg.imread("src.png")
mpimg.imsave("out.png", img, cmap=cmap)

-1

Якщо ви хочете показати, що потрібно зберегти, я рекомендую використовувати plt.tight_layoutтрансформацію, яка є фактично більш кращою, оскільки вона не робить зайвого обрізання при використанніplt.savefig

import matplotlib as plt    
plt.plot([1,2,3], [1,2,3])
plt.tight_layout(pad=0)
plt.savefig('plot.png')

-4

Це працює для мене, зберігаючи numpy масив, побудований з імшоу для файлу

import matplotlib.pyplot as plt

fig = plt.figure(figsize=(10,10))
plt.imshow(img) # your image here
plt.axis("off")
plt.subplots_adjust(top = 1, bottom = 0, right = 1, left = 0, 
        hspace = 0, wspace = 0)
plt.savefig("example2.png", box_inches='tight', dpi=100)
plt.show()
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.