scipy: savefig sin marcos, ejes, solo contenido

92

En numpy / scipy tengo una imagen almacenada en una matriz. Puedo mostrarlo, quiero guardarlo usando savefig sin bordes, ejes, etiquetas, títulos, ... Solo imagen pura, nada más.

Quiero evitar paquetes como PyPNGo scipy.misc.imsave, a veces son problemáticos (no siempre se instalan bien, solo básicos savefig()para mí

Jakub M.
fuente

Respuestas:

115

EDITAR

Cambiado aspect='normala aspect='auto'porque eso cambió en versiones más recientes de matplotlib (gracias a @ Luke19).


Asumiendo :

import matplotlib.pyplot as plt

Para hacer una figura sin el marco:

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

Para que el contenido llene toda la figura

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

Luego dibuja tu imagen en él:

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

El aspectparámetro cambia el tamaño de los píxeles para asegurarse de que llenen el tamaño de la figura especificado en fig.set_size_inches(…). Para tener una idea de cómo jugar con este tipo de cosas, lea la documentación de matplotlib , particularmente sobre el tema de Axes, Axis y Artist.

matehat
fuente
4
no, todavía tengo un pequeño borde transparente, y lo que quiero no es ningún borde , imagen pura
Jakub M.
5
Si ajusta manualmente el wy hparámetros en fig.set_size_inches(w,h)y el dpiparámetro de fig.savefig(fname, dpi)modo que resulta en 24px por 24px, que debería funcionar bien. Por ejemplo, w = h = 1ydpi = 24
matehat
5
Tuve que combinar esta respuesta y la respuesta a continuación de Mostafa Pakparvar. No solo necesita apagar los ejes, sino que también necesita establecer_visible en falso para asegurarse de que el espacio en blanco desaparezca. (wtf?)
Bryce Guinta
6
Intenté esto usando matplotlib v2.2.2 y funcionó perfectamente (excepto que imshowla sintaxis cambió a en aspect='auto'lugar de 'normal').
Luke
2
Este es el enfoque correcto. ax = plt.Axes(fig, [0., 0., 1., 1.])es lo que lo hace funcionar.
greatvovan
73

Una solución más sencilla parece ser:

fig.savefig('out.png', bbox_inches='tight', pad_inches=0)
rana del tiempo
fuente
2
Esto funcionó muy bien para mí. Además, pad_inches se puede cambiar fácilmente al tamaño deseado. ¡Gracias!
Curious2learn
27
Todavía tengo márgenes blancos con esto.
Fábio Perez
3
Pude actualizar esto para versiones más nuevas / problema de márgenes restantes simplemente agregando transparent = True fig.savefig('out.png', bbox_inches='tight',transparent=True, pad_inches=0)
mdoc-2011
2
Todavía tengo ejes y marcas y todo con esto :(
BjornW
3
Esto no hace nada en absoluto. Te dará la figura con todos los ejes y etiquetas.
1313e
27

Puede encontrar el bbox de la imagen dentro del eje (usando get_window_extent) y usar el bbox_inchesparámetro para guardar solo esa parte de la imagen:

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)

Aprendí este truco de Joe Kington aquí .

unutbu
fuente
6
sólo plt.axis('off')ayudó. Otras respuestas no ayudan mucho.
imsrgadich
3
Esto funcionó bastante bien. Sin embargo, en mi caso todavía hay un pequeño borde blanco. ¿Alguna idea de cómo eliminar este borde?
user3731622
@ user3731622, intente en plt.savefig('/temp/test.png', bbox_inches='tight', transparent=True, pad_inches=0)lugar deplt.savefig('/tmp/test.png', bbox_inches=extent)
Cloud Cho
17

Probé varias opciones en mi caso, y la mejor solución fue esta:

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

luego guarda tu figura con savefig

Cagri Sarigoz
fuente
1
De todas estas soluciones, esta es la única que funcionó para mí.
Puff
8

Sugeriré la respuesta de heron13 con una pequeña adición tomada de aquí para eliminar el relleno que queda después de configurar el bbox en modo ajustado, por lo tanto:

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)
Mostafa Pakparvar
fuente
Recibo un error que dice que get_xaxis () y get_yaxis () no existen. ¿Alguna idea de por qué pasaría eso?
Jacob Malachowski
Hacer una ejes () objeto, a continuación, utilizar ax.xaxis y ax.yaxis
Perigon
Obtuve un error que decía que el objeto 'lista' no tiene atributo 'get_xaxis'
Haozhe Xie
7

Este funciona para mi

plt.savefig('filename',bbox_inches='tight',transparent=True, pad_inches=0)
Cathy Yang
fuente
3

Tuve el mismo problema mientras hacía una visualización usando librosa donde quería extraer el contenido de la trama sin ninguna otra información. Así que este es mi enfoque. Unutbu answer también me ayuda a trabajar.

    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()
GPrathap
fuente
Esto me puso en el camino correcto, pero tuve dos problemas: 1) Tuve que configurar el ppp en un número mayor que 1 para evitar un error de fuente en mi cuaderno jupyter; y 2) todavía había un borde pequeño, así que tengo que cambiar manualmente la extensión a Bbox extent.get_points()*np.array([[1.1],[.9]]).
Bob Baxley
gracias por completar la respuesta que puede ayudar a alguien más.
GPrathap
3

Para cualquiera que intente hacer esto en Jupyter

 plt.axis('off')

 spec = plt.imshow

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

Si bien las respuestas anteriores abordan la eliminación de márgenes y relleno, no me funcionaron para eliminar etiquetas. Esto es lo que funcionó, para cualquiera que se encuentre con esta pregunta más adelante:

Suponiendo que desea una cuadrícula de 2x2 de subtramas de cuatro imágenes almacenadas en 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')
curioso
fuente
1

Traté de deshacerme de la frontera también, usando consejos aquí, pero nada realmente funcionó. Un poco de jugueteo y descubrí que cambiar el color de la cara no me daba ningún borde en los laboratorios de jupyter (cualquier color resultaba en eliminar el borde blanco). Espero que esto ayude.

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

ingrese la descripción de la imagen aquí

Atom Scott
fuente
0

Para mí, este código hizo similar el tamaño de la imagen de entrada sin marco y ejes de los códigos matehat , unutbu y 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)

Entorno de ejecución:
Python 3.6.10
Matplotlib 3.2.1
OS Windows 10

Cloud Cho
fuente