Python et Matplotlib nouveaux, je voudrais simplement appliquer une palette de couleurs à une image et écrire l'image résultante, sans utiliser d'axes, d'étiquettes, de titres ou quoi que ce soit habituellement ajouté automatiquement par matplotlib. Voici ce que j'ai fait:
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)
Il supprime avec succès l'axe de la figure, mais la figure enregistrée présente un remplissage blanc et un cadre autour de l'image réelle. Comment puis-je les supprimer (au moins le rembourrage blanc)? Merci
Je pense que la commande axis('off')
résout l'un des problèmes plus succinctement que de changer chaque axe et la bordure séparément. Il reste cependant l’espace blanc autour de la frontière. L'ajout de bbox_inches='tight'
à la commande savefig
vous y amène presque. Vous pouvez voir dans l'exemple ci-dessous que l'espace blanc restant est beaucoup plus petit, mais toujours présent.
Notez que les nouvelles versions de matplotlib peuvent nécessiter bbox_inches=0
au lieu de la chaîne 'tight'
(via @episodeyang et @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')
J'ai appris cette astuce 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')
les rendements
Solution la plus simple possible:
J'ai simplement combiné la méthode décrite dans la question et la méthode tirée de la réponse 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)
Après ce code, il n’ya plus d’espace ni de cadre.
Personne n'a mentionné imsave
, ce qui en fait un 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")
Il stocke directement l’image telle quelle, c’est-à-dire qu’il n’ajoute aucun axe ni bordure/remplissage.
Vous pouvez également spécifier l'étendue de la figure dans l'argument bbox_inches
. Cela éliminerait le rembourrage blanc autour de la figure.
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)
Cela devrait supprimer tout le rembourrage et les bordures:
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)
J'ai bien aimé d'ubunt répondre, mais cela ne montrait pas explicitement comment définir la taille des images non carrées prêtes à l'emploi, je l'ai donc modifiée pour faciliter le copier-coller:
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()
Il est facile d’enregistrer des images sans bordure, quelle que soit la résolution choisie si pixel_size/dpi = size est conservé.
data = mpimg.imread('test.png')
save_image_fix_dpi(data, dpi=100)
Cependant, l'affichage est fantasmagorique. Si vous choisissez un petit dpi, la taille de votre image peut être supérieure à celle de votre écran et vous obtenez une bordure pendant l'affichage. Néanmoins, cela n’affecte pas l’épargne.
Donc pour
save_image_fix_dpi(data, dpi=20)
Tout d'abord, pour certains formats d'image (c'est-à-dire TIFF ), vous pouvez réellement enregistrer la palette de couleurs dans l'en-tête et la plupart des lecteurs afficheront vos données avec la palette de couleurs.
Pour enregistrer une image matplotlib
réelle, ce qui peut être utile pour ajouter des annotations ou d'autres données aux images, j'ai utilisé la solution suivante:
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)
Merci pour les réponses géniales de tout le monde ... J'ai eu exactement le même problème avec le désir de tracer une image sans aucune marge/espace supplémentaire, donc j'étais super heureux de trouver les idées de tout le monde ici.
Outre une image sans remplissage, je voulais aussi pouvoir ajouter facilement des annotations, etc., au-delà d'un simple tracé d'image.
Donc, ce que j'ai fini par faire était de combiner la réponse de David avec csnemes ' pour créer un simple wrapper au moment de la création de la figure. Lorsque vous utilisez cela, vous n'avez besoin d'aucune modification plus tard avec imsave () ou quoi que ce soit d'autre:
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
Toutes les anciennes réponses ne fonctionnent plus. Vous devez utiliser bbox_inches=0
pour le faire fonctionner.
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.
Sinon, vous pouvez utiliser
plt.savefig("test.png", bbox_inches=None)
La présence ou non de cet argument de mot clé a un impact sur la manière dont matplotlib
traite les mots clés facultatifs.
Ceci est testé avec la version 3.0.3
le 2019/06/19.
La réponse votée ne fonctionne plus. Pour que cela fonctionne, vous devez ajouter manuellement un axe défini sur [0, 0, 1, 1] ou supprimer le patch sous la figure.
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")
Alternativement, vous pouvez simplement supprimer le patch. Vous n'avez pas besoin d'ajouter une sous-parcelle pour supprimer les bourrages. Ceci est simplifié à partir de réponse de Vlady ci-dessous
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')
Ceci est testé avec la version 3.0.3
le 2019/06/19. Image voir ci-dessous:
Une chose beaucoup plus simple à faire est d'utiliser pyplot.imsave
. Pour plus de détails, voir la réponse de luator ci-dessous