Entfernen von Leerzeichen um ein gespeichertes Bild in matplotlib

171

Ich muss ein Bild aufnehmen und es nach einiger Zeit speichern. Die Figur sieht gut aus, wenn ich sie anzeige, aber nach dem Speichern der Figur habe ich einen Leerraum um das gespeicherte Bild. Ich habe die 'tight'Option für savefigMethode ausprobiert , hat auch nicht funktioniert. Der 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()

Ich versuche, ein grundlegendes Diagramm mithilfe von NetworkX für eine Figur zu zeichnen und zu speichern. Ich habe festgestellt, dass es ohne Grafik funktioniert, aber wenn ich eine Grafik hinzufüge, bekomme ich einen Leerraum um das gespeicherte Bild.

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
quelle
Was für mich wirklich funktioniert hat, war, das PDF mit einem anderen Tool wie pdfcrop zuzuschneiden.
Toliveira

Antworten:

168

Ich kann nicht behaupten, dass ich genau weiß, warum oder wie meine „Lösung“ funktioniert, aber das musste ich tun, als ich den Umriss einiger Tragflächenabschnitte - ohne weiße Ränder - in eine PDF-Datei zeichnen wollte. (Beachten Sie, dass ich matplotlib in einem IPython-Notizbuch mit dem Flag -pylab verwendet habe.)

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)

Ich habe versucht, verschiedene Teile davon zu deaktivieren, aber dies führte immer irgendwo zu einem weißen Rand. Möglicherweise müssen Sie dies sogar ändern, um zu verhindern, dass fette Linien in der Nähe der Grenzen der Figur durch fehlende Ränder rasiert werden.

Johannes S.
quelle
6
Endlich etwas, das funktioniert, vielen Dank! Übrigens waren in meinem Fall nur die beiden verwendeten Zeilen set_major_locatornotwendig.
Florian Brucker
6
Ich habe die letzte Stunde damit verbracht, verschiedene Dinge auszuprobieren und konnte einen 1px weißen Rand nicht loswerden. Dies war das einzige, was funktionierte - insbesondere das, pad_inches=0was andere Antworten nicht erwähnen.
AnnanFay
1
set_major_locatorwar der Schlüssel für mich.
kmac
16
pad_incheshalf mir.
Myles Baker
5
matplotlib.ticker.NullLocator ()
Joop
200

Sie können den weißen Raum Polsterung entfernen , indem Sie bbox_inches="tight"in savefig:

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

Sie müssen das Argument bbox_inchesals Zeichenfolge verwenden. Vielleicht hat es deshalb bei Ihnen früher nicht funktioniert.


Mögliche Duplikate:

Matplotlib-Diagramme: Entfernen von Achsen, Legenden und Leerzeichen

Wie stelle ich die Ränder für eine Matplotlib-Figur ein?

Reduzieren Sie den linken und rechten Rand im Matplotlib-Plot

Süchtig
quelle
1
Wenn Sie mehrere Nebenhandlungen haben und jede von ihnen speichern möchten, können Sie diese auch mit verwenden fig.savefig(). ( plt.savefig()wird in diesem Fall nicht funktionieren.)
Abhranil Das
30
Das ist nicht ganz richtig. Wenn Sie diese bbox_inchesOption verwenden, gibt es einen anderen Standard, der etwas Platz lässt. Wenn Sie wirklich alles loswerden wollen, müssen Sie auch verwenden pad_inches=0.0. Natürlich schneidet solch eine enge Polsterung häufig ab, z. B. Exponenten ...
Mike
5
Um auch die schwarze Kante zu entfernen, müssen Sie möglicherweisepad_inches=-0.1
lenhhoxung
10
Das funktioniert einfach nicht, man bekommt immer noch Leerzeichen um die Figur. Das Einstellen der transparenten Option (wie in einigen Antworten erwähnt) hilft auch nicht wirklich, das Leerzeichen ist immer noch vorhanden, es ist nur transparent.
BjörnW
1
@piperchester das ist eine gute Frage, sollte aber wahrscheinlich als neue Frage gestellt werden, damit sie nicht in den Kommentaren verloren geht. Sie sollten die neue Frage jedoch mit der alten verknüpfen!
Hooked
20

