3235 Stimmen

Wie kann man die Größe der mit Matplotlib gezeichneten Figuren ändern?

Wie kann man die Größe einer mit Matplotlib gezeichneten Figur ändern?

43voto

Blairg23 Punkte 9968

Das funktioniert bei mir gut:

from matplotlib import pyplot as plt

F = plt.gcf()
Size = F.get_size_inches()
F.set_size_inches(Size[0]*2, Size[1]*2, forward=True) # Set forward to True to resize window along with plot in figure.
plt.show() # Or plt.imshow(z_array) if using an animation, where z_array is a matrix or NumPy array

Dieser Forumsbeitrag könnte ebenfalls hilfreich sein: Größenänderung der Abbildung Fenster

0 Stimmen

Die Größenänderung des Fensters hat bei mir nicht funktioniert. Es sah so aus, als ob forward=True der Schlüssel war, aber es hat das Problem nicht gelöst. Wie sich herausstellte, hat es das Problem behoben, ich musste nur auf die Reihenfolge achten, in der set_size_inches aufgerufen wurde. Es musste nach dem Aufruf von tight_layout() aufgerufen werden. Ich hatte dieses Problem mit einem axes.bar-Plot, nicht aber mit normalen Plots.

37voto

Vergleich verschiedener Ansätze zur Festlegung exakter Bildgrößen in Pixeln

Diese Antwort wird sich auf folgende Punkte konzentrieren:

  • savefig : Speichern in einer Datei, nicht nur Anzeige auf dem Bildschirm
  • Einstellung der Größe in Pixeln

Hier ist ein schneller Vergleich einiger der Ansätze, die ich ausprobiert habe, mit Bildern, die zeigen, was sie ergeben.

Zusammenfassung des aktuellen Status: Die Dinge sind chaotisch, ich bin mir nicht sicher, ob es sich um eine grundsätzliche Einschränkung handelt, oder ob der Anwendungsfall einfach nicht genug Aufmerksamkeit von den Entwicklern bekommen hat, ich konnte nicht leicht eine Upstream-Diskussion darüber finden.

Grundlegendes Beispiel, ohne dass versucht wird, die Bildabmessungen festzulegen

Nur um einen Vergleichspunkt zu haben:

base.py

#!/usr/bin/env python3

import sys

import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl

fig, ax = plt.subplots()
print('fig.dpi = {}'.format(fig.dpi))
print('fig.get_size_inches() = ' + str(fig.get_size_inches())
t = np.arange(-10., 10., 1.)
plt.plot(t, t, '.')
plt.plot(t, t**2, '.')
ax.text(0., 60., 'Hello', fontdict=dict(size=25))
plt.savefig('base.png', format='png')

laufen:

./base.py
identify base.png

Ausgänge:

fig.dpi = 100.0
fig.get_size_inches() = [6.4 4.8]
base.png PNG 640x480 640x480+0+0 8-bit sRGB 13064B 0.000u 0:00.000

enter image description here

Mein bisher bester Ansatz: plt.savefig(dpi=h/fig.get_size_inches()[1] reine Höhensteuerung

Ich denke, dass ich mich meistens für diese Variante entscheiden werde, da sie einfach und maßstabsgetreu ist:

get_size.py

#!/usr/bin/env python3

import sys

import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl

height = int(sys.argv[1])
fig, ax = plt.subplots()
t = np.arange(-10., 10., 1.)
plt.plot(t, t, '.')
plt.plot(t, t**2, '.')
ax.text(0., 60., 'Hello', fontdict=dict(size=25))
plt.savefig(
    'get_size.png',
    format='png',
    dpi=height/fig.get_size_inches()[1]
)

laufen:

./get_size.py 431

Ausgänge:

get_size.png PNG 574x431 574x431+0+0 8-bit sRGB 10058B 0.000u 0:00.000

enter image description here

y

./get_size.py 1293

Ausgänge:

main.png PNG 1724x1293 1724x1293+0+0 8-bit sRGB 46709B 0.000u 0:00.000

enter image description here

Ich neige dazu, nur die Höhe einzustellen, weil ich mir normalerweise am meisten Sorgen darüber mache, wie viel vertikalen Platz das Bild in der Mitte meines Textes einnehmen wird.

plt.savefig(bbox_inches='tight' ändert die Bildgröße

Ich habe immer das Gefühl, dass zu viel weißer Raum um die Bilder herum vorhanden ist, und neige dazu, die bbox_inches='tight' von: Entfernen von Leerraum um ein gespeichertes Bild

Dabei wird das Bild jedoch beschnitten, und Sie erhalten damit nicht die gewünschten Größen.

Stattdessen scheint dieser andere Ansatz, der in derselben Frage vorgeschlagen wurde, gut zu funktionieren:

plt.tight_layout(pad=1)
plt.savefig(...

was bei einer Höhe von 431 genau die gewünschte Höhe ergibt:

enter image description here

Feste Höhe, set_aspect , automatisch angepasste Breite und kleine Ränder

Hmmm, set_aspect bringt die Dinge wieder durcheinander und verhindert plt.tight_layout Das ist ein wichtiger Anwendungsfall, für den ich noch keine gute Lösung habe.

Nachgefragt bei: Wie man eine feste Höhe in Pixel, feste Daten x/y-Seitenverhältnis zu erhalten und automatisch entfernen entfernen horizontalen Leerzeichen Rand in Matplotlib?

plt.savefig(dpi=h/fig.get_size_inches()[1] + Breitensteuerung

Wenn Sie neben der Höhe auch eine bestimmte Breite benötigen, scheint dies gut zu funktionieren:

Breite.py

#!/usr/bin/env python3

import sys

import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl

h = int(sys.argv[1])
w = int(sys.argv[2])
fig, ax = plt.subplots()
wi, hi = fig.get_size_inches()
fig.set_size_inches(hi*(w/h), hi)
t = np.arange(-10., 10., 1.)
plt.plot(t, t, '.')
plt.plot(t, t**2, '.')
ax.text(0., 60., 'Hello', fontdict=dict(size=25))
plt.savefig(
    'width.png',
    format='png',
    dpi=h/hi
)

laufen:

./width.py 431 869

Ausgabe:

width.png PNG 869x431 869x431+0+0 8-bit sRGB 10965B 0.000u 0:00.000

enter image description here

und für eine geringe Breite:

./width.py 431 869

Ausgabe:

width.png PNG 211x431 211x431+0+0 8-bit sRGB 6949B 0.000u 0:00.000

enter image description here

Es scheint also, dass die Schriftarten korrekt skaliert werden, wir bekommen nur bei sehr kleinen Breiten Probleme mit abgeschnittenen Beschriftungen, z.B. bei der 100 oben links.

Diese habe ich mit folgenden Mitteln umgehen können Entfernen von Leerraum um ein gespeichertes Bild

plt.tight_layout(pad=1)

das ergibt:

width.png PNG 211x431 211x431+0+0 8-bit sRGB 7134B 0.000u 0:00.000

enter image description here

Daraus ergibt sich auch, dass tight_layout entfernt einen Großteil des leeren Raums am oberen Rand des Bildes, daher verwende ich ihn im Allgemeinen immer.

Feste Höhe der magischen Basis, dpi auf fig.set_size_inches y plt.savefig(dpi= Skalierung

Ich glaube, dass dies dem unter erwähnten Ansatz entspricht: https://stackoverflow.com/a/13714720/895245

magic.py

#!/usr/bin/env python3

import sys

import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl

magic_height = 300
w = int(sys.argv[1])
h = int(sys.argv[2])
dpi = 80
fig, ax = plt.subplots(dpi=dpi)
fig.set_size_inches(magic_height*w/(h*dpi), magic_height/dpi)
t = np.arange(-10., 10., 1.)
plt.plot(t, t, '.')
plt.plot(t, t**2, '.')
ax.text(0., 60., 'Hello', fontdict=dict(size=25))
plt.savefig(
    'magic.png',
    format='png',
    dpi=h/magic_height*dpi,
)

laufen:

./magic.py 431 231

Ausgänge:

magic.png PNG 431x231 431x231+0+0 8-bit sRGB 7923B 0.000u 0:00.000

enter image description here

Und um zu sehen, ob es sich gut skalieren lässt:

./magic.py 1291 693

Ausgänge:

magic.png PNG 1291x693 1291x693+0+0 8-bit sRGB 25013B 0.000u 0:00.000

enter image description here

Wir sehen also, dass auch dieser Ansatz gut funktioniert. Das einzige Problem, das ich damit habe, ist, dass man das magic_height oder einen gleichwertigen Parameter.

Feste DPI + set_size_inches

Dieser Ansatz ergab eine leicht falsche Pixelgröße, und es ist schwierig, alles nahtlos zu skalieren.

set_size_inches.py

#!/usr/bin/env python3

import sys

import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl

w = int(sys.argv[1])
h = int(sys.argv[2])
fig, ax = plt.subplots()
fig.set_size_inches(w/fig.dpi, h/fig.dpi)
t = np.arange(-10., 10., 1.)
plt.plot(t, t, '.')
plt.plot(t, t**2, '.')
ax.text(
    0,
    60.,
    'Hello',
    # Keep font size fixed independently of DPI.
    # https://stackoverflow.com/questions/39395616/matplotlib-change-figsize-but-keep-fontsize-constant
    fontdict=dict(size=10*h/fig.dpi),
)
plt.savefig(
    'set_size_inches.png',
    format='png',
)

laufen:

./set_size_inches.py 431 231

Ausgänge:

set_size_inches.png PNG 430x231 430x231+0+0 8-bit sRGB 8078B 0.000u 0:00.000

daher ist die Höhe leicht verschoben, und das Bild:

enter image description here

Die Pixelgrößen sind auch dann korrekt, wenn ich es dreimal so groß mache:

./set_size_inches.py 1291 693

Ausgänge:

set_size_inches.png PNG 1291x693 1291x693+0+0 8-bit sRGB 19798B 0.000u 0:00.000

enter image description here

Daraus ergibt sich jedoch, dass Sie jede DPI-abhängige Einstellung proportional zur Größe in Zoll machen müssen, damit dieser Ansatz gut skaliert.

Im vorigen Beispiel haben wir nur den "Hallo"-Text proportional gemacht, und er hat seine Höhe zwischen 60 und 80 beibehalten, wie wir es erwartet hätten. Aber alles, was wir nicht gemacht haben, sieht winzig aus, einschließlich:

  • Linienbreite der Achsen
  • Häkchen-Etiketten
  • Punktmarker

SVG

Ich konnte nicht herausfinden, wie man sie für SVG-Bilder einstellt, meine Ansätze funktionierten nur für PNG-Bilder:

get_size_svg.py

#!/usr/bin/env python3

import sys

import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl

height = int(sys.argv[1])
fig, ax = plt.subplots()
t = np.arange(-10., 10., 1.)
plt.plot(t, t, '.')
plt.plot(t, t**2, '.')
ax.text(0., 60., 'Hello', fontdict=dict(size=25))
plt.savefig(
    'get_size_svg.svg',
    format='svg',
    dpi=height/fig.get_size_inches()[1]
)

laufen:

./get_size_svg.py 431

und die erzeugte Ausgabe enthält:

<svg height="345.6pt" version="1.1" viewBox="0 0 460.8 345.6" width="460.8pt"

und identifizieren sagt:

get_size_svg.svg SVG 614x461 614x461+0+0 8-bit sRGB 17094B 0.000u 0:00.000

und wenn ich es in Chromium 86 öffne, bestätigen die Debug-Tools des Browsers, dass die Höhe 460,79 beträgt.

Aber da SVG ein Vektorformat ist, sollte theoretisch alles skalierbar sein, so dass Sie einfach in ein beliebiges Format mit fester Größe konvertieren können, ohne die Auflösung zu verlieren, z. B:

inkscape -h 431 get_size_svg.svg -b FFF -e get_size_svg.png

gibt die genaue Höhe an:

enter image description here

Ich verwende Inkscape anstelle von Imagemagick's convert hier, denn Sie müssen sich mit -density um scharfe SVG-Größenänderungen mit ImageMagick zu erhalten:

Und Einstellung <img height="" im HTML sollte auch für den Browser funktionieren.

Getestet mit matplotlib==3.2.2.

20voto

psihodelia Punkte 28004

Um die Größe der Figur um das N-fache zu erhöhen, müssen Sie dies direkt vor Ihrer pl.show() :

N = 2
params = pl.gcf()
plSize = params.get_size_inches()
params.set_size_inches((plSize[0]*N, plSize[1]*N))

Es funktioniert auch gut mit einer IPython Notizbuch.

16voto

loved.by.Jesus Punkte 1777

Verallgemeinerung und Vereinfachung psihodelias Antwort :

Wenn Sie die aktuelle Größe der Figur um einen Faktor ändern wollen sizefactor :

import matplotlib.pyplot as plt

# Here goes your code

fig_size = plt.gcf().get_size_inches() # Get current size
sizefactor = 0.8 # Set a zoom factor
# Modify the current size by the factor
plt.gcf().set_size_inches(sizefactor * fig_size) 

Nachdem Sie die aktuelle Größe geändert haben, kann es vorkommen, dass Sie eine Feinabstimmung der Teilgrundriss . Sie können dies in der grafischen Benutzeroberfläche des Figurenfensters tun oder mit dem Befehl subplots_adjust

Zum Beispiel,

plt.subplots_adjust(left=0.16, bottom=0.19, top=0.82)

16voto

Das Folgende wird sicherlich funktionieren, aber fügen Sie unbedingt die Zeile plt.figure(figsize=(20,10)) über plt.plot(x,y) , plt.pie() , usw.

import matplotlib.pyplot as plt
plt.figure(figsize=(20,10))
plt.plot(x,y) ## This is your plot
plt.show()

Der Code wird kopiert von amalik2205 .

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X