it-swarm.com.de

Matplotlib-Diagramme: Entfernen von Achsen, Legenden und Leerzeichen

Ich bin neu in Python und Matplotlib. Ich möchte einfach eine Farbkarte auf ein Bild anwenden und das resultierende Bild schreiben, ohne Achsen, Beschriftungen, Titel oder andere Elemente zu verwenden, die normalerweise automatisch von Matplotlib hinzugefügt werden. Folgendes habe ich getan:

def make_image(inputname,outputname):
    data = mpimg.imread(inputname)[:,:,0]
    fig = plt.imshow(data)
    fig.set_cmap('hot')
    fig.axes.get_xaxis().set_visible(False)
    fig.axes.get_yaxis().set_visible(False)
    plt.savefig(outputname)

Die Achse der Figur wird erfolgreich entfernt, die gespeicherte Figur weist jedoch einen weißen Rand und einen Rahmen um das eigentliche Bild auf. Wie kann ich sie entfernen (zumindest die weiße Polsterung)? Vielen Dank

226
sunmat

Ich denke, dass der Befehl axis('off') eines der Probleme präziser löst, als jede Achse und den Rand einzeln zu ändern. Der weiße Raum um die Grenze bleibt jedoch erhalten. Das Hinzufügen von bbox_inches='tight' zum Befehl savefig bringt Sie fast ans Ziel. Im folgenden Beispiel sehen Sie, dass der verbleibende Leerraum viel kleiner, aber immer noch vorhanden ist.

Beachten Sie, dass neuere Versionen von matplotlib möglicherweise bbox_inches=0 anstelle der Zeichenfolge 'tight' erfordern (über @episodeyang und @kadrach).

from numpy import random
import matplotlib.pyplot as plt

data = random.random((5,5))
img = plt.imshow(data, interpolation='nearest')
img.set_cmap('hot')
plt.axis('off')
plt.savefig("test.png", bbox_inches='tight')

enter image description here

303
Hooked

Ich habe diesen Trick gelernt von Kumpel, hier :

import matplotlib.pyplot as plt
import numpy as np

def make_image(data, outputname, size=(1, 1), dpi=80):
    fig = plt.figure()
    fig.set_size_inches(size)
    ax = plt.Axes(fig, [0., 0., 1., 1.])
    ax.set_axis_off()
    fig.add_axes(ax)
    plt.set_cmap('hot')
    ax.imshow(data, aspect='equal')
    plt.savefig(outputname, dpi=dpi)

# data = mpimg.imread(inputname)[:,:,0]
data = np.arange(1,10).reshape((3, 3))

make_image(data, '/tmp/out.png')

ausbeuten

enter image description here

91
unutbu

Möglichst einfachste Lösung:

Ich habe einfach die in der Frage beschriebene Methode und die Methode aus der Antwort von Hooked kombiniert.

fig = plt.imshow(my_data)
plt.axis('off')
fig.axes.get_xaxis().set_visible(False)
fig.axes.get_yaxis().set_visible(False)
plt.savefig('pict.png', bbox_inches='tight', pad_inches = 0)

Nach diesem Code gibt es keine Leerzeichen und keinen Frame.

No whitespaces, axes or frame

46
Domagoj

Niemand erwähnte imsave , was dies zu einem Einzeiler macht:

import matplotlib.pyplot as plt
import numpy as np

data = np.arange(10000).reshape((100, 100))
plt.imsave("/tmp/foo.png", data, format="png", cmap="hot")

Es speichert das Bild direkt so, wie es ist, d. H. Es werden keine Achsen oder Rahmen/Auffüllungen hinzugefügt.

enter image description here

25
luator

Sie können den Umfang der Abbildung auch mit dem Argument bbox_inches angeben. Dies würde die weiße Polsterung um die Figur loswerden.

def make_image(inputname,outputname):
    data = mpimg.imread(inputname)[:,:,0]
    fig = plt.imshow(data)
    fig.set_cmap('hot')
    ax = fig.gca()
    ax.set_axis_off()
    ax.autoscale(False)
    extent = ax.get_window_extent().transformed(plt.gcf().dpi_scale_trans.inverted())
    plt.savefig(outputname, bbox_inches=extent)
9

Dies sollte alle Auffüllungen und Ränder entfernen:

from matplotlib import pyplot as plt

fig = plt.figure()
fig.patch.set_visible(False)

ax = fig.add_subplot(111)

plt.axis('off')
plt.imshow(data)

extent = ax.get_window_extent().transformed(fig.dpi_scale_trans.inverted())
plt.savefig("../images/test.png", bbox_inches=extent)
6
Vlady Veselinov

Ich mochte buntu's Antwort, aber es wurde nicht explizit gezeigt, wie die Größe für nicht quadratische Bilder im Auslieferungszustand eingestellt wird, so dass ich sie für einfaches Kopieren und Einfügen modifizierte:

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

def save_image_fix_dpi(data, dpi=100):
    shape=np.shape(data)[0:2][::-1]
    size = [float(i)/dpi for i in shape]

    fig = plt.figure()
    fig.set_size_inches(size)
    ax = plt.Axes(fig,[0,0,1,1])
    ax.set_axis_off()
    fig.add_axes(ax)
    ax.imshow(data)
    fig.savefig('out.png', dpi=dpi)
    plt.show()

