1,准備
首先得安裝Mayavi,看我之前的帖子,鏈接。
然后安裝Moviepy,pip install moviepy. 關於Moviepy怎么用,可以見官網。
2,思路
通過Mayavi繪制每一幀的圖片,然后Moviepy獲取到每一幀,生成視頻文件。
3,示例
1 import numpy as np 2 import mayavi.mlab as mlab 3 import moviepy.editor as mpy 4 5 duration= 2 # duration of the animation in seconds (it will loop) 6 7 # 使用MAYAVI先創建一個圖片 8 fig_myv = mlab.figure(size=(220,220), bgcolor=(1,1,1)) 9 X, Y = np.linspace(-2,2,200), np.linspace(-2,2,200) 10 XX, YY = np.meshgrid(X,Y) 11 ZZ = lambda d: np.sinc(XX**2+YY**2)+np.sin(XX+d) 12 13 # 使用MoviePy把這個圖片創建為一個動畫,並保存 14 def make_frame(t): 15 mlab.clf() # clear the figure (to reset the colors) 16 mlab.mesh(YY,XX,ZZ(2*np.pi*t/duration), figure=fig_myv) 17 #下面兩句很重要 18 f = mlab.gcf() 19 f.scene._lift() 20 return mlab.screenshot() #antialiased=True 21 22 animation = mpy.VideoClip(make_frame, duration=duration) 23 animation.write_gif("sinc.gif", fps=20)
值得注意的是,很多地方提供了類似於上面的代碼,但是運行時會報錯:“ValueError: cannot reshape array of size 12 into shape (0,0,3)”
解決辦法是在 返回screenshot()前添加兩行代碼
1 f = mlab.gcf() 2 f.scene._lift()
運行結果如下
4,示例二
將我之前博客中的例子轉換成動畫
1 import mayavi.mlab as mlab 2 import numpy as np 3 from moviepy.editor import VideoClip 4 5 fig=mlab.figure(size=(200,200),bgcolor=(1.0,1.0,1.0)) 6 duration = 5 7 #生成20個點坐標 8 t = np.linspace(0, 4 * np.pi, 20) 9 x = np.sin(2 * t) 10 y = np.cos(t) 11 z = np.cos(2 * t) 12 s = 2 + np.sin(t) 13 14 def make_frame(t): 15 mlab.clf() 16 # # s數組只移動一位,點的顏色也就會變換 17 b = s[19] 18 s[1:20]=s[0:19] 19 s[0] = b 20 f = mlab.gcf() 21 f.scene._lift() 22 mlab.points3d(x, y, z, s, mode="cube",scale_mode="none", colormap="spectral", scale_factor=.5) 23 mlab.view(azimuth= 180*t/duration, distance=9) # camera angle 24 return mlab.screenshot(antialiased=True) 25 26 # duration是gif時長 27 animation = VideoClip(make_frame, duration=duration) 28 # fps幀率 29 animation.write_gif('rot.gif', fps=3)
本來小球的顏色是由s變量控制的,每一幀將s數組中的數平移一位,這樣顏色點的顏色就能變化了。每一秒3幀,mlab.view控制相機變換。
運行結果如下
PS: Matplotlib輸出動畫
與Mayavi輸出動畫思路是一模一樣的,區別在於返回每一幀圖像的函數不同。
1 import matplotlib.pyplot as plt 2 import numpy as np 3 from moviepy.editor import VideoClip 4 from moviepy.video.io.bindings import mplfig_to_npimage 5 6 x = np.linspace(-2, 2, 200) 7 8 duration = 2 9 10 fig,ax = plt.subplots() 11 def make_frame(t): 12 ax.clear() 13 ax.plot(x, np.sin(x**2) + np.sin(x + 2*np.pi/duration * t), lw=3) 14 ax.set_ylim(-1.5, 2.5) 15 return mplfig_to_npimage(fig) 16 17 animation = VideoClip(make_frame, duration=duration) 18 animation.write_gif("matplotlib.gif", fps=4)
運行結果: