动画能够有趣地展现某种现象。相比于静态图表,人们更容易被动画和交互式的图表所吸引。在描绘时间序列数据时,动画更有意义,例如多年来股票价格的波动,过去十年气候的季节性变化和和趋势,由于咱们能够看到特定参数如何随时间变化。html
上图是用Matplotlib实现的雨滴模拟,Matplotlib库被人们亲切地称为Python可视化包的祖父。Matplotlib经过设置50个散射点的比例和不透明度的动画来模拟地表的雨滴。现在,python拥有大量强大的可视化工具,如plotly、bokeh、altair等等。这些库可以实现最早进的动画和交互。本文的目在于介绍matlibplot这个库的中不为人熟悉的一面,那就是动画。让咱们一窥matplotlib的动画绘制。python
Matplotlib是一个python 2D绘图库,也是最流行的库之一。大多数人都是从Matplotlib开始他们的数据可视化之旅。使用matplotlib能够轻松生成plot图、柱状图、功率谱、柱状图、偏差图、散点图等。它还与Pandas和Seaborn等库无缝集成,以建立更复杂的可视化效果。linux
Matplotlib的一些优势是:git
然而,也有一些方面,Matplotlib并无那么耀眼,落后于其强大的对手。github
为了快速复习一下matplotlib的用法,这里有一个来自Datacamp的Cheat sheet.后端
matplotlib的动画基础类实现了动画的绘制。它提供了一个框架,内建动画功能。由两个主要的接口的实现:api
FuncAnimation 经过周期性地调用函数func来制做动画。
ArtistAnimation:使用一个固定的
Artist
对象绘制动画.在这两种方法中, FuncAnimation用起来最方便,这是它的文档。bash
必要:安装numpy和matplotlibapp
可选:为了保存动画为mp4或gif格式,须要 ffmpeg
or imagemagick
(不少linux发行版自带).框架
这个例子来自于Matplotlib Animation tutorial,展现如何使用FuncAnimation建立一个基本的动画。
import numpy as np from matplotlib import pyplot as plt from matplotlib.animation import FuncAnimation plt.style.use('seaborn-pastel') fig = plt.figure() ax = plt.axes(xlim=(0, 4), ylim=(-2, 2)) line, = ax.plot([], [], lw=3) def init(): line.set_data([], []) return line, def animate(i): x = np.linspace(0, 4, 1000) y = np.sin(2 * np.pi * (x - 0.01 * i)) line.set_data(x, y) return line, anim = FuncAnimation(fig, animate, init_func=init, frames=100, interval=20, blit=True) anim.save('sine_wave.gif', writer='imagemagick')
运行以后,将在当前目录下生成一个gif文件。
解析:
在第7-9行,咱们建立了一个图像窗口,设置了坐标轴的范围。关键在于,在第9行建立了一个空的line对象,以后将经过更新line的数据,实现动画效果。
在第11-13行,咱们建立了初始化函数init,这个函数其实什么也没干,给了line对象空的数据。
第14-18行,咱们第难以了动画函数animate,入参i是动画帧序号,根据i计算新的sin曲线数据,更新到line对象。
在第20行,咱们利用以前所说的FuncAnimation()函数建立了对象anim,初始化时传入了figure对象,init()函数和animate()函数,以及帧数和更新时间。因为咱们的sin函数是波长为1,显示4个周期,所以循环一个周期,也就是100帧,就能够实现先后相接的循环效果了。
画一个一个正弦信号毕竟too simple. 大学课堂的物理课使用示波器,确定作过这样的实验:在阴极射线管示波器上使用x-y模式,x通道的正弦信号频率为f1,y通道的频率为f2,二者之间存在关系,随着n和m的不一样,残留的光辉会变幻出各类图形,称之为李萨如(Liaasjous)图形。无论你们还记不记得,咱们这就来画一个,直接上代码。
import matplotlib.pyplot as plt import matplotlib.animation as animation import numpy as np plt.style.use('dark_background') fig = plt.figure() ax = plt.axes(xlim=(-50, 50), ylim=(-50, 50)) line, = ax.plot([], [], lw=2) # initialization function def init(): # creating an empty plot/frame line.set_data([], []) return line, # lists to store x and y axis points xdata, ydata = [], [] #simulate ghost effect of oscilloscope def ghostImage(x,y): xdata.append(x) ydata.append(y) if len(xdata)>60: del xdata[0] del ydata[0] return xdata,ydata # animation function def animate(i): # t is a parameter t = i/100.0 # x, y values to be plotted x = 40*np.sin(2*2*np.pi*(t+0.3)) y = 40*np.cos(3*2*np.pi*t) # appending new points to x, y axes points list line.set_data(ghostImage(x,y)) return line, # setting a title for the plot plt.title('Creating a Lissajous figure with matplotlib') # hiding the axis details plt.axis('off') # call the animator anim = animation.FuncAnimation(fig, animate, init_func=init, frames=400, interval=20, blit=True) # save the animation as gif file anim.save('figure.gif',writer='imagemagick')
三维图像具备更多的信息,若是让三维图像的观察角度运动起来,那将十分有意思。
如今咱们用另一种暴力的思路制做三维动画:首先绘制一幅三维图,而后每次改变一下视角,成为一帧。这里再也不使用什么FuncAnimation函数了,直接将每帧保存成静态图片,而后合成为gif图。这样的好处在于,只要在原来的基础上增长一个循环,保存成多幅图像,就能合成动画。
咱们来读入一幅图片test.jpg,用plot_surface画成3D图;而后在程序中改变视角,保存成多幅图片(运行前要新建一个目录animFram,用于写入图像)。
from mpl_toolkits.mplot3d import Axes3D import matplotlib.pyplot as plt from PIL import Image #import matplotlib.animation as animation import numpy as np img = Image.open('test.jpg') grayImg = img.convert('L') width, height = grayImg.size X, Y = np.meshgrid(np.arange(0,width), np.arange(0,height)) #print(X) Z = np.array(grayImg) fig = plt.figure() ax = fig.gca(projection='3d') ax.plot_surface(X,Y,Z, rstride=1, cstride=1, cmap='viridis') transition = lambda x,N: (1+np.sin(-0.5*np.pi+2*np.pi*x / (1.0*N)))/2.0 for i in range (40): horiAngle=45+50*transition(i,40) vertAngle=50+43*transition(i,40) ax.view_init(vertAngle,horiAngle) filename='animFram/'+str('%03d'%i)+'.png' plt.savefig(filename, dpi=96)
而后使用ImageMagick的convert命令,将多幅静态帧转换成gif,使用如下命令:
convert -delay 10 *.png gif.gif
好了那就介绍到这,足够用了,外面有人敲门。
https://towardsdatascience.com/animations-with-matplotlib-d96375c5442c