scipy: savefig sem frames, eixos, apenas conteúdo


92

Em numpy / scipy, tenho uma imagem armazenada em uma matriz. Posso exibi-lo, quero salvá-lo usando savefig sem bordas, eixos, rótulos, títulos, ... Apenas imagem pura, nada mais.

Eu quero evitar pacotes como PyPNGou scipy.misc.imsave, eles às vezes são problemáticos (eles nem sempre instalam bem, apenas básicos savefig()para mim

Respostas:


118

EDITAR

Alterado aspect='normalpara aspect='auto'desde que mudou nas versões mais recentes do matplotlib (graças a @ Luke19).


Assumindo:

import matplotlib.pyplot as plt

Para fazer uma figura sem moldura:

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

Para fazer o conteúdo preencher a figura inteira

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

Em seguida, desenhe sua imagem nele:

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

O aspectparâmetro altera o tamanho do pixel para garantir que preencham o tamanho da figura especificado em fig.set_size_inches(…). Para ter uma ideia de como brincar com esse tipo de coisa, leia a documentação do matplotlib , particularmente sobre o assunto Axes, Axis e Artist.


4
não, ainda tenho uma pequena borda transparente e o que eu quero não é nenhuma borda , imagem pura
Jakub M.

5
Se você definir manualmente os parâmetros we hem fig.set_size_inches(w,h)e o dpiparâmetro em de fig.savefig(fname, dpi)modo que resulte em 24px por 24px, deve funcionar perfeitamente. Por exemplo, w = h = 1edpi = 24
matehat

5
Tive de combinar esta resposta e a resposta abaixo de Mostafa Pakparvar. Você não só precisa desligar os eixos, mas também definir set_visible para false para garantir que o espaço em branco desapareça. (wtf?)
Bryce Guinta

6
Tentei fazer isso usando matplotlib v2.2.2 e funcionou perfeitamente (exceto que imshowa sintaxe foi alterada para em aspect='auto'vez de 'normal').
Luke19

2
Esta é a abordagem certa. ax = plt.Axes(fig, [0., 0., 1., 1.])é o que o faz funcionar.
greatvovan

74

Uma solução mais fácil parece ser:

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

2
Isso funcionou muito bem para mim. Além disso, pad_inches podem ser alterados para o tamanho desejado facilmente. Obrigado!
Curious2learn

27
Eu ainda tenho margens brancas com isso.
Fábio Perez

5
Consegui atualizar isso para versões mais novas / problema de margens restantes simplesmente adicionando transparent = True fig.savefig('out.png', bbox_inches='tight',transparent=True, pad_inches=0)
mdoc-2011

2
Ainda tenho machados, marcas de seleção e tudo mais com isto :(
BjornW,

3
Isso não faz absolutamente nada. Ele lhe dará a figura com todos os eixos e rótulos.
1313e

27

Você pode encontrar a bbox da imagem dentro do eixo (usando get_window_extent) e usar o bbox_inchesparâmetro para salvar apenas aquela parte da imagem:

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)

Aprendi esse truque com Joe Kington aqui .


6
apenas plt.axis('off')ajudou. Outras respostas não ajudam muito.
imsrgadich

3
Isso funcionou muito bem. Porém, no meu caso, ainda há uma pequena borda branca. Alguma ideia de como remover essa fronteira?
user3731622

@ user3731622, tente em plt.savefig('/temp/test.png', bbox_inches='tight', transparent=True, pad_inches=0)vez deplt.savefig('/tmp/test.png', bbox_inches=extent)
Cloud Cho

17

Eu tentei várias opções no meu caso, e a melhor solução foi esta:

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

então salve sua figura com savefig


1
De todas essas soluções, esta é a única que funcionou para mim.
Puff de

8

Vou sugerir a resposta heron13 com uma ligeira adição emprestada daqui para remover o preenchimento deixado após definir o bbox para o modo apertado, portanto:

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)

Estou recebendo um erro dizendo que get_xaxis () e get_yaxis () não existem. Alguma ideia de por que isso aconteceria?
Jacob Malachowski

Realizar uma eixos () objeto, então use ax.xaxis e ax.yaxis
perigon

Ocorreu um erro dizendo que o objeto 'list' não tem o atributo 'get_xaxis'
Haozhe Xie

7

Este funciona para mim

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

3

Tive o mesmo problema ao fazer algumas visualizações usando a librosa onde queria extrair o conteúdo da trama sem qualquer outra informação. Portanto, esta é a minha abordagem. resposta unutbu também me ajuda a fazer funcionar.

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

Isso me colocou no caminho certo, mas tive dois problemas: 1) Tive que definir o dpi para um número maior do que 1 para evitar um erro de fonte em meu caderno jupyter; e 2) ainda havia uma pequena borda, então eu tenho que alterar manualmente a extensão para Bbox extent.get_points()*np.array([[1.1],[.9]]).
Bob Baxley

obrigado por cumprir a resposta que pode ajudar a outra pessoa.
GPrathap

3

Para quem está tentando fazer isso em Jupyter

 plt.axis('off')

 spec = plt.imshow

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

2

Embora as respostas acima tratem da remoção de margens e preenchimento, elas não funcionaram para mim na remoção de rótulos. Aqui está o que funcionou, para quem se depara com esta questão mais tarde:

Supondo que você queira uma grade 2x2 de subtramas de quatro imagens armazenadas em 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

Tentei me livrar da borda também, usando dicas aqui, mas nada funcionou. Fugindo um pouco e descobri que mudar a cor do rosto não me deu bordas nos laboratórios Jupyter (qualquer cor resultou na eliminação da borda branca). Espero que isto ajude.

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

insira a descrição da imagem aqui


1

Para mim, este código tornou semelhante o tamanho da imagem de entrada sem moldura e eixos dos códigos matehat , unutbu e 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)

Ambiente de tempo de execução:
Python 3.6.10
Matplotlib 3.2.1
OS Windows 10

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.