2012-02-15 11 views
128

Soy nuevo en Python y Matplotlib, me gustaría simplemente aplicar colormap a una imagen y escribir la imagen resultante, sin usar ejes, etiquetas, títulos ni nada que se agregue automáticamente por matplotlib. Esto es lo que hice:Gráficos de Matplotlib: eliminación de ejes, leyendas y espacios en blanco

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) 

Se elimina con éxito el eje de la figura, pero la figura salvado presenta un acolchado blanco y un marco alrededor de la imagen real. ¿Cómo puedo eliminarlos (al menos el relleno blanco)? Gracias

+0

Todas las soluciones en esta pregunta se centra en 'imshow'. Si tiene un diagrama de dispersión, la siguiente respuesta podría ayudarlo: http://stackoverflow.com/a/40727744/4124317 – ImportanceOfBeingErnest

+0

Esta pregunta es actualmente el segundo resultado de una búsqueda en Google de 'matplotlib'. – onewhaleid

Respuesta

176

Creo que el comando axis('off') se encarga de uno de los problemas más sucinta que cambiar cada eje y las frontera por separado. Sin embargo, deja el espacio en blanco alrededor de la frontera. Agregar bbox_inches='tight' al comando savefig casi lo lleva hasta allí, puede ver en el ejemplo a continuación que el espacio en blanco que queda es mucho más pequeño, pero aún está presente.

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

+3

Siguiendo la sugerencia de unutbu, podría usar 'fig = plt.figure()', 'ax = plt.axes ([0,0,1,1])', luego 'plt.imshow (data, interpolation =" más cercano " '. Combinado con' plt.axis ("off") ', debería deshacerse de todo lo que se encuentre al lado de la imagen, con suerte! – PhilMacKay

+1

Combinando los métodos de la pregunta ({fig.axes.get_xaxis(). Set_visible (False) & fig.axes.get_yaxis(). set_visible (False)} con {plt.axis ('off')}) me arregló el problema. (Ya no hay espacios en blanco). Y no olvides configurar {pad_inches} en savefig en 0 – Domagoj

+2

Acabo de toparme con este problema, ninguna de las soluciones en este hilo, ni las vinculadas, funcionó. Sin embargo, especificar explícitamente 'bbox_inches = 0' hizo el truco. – kadrach

62

Aprendí este truco 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') 

rendimientos

enter image description here

+2

Estoy bastante seguro de que tienes la respuesta correcta (aunque probablemente haya más de una forma de hacerlo), pero me pregunto si puedes explicar * por qué * es la respuesta correcta. ¿Qué pasa con su código elimina el espacio en blanco? – Yann

+0

Siguiendo el enlace, encuentro una respuesta a lo que me preguntaba sobre ... – Yann

+3

@Yann, además de la documentación, encuentro muy útil comentar una línea a la vez para ver qué efecto tiene cada comando. ¡Es la forma empírica! – unutbu

7

También puede especificar la extensión de la figura para el argumento bbox_inches. Esto eliminaría el relleno blanco alrededor de la 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) 
27

Posible solución más simple:

I combina simplemente el método descrito en la pregunta y el método de la respuesta por enganchado.

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) 

Después de este código no hay espacios en blanco ni marco.

No whitespaces, axes or frame

+2

Su método eliminó todos los espacios en blanco alrededor de esta imagen, buen trabajo, pero todavía no sé por qué agregar el comando 'fig.axes.get_xaxis(). set_visible (False)' resolver el problema. Gracias – ollydbg23

+3

Sí, si no llamas a este comando, se eliminarán la mayoría de los espacios en blanco. Sin embargo, en mi caso todavía había algunos espacios entre mi trama y el borde de la imagen .png (tal vez 2px de ancho). Al llamar a los siguientes comandos, me deshice de esos espacios difíciles. – Domagoj

+3

Sin embargo, tenga en cuenta que lo anterior fallará en presencia de varios ejes en la misma figura (en mi caso, una imagen incrustada en la trama). Solución: 'fig.axes [0]', y en general todos o los ejes seleccionados. –

9

Nadie mencionado imsave todavía, lo que hace esta una sola línea:

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

Almacena directamente la imagen tal como es, es decir, no añade ningún ejes o frontera/relleno.

enter image description here

0

En primer lugar, para ciertos formatos de imagen (es decir, TIFF) en realidad se puede guardar el mapa de colores en la cabecera y la mayoría de los televidentes podrán mostrar sus datos con el mapa de colores.

Para guardar una imagen real matplotlib, que puede ser útil para añadir anotaciones u otros datos a las imágenes, he utilizado la siguiente solución:

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

me ha gustado ubuntu's respuesta, pero no mostraba explícitamente cómo configurar el tamaño de las imágenes no cuadrados fuera de la caja, por lo que he modificado para una fácil copiar y pegar:

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

almacenamiento de imágenes sin frontera es fácil lo dpi elige si pixel_size/dpi = el tamaño se mantiene.

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

enter image description here

Sin embargo visualización es espeluznante. Si elige una resolución de dpi pequeña, el tamaño de su imagen puede ser más grande que la de su pantalla y obtendrá un borde durante la visualización. Sin embargo, esto no afecta el ahorro.

Así que para

save_image_fix_dpi(data, dpi=20) 

la pantalla se limita (pero las obras de ahorros): enter image description here

Cuestiones relacionadas