[PYTHON] [Introduction à Matplotlib] Axes Animation 3D: J'ai joué avec des figurines 3D Lisaju ♬

Je suis accro à l'animation 3D Sin-Cos-t suivante qui est arrivée sur Twitter il y a 3 jours, je vais donc la résumer. Je voulais dessiner une figure Lisaju plus intéressante avec une colle légère qui semble être une figure Lisaju ordinaire. .. .. J'en étais accro. https://twitter.com/i/status/1302164499139502080 Je voulais dessiner la même image, mais j'ai abandonné sur les points suivants.

Ce que j'ai fait

・ Animation Axes3D ・ Animation Sin-Cos-t -Appelez la fonction update () directement pour dessiner ・ Décalez l'axe Z ・ Rotation des figures ・ Figurine Lisaju 3D

・ Animation Axes3D

Au début, même si c'était en 3D, j'ai finalement pensé qu'il serait possible d'aller avec quelque chose comme une référence. 【référence】 [Matplotlib basic] Essayez d'écrire un graphique dynamique ♬ ~ Sortie vidéo; animation Gif En fait, dans sin-cos-t, vous trouverez un code similaire à Gugu: 【référence】 ② [Matplotlib] Visualisation des données 3D

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
#Ajouter une figure
fig = plt.figure(figsize = (8, 8))
#Ajout d'axes 3D
ax = fig.add_subplot(111, projection='3d')
#Définir le titre des axes
ax.set_title("Helix", size = 20)
#Définir l'étiquette de l'axe
ax.set_xlabel("x", size = 14)
ax.set_ylabel("y", size = 14)
ax.set_zlabel("z", size = 14)
#Définir l'échelle de l'axe
ax.set_xticks([-1.0, -0.5, 0.0, 0.5, 1.0])
ax.set_yticks([-1.0, -0.5, 0.0, 0.5, 1.0])
#Définition du rapport de circonférence
pi = np.pi
#Nombre de divisions de paramètres
n = 256
#Créer le paramètre t
t = np.linspace(-6*pi, 6*pi, n)
#Equation en spirale
x = np.cos(t)
y = np.sin(t)
z = t
#Tracez une courbe
ax.plot(x, y, z, color = "red")
plt.show()

Le résultat est le suivant, mais j'ai obtenu un chiffre similaire bien que cela ne fonctionne pas. Après cela, déplacez-le simplement, recherchez l'animation. Figure_helix.png Un moyen facile de le trouver est sur matplotlib.org Une intrigue animée en 3D., mais j'ai trouvé quelque chose de plus proche ci-dessous.

・ Animation Sin-Cos-t

【référence】 3D animation using matplotlib C'est presque la réponse.

from matplotlib import pyplot as plt
import numpy as np
import mpl_toolkits.mplot3d.axes3d as p3
from matplotlib import animation

fig = plt.figure()
ax = p3.Axes3D(fig)

def gen(n):
    phi = 0
    while phi < 2*np.pi:
        yield np.array([np.cos(phi), np.sin(phi), phi])
        phi += 2*np.pi/n

def update(num, data, line):
    line.set_data(data[:2, :num])
    line.set_3d_properties(data[2, :num])

N = 100
data = np.array(list(gen(N))).T
line, = ax.plot(data[0, 0:1], data[1, 0:1], data[2, 0:1])
# Setting the axes properties
ax.set_xlim3d([-1.0, 1.0])
ax.set_xlabel('X')
ax.set_ylim3d([-1.0, 1.0])
ax.set_ylabel('Y')
ax.set_zlim3d([0.0, 10.0])
ax.set_zlabel('Z')
ani = animation.FuncAnimation(fig, update, N, fargs=(data, line), interval=10000/N, blit=False)
#ani.save('matplot003.gif', writer='imagemagick')
plt.show()

matplot003.gif Cependant, lorsque j'essaye de dessiner trois animations, cela ressemble à ceci:

