Suppression d'espace blanc autour d'une image enregistrée dans matplotlib

172

J'ai besoin de prendre une image et de la sauvegarder après un certain processus. La figure semble correcte lorsque je l'affiche, mais après avoir sauvegardé la figure, j'ai obtenu un espace blanc autour de l'image enregistrée. J'ai essayé l' 'tight'option savefigméthode, cela n'a pas fonctionné non plus. Le code:

  import matplotlib.image as mpimg
  import matplotlib.pyplot as plt

  fig = plt.figure(1)
  img = mpimg.imread(path)
  plt.imshow(img)
  ax=fig.add_subplot(1,1,1)

  extent = ax.get_window_extent().transformed(fig.dpi_scale_trans.inverted())
  plt.savefig('1.png', bbox_inches=extent)

  plt.axis('off') 
  plt.show()

J'essaie de dessiner un graphique de base en utilisant NetworkX sur une figure et de l'enregistrer. Je me suis rendu compte que sans graphique, cela fonctionne, mais lors de l'ajout d'un graphique, j'obtiens un espace blanc autour de l'image enregistrée;

import matplotlib.image as mpimg
import matplotlib.pyplot as plt
import networkx as nx

G = nx.Graph()
G.add_node(1)
G.add_node(2)
G.add_node(3)
G.add_edge(1,3)
G.add_edge(1,2)
pos = {1:[100,120], 2:[200,300], 3:[50,75]}

fig = plt.figure(1)
img = mpimg.imread("C:\\images\\1.jpg")
plt.imshow(img)
ax=fig.add_subplot(1,1,1)

nx.draw(G, pos=pos)

extent = ax.get_window_extent().transformed(fig.dpi_scale_trans.inverted())
plt.savefig('1.png', bbox_inches = extent)

plt.axis('off') 
plt.show()
Ahmet Tuğrul Bayrak
la source
1
Copie
Joel
Ce qui a vraiment fonctionné pour moi, c'est de recadrer le pdf à l'aide d'un autre outil, tel que pdfcrop.
toliveira

Réponses:

170

Je ne peux pas prétendre savoir exactement pourquoi ou comment ma «solution» fonctionne, mais c'est ce que j'ai dû faire lorsque je voulais tracer le contour de quelques sections de voilure - sans marges blanches - dans un fichier PDF. (Notez que j'ai utilisé matplotlib dans un notebook IPython, avec l'indicateur -pylab.)

plt.gca().set_axis_off()
plt.subplots_adjust(top = 1, bottom = 0, right = 1, left = 0, 
            hspace = 0, wspace = 0)
plt.margins(0,0)
plt.gca().xaxis.set_major_locator(plt.NullLocator())
plt.gca().yaxis.set_major_locator(plt.NullLocator())
plt.savefig("filename.pdf", bbox_inches = 'tight',
    pad_inches = 0)

J'ai essayé de désactiver différentes parties de ceci, mais cela conduit toujours à une marge blanche quelque part. Vous pouvez même avoir modifié cela pour empêcher les lignes grasses proches des limites de la figure d'être rasées par le manque de marges.

Johannes S.
la source
6
Enfin quelque chose qui fonctionne, merci beaucoup! À propos, dans mon cas, seules les deux lignes utilisant set_major_locatorétaient nécessaires.
Florian Brucker
6
J'ai passé la dernière heure à essayer diverses choses et je n'ai pas pu me débarrasser d'une bordure blanche de 1px. C'était la seule chose qui fonctionnait - en particulier celle pad_inches=0que les autres réponses ne mentionnent pas.
AnnanFay
1
set_major_locatorétait la clé pour moi.
kmac
16
pad_inchesm'a aidé.
Myles Baker
5
matplotlib.ticker.NullLocator ()
Joop
201

Vous pouvez supprimer le remplissage des espaces blancs en définissant bbox_inches="tight"dans savefig:

plt.savefig("test.png",bbox_inches='tight')

Vous devrez mettre l'argument bbox_inchessous forme de chaîne, c'est peut-être pour cette raison que cela n'a pas fonctionné plus tôt pour vous.


Doublons possibles:

Graphiques Matplotlib: suppression des axes, des légendes et des espaces blancs

Comment définir les marges d'une figure matplotlib?

