scipy: savefig sans cadres, axes, seulement contenu


92

Dans numpy / scipy, j'ai une image stockée dans un tableau. Je peux l'afficher, je veux l'enregistrer en utilisant savefig sans bordures, axes, étiquettes, titres, ... Juste une image pure, rien d'autre.

Je veux éviter les paquets comme PyPNGou scipy.misc.imsave, ils sont parfois problématiques (ils ne s'installent pas toujours bien, seulement basiques savefig()pour moi

Réponses:


115

ÉDITER

Changé aspect='normalen aspect='auto'depuis que cela a changé dans les versions plus récentes de matplotlib (merci à @ Luke19).


En supposant :

import matplotlib.pyplot as plt

Pour faire une figure sans le cadre:

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

Pour que le contenu remplisse toute la figure

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

Dessinez ensuite votre image dessus:

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

Le aspectparamètre modifie la taille des pixels pour s'assurer qu'ils remplissent la taille de la figure spécifiée dans fig.set_size_inches(…). Pour avoir une idée de la façon de jouer avec ce genre de choses, lisez la documentation de matplotlib , en particulier sur le thème Axes, Axis et Artist.


4
non, j'ai encore une petite bordure transparente, et ce que je veux, ce n'est pas de bordure , une image pure
Jakub M.

5
Si vous définissez manuellement les paramètres wet hdans fig.set_size_inches(w,h)et le dpiparamètre dans de fig.savefig(fname, dpi)sorte qu'il en résulte 24px par 24px, cela devrait fonctionner correctement. Par exemple, w = h = 1etdpi = 24
matehat

5
J'ai dû combiner à la fois cette réponse et la réponse ci-dessous de Mostafa Pakparvar. Non seulement vous devez désactiver les axes, mais vous devez définir_visible sur false pour vous assurer que l'espace blanc disparaît. (wtf?)
Bryce Guinta

6
J'ai juste essayé ceci en utilisant matplotlib v2.2.2 et cela a fonctionné parfaitement (sauf que imshowla syntaxe de a changé à aspect='auto'au lieu de 'normal').
Luke19

2
C'est la bonne approche. ax = plt.Axes(fig, [0., 0., 1., 1.])est ce qui le fait fonctionner.
greatvovan

73

Une solution plus simple semble être:

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

2
Cela a très bien fonctionné pour moi. En outre, pad_inches peut être facilement changé à la taille souhaitée. Merci!
Curious2learn

27
J'ai toujours des marges blanches avec ça.
Fábio Perez

3
J'ai pu mettre à jour cela pour les versions plus récentes / le problème des marges restantes simplement en ajoutant transparent = True fig.savefig('out.png', bbox_inches='tight',transparent=True, pad_inches=0)
mdoc-2011

2
J'ai encore des axes et des coches et tout avec ceci :(
BjornW

3
Cela ne fait rien du tout. Il vous donnera la figure avec tous les axes et étiquettes.
1313e

27

Vous pouvez trouver la bbox de l'image à l'intérieur de l'axe (en utilisant get_window_extent), et utiliser le bbox_inchesparamètre pour enregistrer uniquement cette partie de l'image:

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)

J'ai appris cette astuce de Joe Kington ici .


6
juste plt.axis('off')aidé. Les autres réponses n'aident pas beaucoup.
imsrgadich

3
Cela a plutôt bien fonctionné. Cependant, dans mon cas, il y a encore une petite bordure blanche. Des idées sur la façon de supprimer cette frontière?
user3731622

@ user3731622, veuillez essayer à la plt.savefig('/temp/test.png', bbox_inches='tight', transparent=True, pad_inches=0)place deplt.savefig('/tmp/test.png', bbox_inches=extent)
Cloud Cho

17

J'ai essayé plusieurs options dans mon cas, et la meilleure solution était la suivante:

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

puis enregistrez votre silhouette avec savefig


1
De toutes ces solutions, c'est la seule qui a fonctionné pour moi.
Puff le

8

Je vais suggérer une réponse à heron13 avec un léger ajout emprunté à ici pour supprimer le rembourrage laissé après avoir mis la bbox en mode serré, donc:

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)

J'obtiens une erreur disant que get_xaxis () et get_yaxis () n'existent pas. Une idée de pourquoi cela arriverait?
Jacob Malachowski

Créez un objet axes (), puis utilisez ax.xaxis et ax.yaxis
perigon

Vous avez une erreur disant que l'objet 'list' n'a pas d'attribut 'get_xaxis'
Haozhe Xie

7

Celui-ci fonctionne pour moi

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

3

J'ai eu le même problème en faisant de la visualisation à l'aide de librosa où je voulais extraire le contenu de l'intrigue sans aucune autre information. Voilà donc mon approche. Unutbu answer m'aide aussi à me mettre au travail.

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

Cela m'a mis sur la bonne voie, mais j'ai eu deux problèmes: 1) J'ai dû régler le dpi sur un nombre supérieur à 1 pour éviter une erreur de police dans mon notebook jupyter; et 2) il y avait encore une petite bordure donc je dois changer manuellement l'étendue Bbox en extent.get_points()*np.array([[1.1],[.9]]).
Bob Baxley

merci pour l'accomplissement de la réponse qui peut aider quelqu'un d'autre.
GPrathap

3

Pour quiconque essaie de faire cela dans Jupyter

 plt.axis('off')

 spec = plt.imshow

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

2

Bien que les réponses ci-dessus traitent de la suppression des marges et du remplissage, elles n'ont pas fonctionné pour moi pour supprimer les étiquettes. Voici ce qui a fonctionné, pour quiconque tombe sur cette question plus tard:

En supposant que vous vouliez une grille 2x2 de sous-graphiques à partir de quatre images stockées dans 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

J'ai essayé de me débarrasser de la frontière aussi, en utilisant des conseils ici, mais rien n'a vraiment fonctionné. Certains bidouillages et j'ai trouvé que changer la couleur du visage ne me donnait pas de bordure dans les laboratoires Jupyter (toute couleur entraînait la suppression de la bordure blanche). J'espère que cela t'aides.

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

entrez la description de l'image ici



0

Pour moi, ce code a rendu similaire la taille de l'image d'entrée sans cadre et axes des codes matehat , unutbu et 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)

Environnement d'exécution:
Python 3.6.10
Matplotlib 3.2.1
OS Windows 10

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.