美文网首页Python小推车python模块
【转】如何用 Matplotlib 画 GIF 动图

【转】如何用 Matplotlib 画 GIF 动图

作者: 白菜代码小推车 | 来源:发表于2019-03-24 17:26 被阅读2次

如何用 Matplotlib 画 GIF 动图

今天分享的这篇译文中介绍了 matplotlib 绘图库的一个 使用示例,即如何制作 GIF 动图。本文原作者为 Eli Bendersky,译者为 唐晓霆 Jason ,由编程派 EarlGrey 校对。

译者简介:唐晓霆,在香港的成都人,城市大学研究助理,会写python,兴趣是深度学习。

这篇短文介绍如何用 Python 里的 matplotlib 画出 GIF 动图。下面的代码我在一台安装了 ImagMagickUbuntu 机器上运行过。 若想要用 matplotlibsave 方法渲染 GIF 动图的话,就必须安装 ImageMagick

下面给一个动画样本:

有几点需要注意:

  1. 图里的散点部分是不变的;变的是直线
  2. 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 ),就可以多多少少帮助缓解一下这个问题。

EarlGrey:我自己测试生成的 line.gif 文件大概 86 KB 左右。

点击查看原文链接

说明

我将源码测试过,但是在弹出框中的保存没有保存为 gif。另外,按照代码中的说明,这样操作是可以保存为gif

python test.py save

但是之前作者说过,需要安装ImagMagick,这个不是python的包,是依赖于php的一个工具,具体安装步骤可以见这里【windows下的ImageMagick安装详细过程】,感觉有点麻烦,其实也可以下载一个录屏的软件,然后制作为gif就好啦!

另外来自于知乎的 - 【如何用Python实现动态图? - 带萝卜的回答】

import matplotlib.pyplot as plt
import time

def insert_sort(lst):
    lsts = []
    for i in range(len(lst)):
        temp = lst[i]
        j = i-1
        while j>=0 and lst[j]>temp:
            lst[j+1] = lst[j]
            j -= 1
        lst[j+1] = temp
        l = lst[:]
        lsts.append(l)
    return lsts


if __name__ == "__main__":
    lst = [13,32,42,1,53,4,66,2,5,7,74,23]
    lsts = insert_sort(lst)
    plt.ion()#打开交互模式
    fig = plt.figure()#新建绘图窗口
    ax  = plt.gca()#获取当前子图
    bars = ax.bar(range(len(lst)),height=lst)#绘制条形图
    for l in lsts:
        print(l)
        bars.remove()#删除条形图
        bars = ax.bar(range(len(lst)),height=l)#绘制条形图
        plt.pause(0.5)
    while True:#防止图片关闭
        plt.pause(1)

最上面的主要是用的FuncAnimation()的功能,设定帧数,这样在运行代码的时候会一直循环。这里主要是利用了plt.pause()这个方法来让plt绘图时候的暂停,因为图形中大部分的元素是没有发生改变的,所以看起来是连贯的,如果想要播放的间隔变短,可以调整间隔的时间长短,但是这种的不能一直循环,如果需要的话,可以在while True的循环里面加上break,然后把for嵌套在while里面,也实现了循环

import matplotlib.pyplot as plt
import time

def insert_sort(lst):
    lsts = []
    for i in range(len(lst)):
        temp = lst[i]
        j = i-1
        while j>=0 and lst[j]>temp:
            lst[j+1] = lst[j]
            j -= 1
        lst[j+1] = temp
        l = lst[:]
        lsts.append(l)
    return lsts


if __name__ == "__main__":
    lst = [13,32,42,1,53,4,66,2,5,7,74,23]
    lsts = insert_sort(lst)
    plt.ion()#打开交互模式
    fig = plt.figure()#新建绘图窗口
    ax  = plt.gca()#获取当前子图
    bars = ax.bar(range(len(lst)),height=lst)#绘制条形图
    while True:
        for l in lsts:
            print(l)
            bars.remove()#删除条形图
            bars = ax.bar(range(len(lst)),height=l)#绘制条形图
            plt.pause(0.5)
        while True:#防止图片关闭
            plt.pause(1)
            break

相关文章

网友评论

    本文标题:【转】如何用 Matplotlib 画 GIF 动图

    本文链接:https://www.haomeiwen.com/subject/lawuvqtx.html