Графики Matplotlib: удаление оси, легенд и пробелов
Я новичок в Python и Matplotlib, я хотел бы просто применить colormap к изображению и написать результирующее изображение без использования осей, ярлыков, титров или чего-либо, обычно автоматически добавляемого matplotlib. Вот что я сделал:
def make_image(inputname,outputname):
data = mpimg.imread(inputname)[:,:,0]
fig = plt.imshow(data)
fig.set_cmap('hot')
fig.axes.get_xaxis().set_visible(False)
fig.axes.get_yaxis().set_visible(False)
plt.savefig(outputname)
Он успешно удаляет ось фигуры, но сохраненная фигура представляет собой белое дополнение и рамку вокруг фактического изображения.
Как я могу удалить их (по крайней мере, белое дополнение)? Благодаря
Ответы
Ответ 1
Я думаю, что командная axis('off')
решает одну из проблем более кратко, чем изменение каждой оси и границы в отдельности. Это все еще оставляет белое пространство вокруг границы как бы то ни было. Добавление bbox_inches='tight'
к команде savefig
почти savefig
вас туда. В приведенном ниже примере вы можете видеть, что savefig
пространство намного меньше, но все еще присутствует.
Обратите внимание, что в более новых версиях matplotlib может потребоваться bbox_inches=0
вместо строки 'tight'
thin 'tight'
(через @episodeyang и @kadrach)
from numpy import random
import matplotlib.pyplot as plt
data = random.random((5,5))
img = plt.imshow(data, interpolation='nearest')
img.set_cmap('hot')
plt.axis('off')
plt.savefig("test.png", bbox_inches='tight')
![enter image description here]()
Ответ 2
Я узнал этот трюк из matehat, здесь:
import matplotlib.pyplot as plt
import numpy as np
def make_image(data, outputname, size=(1, 1), dpi=80):
fig = plt.figure()
fig.set_size_inches(size)
ax = plt.Axes(fig, [0., 0., 1., 1.])
ax.set_axis_off()
fig.add_axes(ax)
plt.set_cmap('hot')
ax.imshow(data, aspect='equal')
plt.savefig(outputname, dpi=dpi)
# data = mpimg.imread(inputname)[:,:,0]
data = np.arange(1,10).reshape((3, 3))
make_image(data, '/tmp/out.png')
дает
![enter image description here]()
Ответ 3
Возможное простейшее решение:
Я просто объединил метод, описанный в вопросе и метод из ответа Hooked.
fig = plt.imshow(my_data)
plt.axis('off')
fig.axes.get_xaxis().set_visible(False)
fig.axes.get_yaxis().set_visible(False)
plt.savefig('pict.png', bbox_inches='tight', pad_inches = 0)
После этого кода нет пробелов и кадр.
![No whitespaces, axes or frame]()
Ответ 4
Никто еще не упомянул imsave
, что делает его однострочным:
import matplotlib.pyplot as plt
import numpy as np
data = np.arange(10000).reshape((100, 100))
plt.imsave("/tmp/foo.png", data, format="png", cmap="hot")
Он напрямую сохраняет изображение как есть, то есть не добавляет никаких осей или границ/отступов.
![enter image description here]()
Ответ 5
Вы также можете указать степень фигуры в аргументе bbox_inches
. Это избавится от белого заполнения вокруг фигуры.
def make_image(inputname,outputname):
data = mpimg.imread(inputname)[:,:,0]
fig = plt.imshow(data)
fig.set_cmap('hot')
ax = fig.gca()
ax.set_axis_off()
ax.autoscale(False)
extent = ax.get_window_extent().transformed(plt.gcf().dpi_scale_trans.inverted())
plt.savefig(outputname, bbox_inches=extent)
Ответ 6
Это должно удалить все отступы и границы:
from matplotlib import pyplot as plt
fig = plt.figure()
fig.patch.set_visible(False)
ax = fig.add_subplot(111)
plt.axis('off')
plt.imshow(data)
extent = ax.get_window_extent().transformed(fig.dpi_scale_trans.inverted())
plt.savefig("../images/test.png", bbox_inches=extent)
Ответ 7
Мне понравился ответ Ubuntu, но он не показывал явно, как установить размер для неквадратных изображений из коробки, поэтому я изменил его для легкой копирования-вставки:
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import numpy as np
def save_image_fix_dpi(data, dpi=100):
shape=np.shape(data)[0:2][::-1]
size = [float(i)/dpi for i in shape]
fig = plt.figure()
fig.set_size_inches(size)
ax = plt.Axes(fig,[0,0,1,1])
ax.set_axis_off()
fig.add_axes(ax)
ax.imshow(data)
fig.savefig('out.png', dpi=dpi)
plt.show()
Сохранять изображения без рамки легко, независимо от того, какое значение dpi вы выберете, если сохранить pixel_size/dpi = size.
data = mpimg.imread('test.png')
save_image_fix_dpi(data, dpi=100)
![enter image description here]()
Однако показ жуткий. Если вы выберете маленькое dpi, размер вашего изображения может быть больше, чем у экрана, и вы получите границы во время отображения. Тем не менее, это не влияет на экономию.
Таким образом, для
save_image_fix_dpi(data, dpi=20)
Дисплей становится окаймленным (но сохранение работает): ![enter image description here]()
Ответ 8
Во-первых, для определенных форматов изображений (например, TIFF) вы можете фактически сохранить цветовую карту в заголовке, и большинство зрителей покажет ваши данные с помощью цветной карты.
Для сохранения реального изображения matplotlib
, которое может быть полезно для добавления аннотаций или других данных к изображениям, я использовал следующее решение:
fig, ax = plt.subplots(figsize=inches)
ax.matshow(data) # or you can use also imshow
# add annotations or anything else
# The code below essentially moves your plot so that the upper
# left hand corner coincides with the upper left hand corner
# of the artist
fig.subplots_adjust(left=0, right=1, top=1, bottom=0, wspace=0, hspace=0)
# now generate a Bbox instance that is the same size as your
# single axis size (this bbox will only encompass your figure)
bbox = matplotlib.transforms.Bbox(((0, 0), inches))
# now you can save only the part of the figure with data
fig.savefig(savename, bbox_inches=bbox, **kwargs)
Ответ 9
Ответ с лишним голосом больше не работает. Чтобы заставить его работать, вам нужно вручную добавить ось, установленную в [0, 0, 1, 1], или удалить патч под рисунком.
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(5, 5), dpi=20)
ax = plt.Axes(fig, [0., 0., 1., 1.])
fig.add_axes(ax)
plt.imshow([[0, 1], [0.5, 0]], interpolation="nearest")
plt.axis('off') # same as: ax.set_axis_off()
plt.savefig("test.png")
Кроме того, вы можете просто удалить патч. Вам не нужно добавлять подзаговор, чтобы удалить отступы. Это упрощено от Влады ответ ниже
fig = plt.figure(figsize=(5, 5))
fig.patch.set_visible(False) # turn off the patch
plt.imshow([[0, 1], [0.5, 0]], interpolation="nearest")
plt.axis('off')
plt.savefig("test.png", cmap='hot')
Это проверено с версией 3.0.3
на 2019/06/19. Изображение см. Ниже:
![enter image description here]()
Намного проще сделать это с помощью pyplot.imsave
. Для получения дополнительной информации см. Ответ luator ниже
Ответ 10
Ответ с лишним голосом больше не работает. Чтобы заставить его работать, вам нужно вручную добавить ось, установленную в [0, 0, 1, 1], или удалить патч под рисунком.
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(5, 5), dpi=20)
ax = plt.Axes(fig, [0., 0., 1., 1.])
fig.add_axes(ax)
plt.imshow([[0, 1], [0.5, 0]], interpolation="nearest")
plt.axis('off') # same as: ax.set_axis_off()
plt.savefig("test.png")
Кроме того, вы можете просто удалить патч. Вам не нужно добавлять подзаговор, чтобы удалить отступы. Это упрощено от Влады ответ ниже
fig = plt.figure(figsize=(5, 5))
fig.patch.set_visible(False) # turn off the patch
plt.imshow([[0, 1], [0.5, 0]], interpolation="nearest")
plt.axis('off')
plt.savefig("test.png", cmap='hot')
Это проверено с версией 3.0.3
на 2019/06/19. Изображение см. Ниже:
![enter image description here]()
Намного проще сделать это с помощью pyplot.imsave
. Для получения дополнительной информации см. Ответ luator ниже
Ответ 11
Спасибо за потрясающие ответы от всех... У меня была точно такая же проблема с желанием нарисовать только изображение без лишних отступов/пробелов и т.д., Поэтому был очень рад найти здесь все идеи.
Помимо изображения без отступов, я также хотел иметь возможность легко добавлять аннотации и т.д., Помимо простого графического изображения.
В итоге я соединил ответ дэвида с csnemes ', чтобы создать простую обертку во время создания фигуры. Когда вы используете это, вам не нужно вносить изменения позже с помощью imsave() или чего-либо еще:
def get_img_figure(image, dpi):
"""
Create a matplotlib (figure,axes) for an image (numpy array) setup so that
a) axes will span the entire figure (when saved no whitespace)
b) when saved the figure will have the same x/y resolution as the array,
with the dpi value you pass in.
Arguments:
image -- numpy 2d array
dpi -- dpi value that the figure should use
Returns: (figure, ax) tuple from plt.subplots
"""
# get required figure size in inches (reversed row/column order)
inches = image.shape[1]/dpi, image.shape[0]/dpi
# make figure with that size and a single axes
fig, ax = plt.subplots(figsize=inches, dpi=dpi)
# move axes to span entire figure area
fig.subplots_adjust(left=0, right=1, top=1, bottom=0, wspace=0, hspace=0)
return fig, ax
Ответ 12
Я обнаружил, что это все задокументировано...
https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.axes.Axes.axis.html#matplotlib.axes.Axes.axis
Мой код "bcK" - изображение 512x512
plt.figure()
plt.imshow(bck)
plt.axis("off") # turns off axes
plt.axis("tight") # gets rid of white border
plt.axis("image") # square up the image instead of filling the "figure" space
plt.show()