aniy = animation.FuncAnimation(fig, update, N, fargs=(datay, liney), interval=10000/N, blit=False)
anix = animation.FuncAnimation(fig, update, N, fargs=(datax, linex), interval=10000/N, blit=False)
aniz = animation.FuncAnimation(fig, update, N, fargs=(dataxy, linexy), interval=10000/N, blit=False)

Avec cette méthode, vous pouvez obtenir des animations similaires sous forme d'images, mais je ne peux pas penser à un moyen de sauvegarder ces trois animations ensemble.

-Appelez la fonction update () directement pour dessiner

J'ai décidé de tracer chacun d'eux avec plt.pause (0,001) comme indiqué ci-dessous et d'enregistrer la figure. Finalement, j'ai décidé de générer gif_animation à partir de ces chiffres.

frames =100
s=180
for n in range(frames): 
    s+=1
    num = s%800+200
    update(num,datax,linex)
    update(num,datay,liney)
    update(num,dataz,linez)
    plt.pause(0.001)
    plt.savefig('./sin_wave/'+str(n)+'.png'.format(elev, azim))

from PIL import Image,ImageFilter
images = []
for n in range(frames):
    exec('a'+str(n)+'=Image.open("./sin_wave/'+str(n)+'.png ")')
    images.append(eval('a'+str(n)))
images[0].save('./sin_wave/sin_wave_el{}_az{}.gif'.format(elev, azim),
               save_all=True,
               append_images=images[1:],
               duration=100,
               loop=0)

Et en limitant la plage de dessin avec line.set_data (data [: 2, num-200: num]) et num = s% 800 + 200 comme dans le code ci-dessous, le résultat est plus proche de ce que vous voulez. .. sin_wave_el0_az0.gif

from matplotlib import pyplot as plt
import numpy as np
import mpl_toolkits.mplot3d.axes3d as p3
from matplotlib import animation

fig = plt.figure()
ax = p3.Axes3D(fig)

def genxy(n,fx,fy,fxc=0,fyc=0):
    phi = 0
    sk = 0
    while phi < 360:
        yield np.array([fx*np.cos(phi)+fxc, fy*np.sin(phi)+fyc,phi])
        phi += 36*5/n

def update(num, data, line):
    line.set_data(data[:2,num-200 :num]) #Limiter la section de dessin
    line.set_3d_properties(data[2,num-200 :num])
    
N = 960
datay = np.array(list(genxy(N,fx=0,fy=1,fxc=-2,fyc=0))).T
liney, = ax.plot(datay[0, 0:1], datay[1, 0:1], datay[2, 0:1])
datax = np.array(list(genxy(N,fx=1,fy=0,fxc=0,fyc=2))).T
linex, = ax.plot(datax[0, 0:1], datax[1, 0:1], datax[2, 0:1])
dataz = np.array(list(genxy(N,fx=1,fy=1,fxc=0,fyc=0))).T
linez, = ax.plot(dataz[0, 0:1], dataz[1, 0:1], dataz[2, 0:1])

# Setting the axes properties
ax.set_xlim3d([-2.0,2.0])
ax.set_xlabel('X')

ax.set_ylim3d([-2.0, 2.0])
ax.set_ylabel('Y')

ax.set_zlim3d([36.0, 80.])
ax.set_zlabel('Z')

frames =36
s=180
for n in range(frames):
    s+=1
    num = s%800+200
    update(num,datax,linex)
    update(num,datay,liney)
    update(num,dataz,linez)
    plt.pause(0.001)
    plt.savefig('./sin_wave/'+str(n)+'.png'.format(0, 0))

from PIL import Image,ImageFilter
images = []
for n in range(frames):
    exec('a'+str(n)+'=Image.open("./sin_wave/'+str(n)+'.png ")')
    images.append(eval('a'+str(n)))
images[0].save('./sin_wave/sin_wave_el{}_az{}.gif'.format(0, 0),
               save_all=True,
               append_images=images[1:],
               duration=100,
               loop=0)    

・ Décalez l'axe Z

Réécrivons la fonction update () comme suit pour décaler l'axe Z. En conséquence, l'image est dessinée dans la même position le long de l'axe Z. L'affichage de l'axe est également effacé ici.