Ich fand etwas von Arvind Pereira ( http://robotics.usc.edu/~ampereir/wordpress/?p=626 ) und schien für mich zu arbeiten:

plt.savefig(filename, transparent = True, bbox_inches = 'tight', pad_inches = 0)
unclerico
quelle
7
transparent=Truewird es so aussehen lassen, als gäbe es kein Problem, aber es wird nur Leerzeichen verbergen, Bildabmessungen werden nicht in Ordnung sein.
Vlady Veselinov
Danke fürs Erwähnen pad_inches! Ich wünschte, ich hätte früher von dieser Option gewusst!
ingomueller.net
1
Dies funktioniert für die meisten Diagramme, hat jedoch den rechten Rand für meine Verwirrungsmatrix entfernt. pad_inches=.25
Fügen Sie
20

Nachdem ich die obigen Antworten ohne Erfolg ausprobiert hatte (und eine Menge anderer Stapelpfosten), funktionierte das, was schließlich für mich funktionierte, einfach

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

Wichtig ist, dass dies nicht die Argumente bbox oder padding enthält.

SuaveSouris
quelle
4
Dies sollte die akzeptierte Antwort sein. Außerdem müssen Sie nicht einmal anrufen set_axis_off. Das gespeicherte Bild wird nicht beeinflusst, da subplots_adjustdie Achse außerhalb der Ausdehnung der Figur liegt und die Henne ohnehin nicht gezeichnet wird. In Jupyter-Notizbüchern müssen Sie die Achse jedoch explizit deaktivieren, da das Inline-Backend diese Einstellungen überschreibt.
MaxPowers
14

Die folgende Funktion enthält die obige Antwort von johannes. Ich habe es mit plt.figureund plt.subplots()mit mehreren Achsen getestet und es funktioniert gut.

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
quelle
Lief wie am Schnürchen. Die vorherige Antwort war einige erforderliche Befehle in meinem Export.
Kevin S
11

Ich fand, dass die folgenden Codes perfekt für den Job funktionieren.

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
quelle
2
Im Allgemeinen sind Antworten viel hilfreicher, wenn sie eine Erklärung enthalten, was der Code tun soll und warum dies das Problem löst, ohne andere einzuführen.
Tim Diekmann
7

Ich folgte dieser Sequenz und es funktionierte wie ein Zauber.

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
quelle
1
Eigentlich fand ich diese Antwort einfach und bequemer zu bedienen.
Sikisis
1
Dieser hat für mich gearbeitet; die akzeptierte Antwort nicht.
Joe
3

Für alle, die lieber in Pixel als in Zoll arbeiten möchten, funktioniert dies.

Plus das Übliche, das Sie auch brauchen werden

from matplotlib.transforms import Bbox

Dann können Sie Folgendes verwenden:

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)

Geben Sie hier die Bildbeschreibung ein

Simon Thomas
quelle
Sie müssen kein dpi angeben, fig.dpisondern können stattdessen das Standard-dpi verwenden
intsco
1

Ein viel einfacherer Ansatz, den ich gefunden habe, ist plt.imsave:

    import matplotlib.pyplot as plt
    arr = plt.imread(path)
    plt.imsave('test.png', arr)
Parth92
quelle
Unterschätzte Antwort. Dies half mir nach einer langen Suche, wie man die Auflösung beibehält und Leerzeichen mit entfernt plt.savefig().
Nihal111
Dies funktioniert nur, wenn Sie ein Array (!) Als Image speichern möchten. Dies erlaubt es nicht, eine beliebige Zahl zu speichern.
MaxPowers
Was meinst du mit willkürlichem Bild? Ist ein Bild nicht ein Array von Werten?
Parth92
-1

Wenn Sie anzeigen möchten, was gespeichert werden soll, empfehle ich die Verwendung der plt.tight_layoutTransformation, die eigentlich vorzuziehen ist, da bei der Verwendung kein unnötiges Zuschneiden erfolgtplt.savefig

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

Dies funktioniert für mich beim Speichern eines numpy-Arrays, das mit imshow to file gezeichnet wurde

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
quelle