用Matplotlib画GIF动图
译-唐晓霆 Jason
这篇短文介绍如何用Python里的matplotlib画出GIF动图。下面的代码我在一台安装了ImagMagick 的Ubuntu上运行过。 若想要用matplotlib的save方法渲染GIF动图的话,就必须安装ImageMagick。
下面给一个动画样本:
有几件事情需要注意:
- 图里的散点部分是不变的;变的是直线
- X轴的标题每一帧都在变化
下面上制作该图的代码:
import sys
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
fig, ax = plt.subplots()
fig.set_tight_layout(True)
# 询问图标在屏幕上的尺寸和DPI(每英寸点数)。
# 注意当我们把图标储存成一个文件时,我们需要再另外提供一个DPI值
print('fig size: {0} DPI, size in inches {1}'.format(
fig.get_dpi(), fig.get_size_inches()))
# 画出一个维持不变(不会被重画)的散点图和一开始的那条直线。
x = np.arange(0, 20, 0.1)
ax.scatter(x, x + np.random.normal(0, 3.0, len(x)))
line, = ax.plot(x, x - 5, 'r-', linewidth=2)
def update(i):
label = 'timestep {0}'.format(i)
print(label)
# 更新直线和x轴(用一个新的x轴的标签)。
# 用元组(Tuple)的形式返回在这一帧要被重新绘图的物体
line.set_ydata(x - 5 + i)
ax.set_xlabel(label)
return line, ax
if __name__ == '__main__':
# FuncAnimation 会在每一帧都调用“update” 函数。
# 在这里设置一个10帧的动画,每帧之间间隔200毫秒
anim = FuncAnimation(fig, update, frames=np.arange(0, 10), interval=200)
if len(sys.argv) > 1 and sys.argv[1] == 'save':
anim.save('line.gif', dpi=80, writer='imagemagick')
else:
# plt.show() 会一直循环播放动画
plt.show()
如果你想要一个更精美的主题,安装 seaborn 库之后添加一行:
import seaborn
然后你就会得到这个图:
提一句关于尺寸的警告:虽然我在这里分享的GIF只有10帧,而且图像也很简单, 但是它们每一帧都占大约160K。就我理解而言,GIF动图不使用跨帧压缩, 所以这使得长一点的GIF占的空间异常大。减少帧数到最最小并且让每一帧的图像小一点(通过在matplotlib里调整图表尺寸或者DPI),就可以多多少少帮助缓解一下这个问题。