scipy: savefig ohne Frames, Achsen, nur Inhalt

89

In numpy / scipy habe ich ein Bild in einem Array gespeichert. Ich kann es anzeigen, ich möchte es savefig ohne Ränder, Achsen, Beschriftungen, Titel usw. speichern. Nur reines Bild, sonst nichts.

Ich möchte Pakete wie PyPNGoder vermeiden scipy.misc.imsave, sie sind manchmal problematisch (sie lassen sich nicht immer gut installieren, nur grundlegend savefig()für mich

Jakub M.
quelle

Antworten:

113

BEARBEITEN

Geändert aspect='normalzu aspect='auto'seitdem geändert in neueren Versionen von matplotlib (danke an @ Luke19).


Angenommen:

import matplotlib.pyplot as plt

So machen Sie eine Figur ohne Rahmen:

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

Damit der Inhalt die ganze Figur ausfüllt

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

Dann zeichnen Sie Ihr Bild darauf:

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

Der aspectParameter ändert die Pixelgröße, um sicherzustellen, dass sie die in angegebene Größengröße ausfüllt fig.set_size_inches(…). Um ein Gefühl dafür zu bekommen, wie man mit solchen Dingen spielt, lesen Sie die Dokumentation von matplotlib , insbesondere zum Thema Axes , Axis und Artist.

matehat
quelle
4
Nein, ich habe immer noch einen kleinen transparenten Rand, und was ich will, ist überhaupt kein Rand , reines Bild
Jakub M.
5
Wenn Sie die Parameter wund hin fig.set_size_inches(w,h)und den dpiParameter manuell so einstellen fig.savefig(fname, dpi), dass sie 24 x 24 Pixel groß sind, sollte dies einwandfrei funktionieren. Zum Beispiel w = h = 1unddpi = 24
matehat
5
Ich musste sowohl diese Antwort als auch die Antwort von Mostafa Pakparvar unten kombinieren. Sie müssen nicht nur die Achsen ausschalten, sondern auch set_visible auf false setzen, um sicherzustellen, dass der Leerraum verschwindet. (wtf?)
Bryce Guinta
6
Ich habe es gerade mit matplotlib v2.2.2 versucht und es hat perfekt funktioniert (außer dass imshowdie Syntax von aspect='auto'anstelle von geändert wurde 'normal').
Luke19
2
Dies ist der richtige Ansatz. ax = plt.Axes(fig, [0., 0., 1., 1.])ist es, was es funktioniert.
Greatvovan
73

Eine einfachere Lösung scheint zu sein:

fig.savefig('out.png', bbox_inches='tight', pad_inches=0)
Wetterfrosch
quelle
2
Das hat für mich super geklappt. Außerdem können pad_inches einfach auf die gewünschte Größe geändert werden. Vielen Dank!
Curious2learn
25
Ich habe immer noch weiße Ränder damit.
Fábio Perez
3
Ich konnte dies für neuere Versionen / verbleibende fig.savefig('out.png', bbox_inches='tight',transparent=True, pad_inches=0)
Randprobleme
2
Habe noch Äxte und Häkchen und alles damit :(
BjörnW
3
Das macht überhaupt nichts. Sie erhalten die Figur mit allen Achsen und Beschriftungen.
1313e
27

Sie können die bbox des Bildes innerhalb der Achse finden (mit get_window_extent) und den bbox_inchesParameter verwenden, um nur den Teil des Bildes zu speichern:

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)

Diesen Trick habe ich hier von Joe Kington gelernt .

unutbu
quelle
6
hat nur plt.axis('off')geholfen. Andere Antworten helfen nicht viel.
Imsrgadich
3
Das hat ziemlich gut funktioniert. In meinem Fall gibt es jedoch immer noch einen kleinen weißen Rand. Irgendwelche Ideen, wie man diese Grenze entfernt?
user3731622
@ user3731622, bitte versuchen Sie es plt.savefig('/temp/test.png', bbox_inches='tight', transparent=True, pad_inches=0)stattplt.savefig('/tmp/test.png', bbox_inches=extent)
Cloud Cho
17

Ich habe in meinem Fall mehrere Optionen ausprobiert, und die beste Lösung war folgende:

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

dann speichere deine Figur mit savefig

Cagri Sarigoz
quelle
1
Von all diesen Lösungen ist dies die einzige, die für mich funktioniert hat.
Puff
8

Ich werde eine Antwort von heron13 mit einem kleinen Zusatz vorschlagen, der von hier entlehnt wurde , um die Polsterung zu entfernen, die nach dem Einstellen der bbox in den engen Modus übrig bleibt.

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)
Mostafa Pakparvar
quelle
Ich erhalte die Fehlermeldung, dass get_xaxis () und get_yaxis () nicht vorhanden sind. Irgendeine Idee, warum das passieren würde?
Jacob Malachowski
Machen Sie ein axes () Objekt und verwenden Sie dann ax.xaxis und ax.yaxis
perigon
Ich habe eine Fehlermeldung erhalten, dass das Objekt 'list' kein Attribut 'get_xaxis' hat
Haozhe Xie
7

Dieser arbeitet für mich

plt.savefig('filename',bbox_inches='tight',transparent=True, pad_inches=0)
Cathy Yang
quelle
3

Ich hatte das gleiche Problem bei der Visualisierung mit librosa, bei der ich den Inhalt der Handlung ohne weitere Informationen extrahieren wollte. Das ist also mein Ansatz. unutbu Antwort hilft mir auch, zur Arbeit zu bringen.

    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()
GPrathap
quelle
Dies brachte mich auf den richtigen Weg, aber ich hatte zwei Probleme: 1) Ich musste die dpi auf eine Zahl größer als 1 einstellen, um einen Schriftfehler in meinem Jupyter-Notizbuch zu vermeiden; und 2) es gab noch einen kleinen Rand, so dass ich das Ausmaß der Bbox manuell ändern muss extent.get_points()*np.array([[1.1],[.9]]).
Bob Baxley
Vielen Dank für die Erfüllung der Antwort, die jemand anderem helfen kann.
GPrathap
3

Für alle, die dies in Jupyter versuchen

 plt.axis('off')

 spec = plt.imshow

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

Während die obigen Antworten das Entfernen von Rändern und Auffüllen betreffen, haben sie beim Entfernen von Etiketten bei mir nicht funktioniert. Folgendes hat funktioniert, für alle, die später auf diese Frage stoßen:

Angenommen, Sie möchten ein 2x2-Raster mit Nebenhandlungen aus vier Bildern, die in imagesfolgenden Dateien gespeichert sind :

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')
neugierig
quelle
1

Ich habe auch versucht, die Grenze loszuwerden, indem ich hier Tipps verwendet habe, aber nichts hat wirklich funktioniert. Ein bisschen herumgespielt und ich fand, dass das Ändern der Gesichtsfarbe mir in Jupyter-Labors keinen Rand gab (jede Farbe führte dazu, dass der weiße Rand entfernt wurde). Hoffe das hilft.

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

Geben Sie hier die Bildbeschreibung ein

Atom Scott
quelle
0

Für mich hat dieser Code die Größe des Eingabebildes ohne Rahmen und Achsen aus den Codes matehat , unutbu und WHZW ähnlich gemacht :

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)

Laufzeitumgebung:
Python 3.6.10
Matplotlib 3.2.1
OS Windows 10

Cloud Cho
quelle