Réduisez les marges gauche et droite dans le tracé matplotlib

Accroché
la source
1
Si vous avez plusieurs sous-graphiques et que vous souhaitez enregistrer chacun d'eux, vous pouvez également l'utiliser avec fig.savefig(). ( plt.savefig()ne fonctionnera pas dans ce cas.)
Abhranil Das
30
Ce n'est pas tout à fait vrai. Lorsque vous utilisez cette bbox_inchesoption, il existe une autre valeur par défaut qui laisse un peu d'espace. Si vous voulez vraiment vous débarrasser de tout, vous devez également utiliser pad_inches=0.0. Bien sûr, un rembourrage aussi serré coupe fréquemment, par exemple, les exposants ...
Mike
5
Pour supprimer également le bord noir, vous devrez peut-être définirpad_inches=-0.1
lenhhoxung
10
Cela ne fonctionne tout simplement pas, vous obtenez toujours des espaces autour de la figure. La définition de l'option transparente (comme mentionné dans certaines réponses) n'aide pas vraiment non plus, l'espace blanc est toujours là, il n'est que transparent.
BjornW
1
@piperchester c'est une bonne question, mais devrait probablement être posée comme une nouvelle question pour qu'elle ne se perde pas dans les commentaires. Vous devriez cependant lier la nouvelle question à l'ancienne!
Accroché le
21