Das Speichern von Bildern ohne Rand ist unabhängig von der gewählten Auflösung einfach, wenn pixel_size/dpi = size beibehalten wird.

data = mpimg.imread('test.png')
save_image_fix_dpi(data, dpi=100)

enter image description here

Die Anzeige ist jedoch gruselig. Wenn Sie eine kleine Auflösung wählen, kann das Bild größer sein als der Bildschirm, und Sie erhalten während der Anzeige einen Rand. Das Speichern bleibt davon jedoch unberührt.

So für

save_image_fix_dpi(data, dpi=20)

Die Anzeige wird umrandet (aber das Speichern funktioniert): enter image description here

2
csnemes

Erstens können Sie für bestimmte Bildformate (d. H. TIFF ) die Farbkarte in der Kopfzeile speichern, und die meisten Betrachter zeigen Ihre Daten mit der Farbkarte an.

Um ein aktuelles matplotlib Bild zu speichern, das nützlich sein kann, um Anmerkungen oder andere Daten zu Bildern hinzuzufügen, habe ich die folgende Lösung verwendet:

fig, ax = plt.subplots(figsize=inches)
ax.matshow(data)  # or you can use also imshow
# add annotations or anything else
# The code below essentially moves your plot so that the upper
# left hand corner coincides with the upper left hand corner
# of the artist
fig.subplots_adjust(left=0, right=1, top=1, bottom=0, wspace=0, hspace=0)
# now generate a Bbox instance that is the same size as your
# single axis size (this bbox will only encompass your figure)
bbox = matplotlib.transforms.Bbox(((0, 0), inches))
# now you can save only the part of the figure with data
fig.savefig(savename, bbox_inches=bbox, **kwargs)
1
David Hoffman

Vielen Dank für die tollen Antworten von allen ... Ich hatte genau das gleiche Problem mit dem Wunsch, nur ein Bild ohne zusätzliche Polsterung/Platz usw. zu zeichnen.

Abgesehen von einem Bild ohne Auffüllung wollte ich auch in der Lage sein, Anmerkungen usw. einfach hinzuzufügen, über nur eine einfache Bilddarstellung hinaus.

Am Ende habe ich Davids Antwort mit csnemes ' kombiniert, um beim Erstellen der Figur einen einfachen Wrapper zu erstellen. Wenn Sie das benutzen, brauchen Sie später keine Änderungen mehr mit imsave () oder irgendetwas anderem:

def get_img_figure(image, dpi):
    """
    Create a matplotlib (figure,axes) for an image (numpy array) setup so that
        a) axes will span the entire figure (when saved no whitespace)
        b) when saved the figure will have the same x/y resolution as the array, 
           with the dpi value you pass in.

    Arguments:
        image -- numpy 2d array
        dpi -- dpi value that the figure should use

    Returns: (figure, ax) Tuple from plt.subplots
    """

    # get required figure size in inches (reversed row/column order)
    inches = image.shape[1]/dpi, image.shape[0]/dpi

    # make figure with that size and a single axes
    fig, ax = plt.subplots(figsize=inches, dpi=dpi)

    # move axes to span entire figure area
    fig.subplots_adjust(left=0, right=1, top=1, bottom=0, wspace=0, hspace=0)

    return fig, ax
0
Richard

Alle alten Antworten funktionieren nicht mehr. Sie müssen bbox_inches=0 verwenden, damit es funktioniert.

from numpy import random
import matplotlib.pyplot as plt

data = random.random((5,5))
img = plt.imshow(data, interpolation='nearest')
img.set_cmap('hot')
plt.axis('off')
plt.savefig("test.png", bbox_inches=0)# <= this is where the difference is for newer maptlotlib.

Alternativ könnten Sie verwenden

plt.savefig("test.png", bbox_inches=None)

Ob dieses Schlüsselwortargument vorhanden ist, spielt eine Rolle, da die Art und Weise, wie matplotlib mit optionalen Schlüsselwörtern umgeht.

Dies wurde mit Version 3.0.3 am 19.06.2019 getestet.

0
episodeyang

Die upvoted Antwort funktioniert nicht mehr. Damit es funktioniert, müssen Sie manuell eine Achse hinzufügen, die auf [0, 0, 1, 1] eingestellt ist, oder das in der Abbildung dargestellte Patch entfernen.

import matplotlib.pyplot as plt

fig = plt.figure(figsize=(5, 5), dpi=20)
ax = plt.Axes(fig, [0., 0., 1., 1.])
fig.add_axes(ax)
plt.imshow([[0, 1], [0.5, 0]], interpolation="nearest")
plt.axis('off')                                # same as: ax.set_axis_off()

plt.savefig("test.png")

Alternativ können Sie den Patch auch einfach entfernen. Sie müssen keine Unterzeichnung hinzufügen, um die Füllungen zu entfernen. Dies ist vereinfacht durch Vladys Antwort unten

fig = plt.figure(figsize=(5, 5))
fig.patch.set_visible(False)                   # turn off the patch

plt.imshow([[0, 1], [0.5, 0]], interpolation="nearest")
plt.axis('off')

plt.savefig("test.png", cmap='hot')

Dies wurde mit Version 3.0.3 am 19.06.2019 getestet. Bild siehe unten:

enter image description here

Es ist viel einfacher, pyplot.imsave zu verwenden. Für Details, siehe Antwort des Luators unten

0
episodeyang