def update(num, data, line):
    line.set_data(data[:2,num-200 :num])
    line.set_3d_properties(data[2,num-200 :num])
    ax.set_zlim3d([0+data[2,num-200], 34+data[2,num-200]])
    ax.set_zticklabels([])
    ax.grid(False)

sin_wave_el0_az0.gif

・ Rotation des figures

Eh bien, si vous apportez les axes de coordonnées à cet arrangement, il est terminé pour le moment. Cependant, cela a été difficile. Tout d'abord, vous pouvez faire pivoter l'arbre comme suit. Dans ce qui suit, l'image de la valeur initiale est sortie avec l'axe modifié.

for elev in range(0,360,10): #Changement d'élévation
    for azim in range(-180,180,5): #Changer l'angle azimutal
        ax.view_init(elev, azim) #Ajustez ici l'orientation des axes de coordonnées
        frames =1  #34
        s=180
        for n in range(1): #frames
            s+=1
            num = s%800+200
            update(num,datax,linex)
            update(num,datay,liney)
            update(num,dataz,linez)
            plt.pause(0.001)
            plt.savefig('./sin_wave/'+str(n)+'{}{}.png'.format(elev, azim))

En conséquence, cet arrangement n'a pas été obtenu. Vous n'avez pas assez d'imagination. Je ne peux penser à rien d'autre que la plage d'angles ci-dessus. Cependant, j'ai eu l'idée de changer les en-têtes des axes pour X-Y-Z. yield np.array([phi,fx*np.cos(phi)+fxc, fy*np.sin(phi)+fyc]) C'est dit. En d'autres termes, si vous changez le cap de l'axe, la spirale se couchera. Je suis donc arrivé au code suivant.

from matplotlib import pyplot as plt
import numpy as np
import mpl_toolkits.mplot3d.axes3d as p3
from matplotlib import animation

fig = plt.figure()
ax = p3.Axes3D(fig)

def genxy(n,fx,fy,fxc=0,fyc=0):
    phi = 0
    while phi < 360:
        yield np.array([phi,fx*np.cos(phi)+fxc, fy*np.sin(phi)+fyc])
        phi += 36*5/n

def update(num, data, line):
    line.set_data(data[:2,num-200 :num])
    line.set_3d_properties(data[2,num-200 :num])
    ax.set_xlim3d([0+data[0,num-200], 36+data[0,num-200]])
    ax.set_xticklabels([])
    ax.grid(False)
    
N = 960
datay = np.array(list(genxy(N,fx=0,fy=1,fxc=-2,fyc=0))).T
liney, = ax.plot(datay[0, 0:1], datay[1, 0:1], datay[2, 0:1])
datax = np.array(list(genxy(N,fx=1,fy=0,fxc=0,fyc=-2))).T
linex, = ax.plot(datax[0, 0:1], datax[1, 0:1], datax[2, 0:1])
dataz = np.array(list(genxy(N,fx=1,fy=1,fxc=0,fyc=0))).T
linez, = ax.plot(dataz[0, 0:1], dataz[1, 0:1], dataz[2, 0:1])

# Setting the axes properties
ax.set_xlim3d([20, 70.0])
ax.set_xlabel('Z')
ax.set_ylim3d([-2.0, 2.0])
ax.set_ylabel('X')
ax.set_zlim3d([-2.0, 2.0])
ax.set_zlabel('Y')

elev=20. 
azim=35.
ax.view_init(elev, azim)

frames =100
s=180
for n in range(frames): #frames
    s+=1
    num = s%800+200
    update(num,datax,linex)
    update(num,datay,liney)
    update(num,dataz,linez)
    plt.pause(0.001)
    plt.savefig('./sin_wave/'+str(n)+'.png'.format(elev, azim))

from PIL import Image,ImageFilter
images = []
for n in range(frames):
    exec('a'+str(n)+'=Image.open("./sin_wave/'+str(n)+'.png ")')
    images.append(eval('a'+str(n)))
images[0].save('./sin_wave/sin_wave_el{}_az{}.gif'.format(elev, azim),
               save_all=True,
               append_images=images[1:],
               duration=100,
               loop=0)

