ti-enxame.com

Gráficos de Matplotlib: removendo eixos, lendas e espaços em branco

Eu sou novo em Python e Matplotlib, gostaria de simplesmente aplicar o mapa de cores a uma imagem e gravar a imagem resultante, sem usar eixos, rótulos, títulos ou qualquer coisa geralmente adicionada automaticamente pelo matplotlib. Aqui está o que eu fiz:

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)

Ele remove com sucesso o eixo da figura, mas a figura salva apresenta um preenchimento branco e um quadro ao redor da imagem real. Como posso removê-los (pelo menos o preenchimento branco)? obrigado

211
sunmat

Eu acho que o comando axis('off') cuida de um dos problemas de forma mais sucinta do que mudar cada eixo e a borda separadamente. Ainda deixa o espaço branco ao redor da fronteira no entanto. Adicionar bbox_inches='tight' ao comando savefig quase te leva até lá, você pode ver no exemplo abaixo que o espaço em branco que resta é muito menor, mas ainda está presente.

Note que versões mais novas do matplotlib podem exigir bbox_inches=0 em vez da string 'tight' (via @episodeyang e @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

285
Hooked

Eu aprendi esse truque de matehat, here :

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

rendimentos

enter image description here

87
unutbu

Possível solução mais simples:

Eu simplesmente combinei o método descrito na pergunta e o método da resposta de 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)

Após este código, não há espaços em branco e nenhum quadro.

No whitespaces, axes or frame

42
Domagoj

Ninguém mencionou imsave ainda, o que faz deste um one-liner:

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

Ele armazena diretamente a imagem como ela é, ou seja, não adiciona nenhum eixo ou borda/preenchimento.

enter image description here

23
luator

Você também pode especificar a extensão da figura para o argumento bbox_inches. Isso eliminaria o preenchimento branco em torno da figura.

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)
8
Miguel de Val-Borro

Isso deve remover todos os preenchimentos e bordas:

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)
5
Vlady Veselinov

Eu gostei bunt resposta, mas não estava mostrando explicitamente como definir o tamanho para imagens não-quadradas fora da caixa, então eu modifiquei para fácil copiar e colar:

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

Salvar imagens sem borda é fácil, independentemente do dpi escolhido, se pixel_size/dpi = size for mantido.

data = mpimg.imread('test.png')
save_image_fix_dpi(data, dpi=100)

enter image description here

No entanto, exibir é assustador. Se você escolher dpi pequeno, o tamanho da imagem poderá ser maior que a tela e você terá margem durante a exibição. No entanto, isso não afeta salvar.

Então para

save_image_fix_dpi(data, dpi=20)

O display torna-se limitado (mas o salvamento funciona): enter image description here

2
csnemes

Primeiro, para determinados formatos de imagem (ou seja, TIFF ), você pode salvar o mapa de cores no cabeçalho e a maioria dos visualizadores mostrará seus dados com o mapa de cores.

Para salvar uma imagem real de matplotlib, que pode ser útil para adicionar anotações ou outros dados a imagens, usei a seguinte solução:

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)
1
David Hoffman

Todas as respostas antigas não funcionam mais. Você precisa usar bbox_inches=0 para fazê-lo funcionar.

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=0)# <= this is where the difference is for newer maptlotlib.

Alternativamente, você poderia usar

plt.savefig("test.png", bbox_inches=None)

Se este argumento de palavra-chave existe faz uma diferença porque a maneira matplotlib lida com palavras-chave opcionais.

Isso é testado com a versão 3.0.3 em 2019/06/19.

0
episodeyang