Rimozione di spazi bianchi attorno a un'immagine salvata in matplotlib


172

Devo prendere un'immagine e salvarla dopo qualche processo. La figura sembra a posto quando la visualizzo, ma dopo aver salvato la figura, ho ottenuto uno spazio bianco attorno all'immagine salvata. Ho provato l' 'tight'opzione per il savefigmetodo, non ha funzionato neanche. Il codice:

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

Sto cercando di tracciare un grafico di base usando NetworkX su una figura e salvarlo. Mi sono reso conto che senza grafico funziona, ma quando aggiunto un grafico ottengo uno spazio bianco attorno all'immagine salvata;

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


Quello che ha funzionato davvero per me è stato ritagliare il pdf usando un altro strumento, come pdfcrop.
toliveira,

Risposte:


170

Non posso affermare di sapere esattamente perché o come funziona la mia "soluzione", ma questo è quello che dovevo fare quando volevo tracciare il contorno di un paio di sezioni di profilo alare - senza margini bianchi - in un file PDF. (Nota che ho usato matplotlib all'interno di un notebook IPython, con il flag -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)

Ho provato a disattivare diverse parti di questo, ma questo porta sempre a un margine bianco da qualche parte. Potresti anche averlo modificato per evitare che le linee grasse vicino ai limiti della figura vengano rasate dalla mancanza di margini.


6
Finalmente qualcosa che funziona, grazie mille! A proposito, nel mio caso set_major_locatorerano necessarie solo le due linee .
Florian Brucker,

6
Ho trascorso l'ultima ora a provare varie cose e non sono riuscito a liberarmi di un bordo bianco da 1px. Questa è stata l'unica cosa che ha funzionato, in particolare le pad_inches=0altre risposte che non menzionano.
AnnanFay,

1
set_major_locatorera la chiave per me.
kmac,

16
pad_inchesmi ha aiutato.
Myles Baker,

5
matplotlib.ticker.NullLocator ()
Joop

200

È possibile rimuovere il riempimento degli spazi bianchi impostando bbox_inches="tight"in savefig:

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

Dovrai mettere l'argomento bbox_inchescome una stringa, forse è per questo che non ha funzionato prima per te.


Possibili duplicati:

Grafici matplotlib: rimozione di assi, legende e spazi bianchi

Come impostare i margini per una figura matplotlib?

Riduci i margini sinistro e destro nel grafico matplotlib


1
Se si dispone di più sottotrame e si desidera salvare ciascuno di essi, è possibile utilizzare anche questo fig.savefig(). ( plt.savefig()non funzionerà in quel caso.)
Abhranil Das

30
Non è del tutto esatto. Quando usi bbox_inchesquell'opzione, c'è un altro valore predefinito che lascia spazio. Se vuoi davvero sbarazzarti di tutto, devi anche usare pad_inches=0.0. Naturalmente, un'imbottitura così stretta spesso interrompe, ad esempio, esponenti ...
Mike,

5
Per rimuovere anche il bordo nero, potrebbe essere necessario impostarepad_inches=-0.1
lenhhoxung,

10
Questo semplicemente non funziona, ottieni comunque spazi bianchi attorno alla figura. L'impostazione dell'opzione trasparente (come menzionato in alcune risposte) non aiuta davvero, lo spazio bianco è ancora lì, è solo trasparente.
BjornW

1
@piperchester è una buona domanda, ma probabilmente dovrebbe essere posta come una nuova domanda del tutto in modo da non perdersi nei commenti. Dovresti collegare la nuova domanda a quella vecchia!
Agganciato il

21

Dopo aver provato le risposte di cui sopra senza successo (e una serie di altri post dello stack) quello che alla fine ha funzionato per me è stato giusto

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

È importante sottolineare che questo non include gli argomenti bbox o padding.


4
Questa dovrebbe essere la risposta accettata. Inoltre, non è nemmeno necessario chiamare set_axis_off. Non influisce sull'immagine salvata poiché dopo che subplots_adjustl'asse si trova al di fuori dell'estensione della figura e che comunque non verrà individuato. Nei notebook Jupyter, tuttavia, è necessario disabilitare esplicitamente l'asse, poiché il back-end in linea sovrascrive queste impostazioni.
MaxPowers

20

Ho trovato qualcosa da Arvind Pereira ( http://robotics.usc.edu/~ampereir/wordpress/?p=626 ) e sembrava funzionare per me:

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

7
transparent=Truesembrerà che non ci siano problemi ma nasconderà solo uno spazio bianco, le dimensioni dell'immagine non andranno bene.
Vlady Veselinov,

Grazie per averlo menzionato pad_inches! Vorrei aver saputo di questa opzione prima!
ingomueller.net,

1
Questo funziona per la maggior parte dei grafici, ma ha rimosso il bordo giusto per la mia matrice di confusione. Basta aggiungere una piccola imbottiturapad_inches=.25
YTZ

14

La seguente funzione incorpora la risposta di johannes sopra. L'ho testato con plt.figuree plt.subplots()con più assi e funziona bene.

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

Ha funzionato come un fascino. La risposta precedente era alcuni comandi richiesti nella mia esportazione.
Kevin S,

11

Ho scoperto che i seguenti codici funzionano perfettamente per il lavoro.

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)

2
In generale, le risposte sono molto più utili se includono una spiegazione di ciò che il codice è destinato a fare e perché risolve il problema senza introdurre altri.
Tim Diekmann,

7

ho seguito questa sequenza e ha funzionato come un fascino.

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)

1
In realtà, ho trovato questa risposta facile e più comoda da usare.
Sikisis

1
Questo ha funzionato per me; la risposta accettata no.
Joe,

3

Per chiunque voglia lavorare in pixel anziché in pollici questo funzionerà.

Inoltre avrai anche il solito

from matplotlib.transforms import Bbox

Quindi è possibile utilizzare quanto segue:

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)

inserisci qui la descrizione dell'immagine


Non è necessario specificare dpi, è possibile utilizzare quella di default fig.dpi, invece
intsco

1

Un approccio molto più semplice che ho trovato è usare plt.imsave:

    import matplotlib.pyplot as plt
    arr = plt.imread(path)
    plt.imsave('test.png', arr)

Risposta sottovalutata. Questo mi ha aiutato dopo una lunga ricerca su come mantenere la risoluzione e rimuovere gli spazi bianchi con plt.savefig().
nihal111,

Funziona solo nel caso in cui desideri salvare un array (!) Come immagine. Ciò non consente di salvare una cifra arbitraria.
MaxPowers,

Cosa intendi per immagine arbitraria? Un'immagine non è una matrice di valori?
Parth92,

0

Puoi provare questo. Ha risolto il mio problema.

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

-1

Se si desidera visualizzare ciò che deve essere salvato, si consiglia di utilizzare la plt.tight_layouttrasformazione che è in realtà più preferibile in quanto non esegue ritagli non necessari quando si utilizzaplt.savefig

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

-4

Questo funziona per me salvando un array intorpidito tracciato con imshow su 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()
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.