Après avoir essayé les réponses ci-dessus sans succès (et une multitude d'autres messages de pile), ce qui a finalement fonctionné pour moi était juste

plt.gca().set_axis_off()
plt.subplots_adjust(top = 1, bottom = 0, right = 1, left = 0, 
            hspace = 0, wspace = 0)
plt.margins(0,0)
plt.savefig("myfig.pdf")

Il est important de noter que cela n'inclut pas les arguments bbox ou padding.

SuaveSouris
la source
4
Cela devrait être la réponse acceptée. De plus, vous n'avez même pas besoin d'appeler set_axis_off. Cela n'affecte pas l'image enregistrée car une fois que subplots_adjustl'axe se trouve en dehors de l'étendue de la figure et que henve ne sera de toute façon pas tracé. Dans les blocs-notes Jupyter, cependant, vous devez désactiver explicitement l'axe, car le backend en ligne écrase ces paramètres.
MaxPowers
20

J'ai trouvé quelque chose d'Arvind Pereira ( http://robotics.usc.edu/~ampereir/wordpress/?p=626 ) et j'ai semblé fonctionner pour moi:

plt.savefig(filename, transparent = True, bbox_inches = 'tight', pad_inches = 0)
unclerico
la source
7
transparent=Truedonnera l'impression qu'il n'y a pas de problème, mais cela masquera simplement l'espace blanc, les dimensions de l'image ne seront pas correctes.
Vlady Veselinov
Merci d'avoir mentionné pad_inches! J'aurais aimé connaître cette option plus tôt!
ingomueller.net
1
Cela fonctionne pour la plupart des parcelles, mais cela a supprimé la bordure droite de ma matrice de confusion. Il suffit d'ajouter un petit rembourragepad_inches=.25
YTZ
14

La fonction suivante incorpore la réponse de johannes ci-dessus. Je l'ai testé avec plt.figureet plt.subplots()avec plusieurs axes, et cela fonctionne bien.

def save(filepath, fig=None):
    '''Save the current image with no whitespace
    Example filepath: "myfig.png" or r"C:\myfig.pdf" 
    '''
    import matplotlib.pyplot as plt
    if not fig:
        fig = plt.gcf()

    plt.subplots_adjust(0,0,1,1,0,0)
    for ax in fig.axes:
        ax.axis('off')
        ax.margins(0,0)
        ax.xaxis.set_major_locator(plt.NullLocator())
        ax.yaxis.set_major_locator(plt.NullLocator())
    fig.savefig(filepath, pad_inches = 0, bbox_inches='tight')
TomNorway
la source
A travaillé comme un charme. La réponse précédente était quelques commandes requises dans mon exportation.
Kevin S le
11

J'ai trouvé que les codes suivants fonctionnent parfaitement pour le travail.

fig = plt.figure(figsize=[6,6])
ax = fig.add_subplot(111)
ax.imshow(data)
ax.axes.get_xaxis().set_visible(False)
ax.axes.get_yaxis().set_visible(False)
ax.set_frame_on(False)
plt.savefig('data.png', dpi=400, bbox_inches='tight',pad_inches=0)
Richard Yu Liu
la source
2
En général, les réponses sont beaucoup plus utiles si elles incluent une explication de ce que le code est censé faire et pourquoi cela résout le problème sans en présenter d'autres.
Tim Diekmann
7

J'ai suivi cette séquence et cela a fonctionné comme un charme.

plt.axis("off")
fig=plt.imshow(image array,interpolation='nearest')
fig.axes.get_xaxis().set_visible(False)
fig.axes.get_yaxis().set_visible(False)
plt.savefig('destination_path.pdf',
    bbox_inches='tight', pad_inches=0, format='pdf', dpi=1200)
Khan
la source
1
En fait, j'ai trouvé que cette réponse était facile et plus pratique à utiliser.
sikisis
1
Celui-ci a fonctionné pour moi; pas la réponse acceptée.
Joe
3

Pour tous ceux qui souhaitent travailler en pixels plutôt qu'en pouces, cela fonctionnera.

De plus, vous aurez également besoin de l'habituel

from matplotlib.transforms import Bbox

Ensuite, vous pouvez utiliser ce qui suit:

my_dpi = 100 # Good default - doesn't really matter

# Size of output in pixels
h = 224
w = 224

fig, ax = plt.subplots(1, figsize=(w/my_dpi, h/my_dpi), dpi=my_dpi)

ax.set_position([0, 0, 1, 1]) # Critical!

# Do some stuff
ax.imshow(img)
ax.imshow(heatmap) # 4-channel RGBA
ax.plot([50, 100, 150], [50, 100, 150], color="red")

ax.axis("off")

fig.savefig("saved_img.png",
            bbox_inches=Bbox([[0, 0], [w/my_dpi, h/my_dpi]]),
            dpi=my_dpi)

entrez la description de l'image ici

Simon Thomas
la source
Vous n'avez pas à spécifier de dpi, vous pouvez utiliser la valeur par défaut à la fig.dpiplace
intsco
1

Une approche beaucoup plus simple que j'ai trouvée consiste à utiliser plt.imsave:

    import matplotlib.pyplot as plt
    arr = plt.imread(path)
    plt.imsave('test.png', arr)
Parth92
la source
Réponse sous-estimée. Cela m'a aidé après une longue recherche sur la façon de conserver la résolution et de supprimer les espaces avec plt.savefig().
nihal111
Cela ne fonctionne que si vous souhaitez enregistrer un tableau (!) En tant qu'image. Cela ne permet pas d'enregistrer un chiffre arbitraire.
MaxPowers
Qu'entendez-vous par image arbitraire? Une image n'est-elle pas un tableau de valeurs?
Parth92
0

Vous pouvez essayer ceci. Cela a résolu mon problème.

import matplotlib.image as mpimg
img = mpimg.imread("src.png")
mpimg.imsave("out.png", img, cmap=cmap)
user1410665
la source
0

Cela a fonctionné pour moi plt.savefig(save_path,bbox_inches='tight', pad_inches=0, transparent=True)

Mohammed
la source
Je ne suis pas sûr que ce soit différent des autres réponses publiées ici.
BigBen
-1

Si vous souhaitez afficher ce qui doit être enregistré, je vous recommande d'utiliser la plt.tight_layouttransformation qui est en fait plus préférable car elle ne fait pas de recadrage inutile lors de l'utilisationplt.savefig

import matplotlib as plt    
plt.plot([1,2,3], [1,2,3])
plt.tight_layout(pad=0)
plt.savefig('plot.png')
Keto
la source
-4

Cela fonctionne pour moi en enregistrant un tableau numpy tracé avec imshow to file

import matplotlib.pyplot as plt

fig = plt.figure(figsize=(10,10))
plt.imshow(img) # your image here
plt.axis("off")
plt.subplots_adjust(top = 1, bottom = 0, right = 1, left = 0, 
        hspace = 0, wspace = 0)
plt.savefig("example2.png", box_inches='tight', dpi=100)
plt.show()
Alejandro Sazo
la source