Wie stelle ich die „Kameraposition“ für 3D-Diagramme mit Python / Matplotlib ein?

134

Ich lerne, wie man mit mplot3d schöne Diagramme von 3D-Daten erstellt, und bin bisher ziemlich glücklich. Was ich im Moment versuche, ist eine kleine Animation einer rotierenden Oberfläche. Zu diesem Zweck muss ich eine Kameraposition für die 3D-Projektion festlegen. Ich denke, dies muss möglich sein, da eine Oberfläche mit der Maus gedreht werden kann, wenn matplotlib interaktiv verwendet wird. Aber wie kann ich das aus einem Skript machen? Ich habe in mpl_toolkits.mplot3d.proj3d viele Transformationen gefunden, aber ich konnte nicht herausfinden, wie ich diese für meinen Zweck verwenden kann, und ich habe kein Beispiel für das gefunden, was ich versuche zu tun.

Andreas Bleuler
quelle
2
Randnotiz für diejenigen, die sich fragen, wie man interaktiv im Jupyter-Notizbuch dreht: Sie können verwenden%matplotlib notebook
YvesgereY
Durch Ziehen bei gedrückter rechter Maustaste wird auch der Kameradistanz geändert.
LoMaPh
Für diese Art von Visualisierung würde ich Mayavi ausprobieren.
Tactopoda

Antworten:

158

Bei "Kameraposition" möchten Sie die Höhe und den Azimutwinkel anpassen, mit denen Sie das 3D-Diagramm anzeigen. Sie können dies mit einstellen ax.view_init. Ich habe das folgende Skript verwendet, um zuerst den Plot zu erstellen, dann habe ich eine gute Höhe ermittelt oder elev, von der aus ich meinen Plot anzeigen kann. Ich habe dann den Azimutwinkel angepasst oder azim, um die vollen 360 Grad um mein Diagramm zu variieren, die Zahl bei jeder Instanz gespeichert (und notiert, welcher Azimutwinkel beim Speichern des Diagramms angegeben wurde). Für einen komplizierteren Kameraschwenk können Sie sowohl die Höhe als auch den Winkel anpassen, um den gewünschten Effekt zu erzielen.

    from mpl_toolkits.mplot3d import Axes3D
    ax = Axes3D(fig)
    ax.scatter(xx,yy,zz, marker='o', s=20, c="goldenrod", alpha=0.6)
    for ii in xrange(0,360,1):
        ax.view_init(elev=10., azim=ii)
        savefig("movie%d.png" % ii)
Kosmose
quelle
26
Schlage mich dazu! Nebenbei bemerkt, diese sind als ax.elevund ax.azim-Eigenschaften verfügbar . Sie könnten auch nur geschrieben haben ax.azim = iioder sogar ax.azim += 1den gleichen Effekt erzielen.
Joe Kington
1
Tut mir leid, dass ich dich geschlagen habe, aber überall faire Punkte. Dies ist auch nur ein Codierungsauszug von mir. In dieser for-Schleife befand sich mehr als nur view_init und savefig. =)
Kosmose
4
Danke Cosmosis und Joe, genau das habe ich gesucht. Da ich jetzt wusste, wonach ich suchen musste, fand ich auch ax.dist, mit dem ich zusammen mit ax.azim und ax.elev die Kameraposition in Polarkoordinaten einstellen kann.
Andreas Bleuler
Wenn dies die Antwort ist - können Sie sie bitte ankreuzen? Vielen Dank.
Kosmose
12
Sie können den Abstand zwischen Kamera und Objektpunkt auch mit ax.dist = 15 (standardmäßig 10) einstellen
Tim
14

Praktisch wäre es, die Kameraposition auf ein neues Diagramm anzuwenden. Also zeichne ich und bewege dann die Handlung mit der Maus, um die Entfernung zu ändern. Versuchen Sie dann, die Ansicht einschließlich der Entfernung auf einem anderen Diagramm zu replizieren. Ich finde, dass axx.ax.get_axes () mir ein Objekt mit den alten .azim und .elev bringt.

IN PYTHON ...

axx=ax1.get_axes()
azm=axx.azim
ele=axx.elev
dst=axx.dist       # ALWAYS GIVES 10
#dst=ax1.axes.dist # ALWAYS GIVES 10
#dst=ax1.dist      # ALWAYS GIVES 10

Später 3D-Grafik ...

ax2.view_init(elev=ele, azim=azm) #Works!
ax2.dist=dst                       # works but always 10 from axx

BEARBEITEN 1 ... OK, die Kameraposition ist die falsche Denkweise bezüglich des .dist-Werts. Es ist eine Art Hackey-Skalarmultiplikator für den gesamten Graphen.

Dies funktioniert für die Vergrößerung / Zoom der Ansicht:

xlm=ax1.get_xlim3d() #These are two tupples
ylm=ax1.get_ylim3d() #we use them in the next
zlm=ax1.get_zlim3d() #graph to reproduce the magnification from mousing
axx=ax1.get_axes()
azm=axx.azim
ele=axx.elev

Später Grafik ...

ax2.view_init(elev=ele, azim=azm) #Reproduce view
ax2.set_xlim3d(xlm[0],xlm[1])     #Reproduce magnification
ax2.set_ylim3d(ylm[0],ylm[1])     #...
ax2.set_zlim3d(zlm[0],zlm[1])     #...
user1469620
quelle
+1 für das Aufrufen der hackigen Skalarmultiplikation. Es ist sehr ärgerlich, wenn Sie auf Perspektive gehofft haben.
user5920660