De cette façon, la première animation 3D publiée a été produite.

・ Figurine Lisaju 3D

Cependant, ce que je voulais à l'origine, c'est une figurine 3D Lisaju, alors je vais en essayer. Vous pouvez le faire en changeant ce qui suit et en changeant frames = 200 pour que la connexion soit fluide. yield np.array([phi,fx*np.cos(3*phi/2)+fxc, fy*np.sin(2*phi/3)+fyc])

X : Y = 1 : 2 sin_wave1-2_el20.0_az35.0.gif X : Y = 1/2 : 2/3 sin_wave1w2-2w3_el20.0_az35.0.gif X : Y = 3/2 : 2/3 sin_wave3w2-2w3-2_el20.0_az35.0.gif

Résumé

・ J'ai dessiné une animation 3D de Sin-Cos-t ・ Vous pouvez maintenant dessiner une animation 3D ・ J'ai dessiné une figurine de Lisaju en 3D

prime

Version terminée Amélioré pour dessiner la figure de Lisaju à l'origine 3d_animation_Risajyu/3D_animation_risajyu.py

point ajouté sin_wave_point_el20.0_az35.0.gif

Recommended Posts

[Introduction à Matplotlib] Axes Animation 3D: J'ai joué avec des figurines 3D Lisaju ♬
[Introduction à Pytorch] J'ai joué avec sinGAN ♬
[Introduction à StyleGAN] J'ai joué avec "The Life of a Man" ♬
[Introduction à sinGAN-Tensorflow] J'ai joué avec la super-résolution "Challenge Big Imayuyu" ♬
[Introduction à RasPi4] J'ai joué avec "la conversation de langue empoisonnée d'Hiroko / Hiromi" ♪
[Introduction à StyleGAN] J'ai joué avec "Une femme se transforme en Mayuyu" ♬
Comment titrer plusieurs figures avec matplotlib
[Introduction à AWS] J'ai joué avec des voix masculines et féminines avec Polly et Transcribe ♪
[Introduction à StyleGAN] J'ai joué avec style_mixing "Femme qui enlève ses lunettes" ♬
Animation avec matplotlib
Animation avec matplotlib
Je souhaite afficher plusieurs images avec matplotlib.
Je voulais visualiser la simulation de particules 3D avec la bibliothèque de visualisation Python Matplotlib.
J'ai joué avec wordcloud!
[Introduction au trading système] J'ai dessiné un oscillateur stochastique avec python et joué avec ♬
[Introduction à Pytorch] J'ai essayé de catégoriser Cifar10 avec VGG16 ♬
Je souhaite créer manuellement une légende avec matplotlib
Graphique 3D avec matplotlib
[Python] Comment créer un histogramme bidimensionnel avec Matplotlib
[Introduction à AWS] J'ai essayé de jouer avec la conversion voix-texte ♪
Ajustez les axes avec matplotlib
[IOS] Animation GIF avec Pythonista3. J'en étais accro.
J'ai fait une animation qui renvoie la pierre d'Othello avec POV-Ray
Introduction à RDB avec sqlalchemy Ⅰ
Introduction à l'optimisation non linéaire (I)
J'ai lu "Renforcer l'apprentissage avec Python de l'introduction à la pratique" Chapitre 1
Je voulais résoudre le problème ABC164 A ~ D avec Python
[Introduction] Je veux créer un robot Mastodon avec Python! 【Débutants】
J'ai lu "Renforcer l'apprentissage avec Python de l'introduction à la pratique" Chapitre 2
Créer une animation de tracé avec Python + Matplotlib
Introduction à RDB avec sqlalchemy II
J'ai joué avec PyQt5 et Python3
Je veux faire ○○ avec les Pandas
J'ai joué avec Mecab (analyse morphologique)!
Dessinez facilement des graphiques avec matplotlib
Je veux déboguer avec Python
Animation facile avec matplotlib (mp4, gif)
(Matplotlib) Je veux dessiner un graphique avec une taille spécifiée en pixels
J'ai essayé l'analyse de données IRMf avec python (Introduction au décodage des informations cérébrales)