欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

matplotlib animation 绘制动画

程序员文章站 2022-03-21 23:43:21
...

在博客python中plot实现即时数据动态显示方法中介绍了python利用matplotlib库中的plt.ion()函数实现即时数据动态显示的方法。该方法最初的目的就是为了实时监测系统,实时可视化体系统数据。目前,对于利用Python+Matplotlib实时产生数据实时显示的应用,本人还没有找到能替代它的方案。本文将面向另一种应用背景:生成(收集)数据的过程与动态显示的过程是可以分开的。也即,我们只需要在仿真程序运行完成后,得到数据动态变化的显示(或视频)就可以了。博客python中plot实现即时数据动态显示方法与本文是相互补充的。博客python中plot实现即时数据动态显示方法中的方法一般用于调试系统,在确定系统按照预期运行时,再通过本文的方法绘制动画用于成果展示。

1. 机缘

昨天晚上逛B站被这条与新冠病毒传播模拟有关的视频(【实验模拟】不要给病毒反弹的机会!)吸引,看得出来这是个有情怀的阿婆主,所以多看了一眼。循着阿婆主留下的源码地址,我下载下来看了看。InfectSim。嚯嚯,这个代码一印入眼帘立马一股杀气袭来。下面是代码的开头,孤陋寡闻了,在python3中中文可以当变量名
matplotlib animation 绘制动画
matplotlib animation 绘制动画
我饶有兴趣的把代码复制到jupyter notebook里,还真可以运行。后面的动态显示代码也是基于matplotlib,并且生成的动画可以保存,这是与博客python中plot实现即时数据动态显示方法的区别之一。博客python中plot实现即时数据动态显示方法中实现动态显示,并不会自动保留历史显示信息,我需要在跑程序的同时打开录屏软件,对界面实时显示的图像进行录制,形成可展示的成果。而阿婆主的代码直接生成了可重复播放的视频。这在很多情况下就比博客python中plot实现即时数据动态显示方法方便有效。例如,写这篇博客就比写之前的博客轻松许多,因为运行完程序直接可以生成gif动态图。所以,记录下来方便自己以后查阅。

对于编程来说,几个经典例程胜过一切!!!下面给出线型、散点、3D散点的应用例子。每个例子会给对程序中的关键代码进行解释,并给出需要依赖的包的安装程序(主要是在windows系统下,生成gif,mp4时需要用到的某些依赖软件,例如:ffmpeg,imagemagick)。

例一: 线型动画生成

示例程序

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from IPython.display import HTML
%matplotlib inline
fig, ax = plt.subplots()
xdata, ydata = [], []
ln, = ax.plot([], [], 'r-', animated=False)

def init():
    ax.set_xlim(0, 2*np.pi)
    ax.set_ylim(-1, 1)
    return ln,

def update(frame):
    xdata.append(frame)
    ydata.append(np.sin(frame))
    ln.set_data(xdata, ydata)
    return ln,  # 千万别少了这里的逗号!!!!!

ani = FuncAnimation(fig, update, frames=np.linspace(0, 2*np.pi, 128), init_func=init, blit=True)
ani.save('test_animation.gif',writer='imagemagick') # 保存 gif
# ani.save('test_animation.mp4') # 保存 mp4
# HTML(ani.to_html5_video()) # 直接jupyter notebook 网页内播放,也是mp4格式,可另存为

安装依赖软件

当保存gif时,需要调用imagemagick软件。当要保存为mp4格式或用HTML播放时,需要调用ffmpeg

ubuntu

  • ffmpeg
sudo apt install ffmpeg
  • imagemagick
sudo  apt-get install imagemagick

windows 10

  • ffmpeg
  1. 根据系统下载ffmpeg builds (windows)
  2. 下载好后解压,会生成一个类似名为“ffmpeg-20180820-78d4b6b-win64-static”的文件夹。
  3. 打开你想安装的任意磁盘,例如:c盘。新建一个名为“ffmpeg”的文件夹,将第二步解压生成的文件夹中的内容全部拷贝到“ffmpeg”文件夹中:
    matplotlib animation 绘制动画
  4. 配置FFmpeg环境变量,如下图:
    matplotlib animation 绘制动画
  5. 打开命令提示符窗口。输入命令“ffmpeg –version”。如果命令提示窗口返回FFmpeg的版本信息,那么就说明安装成功了,你可以在命令提示行中任意文件夹下运行FFmpeg。

结果展示(该gif动态图由程序直接生成并保存于本地)

matplotlib animation 绘制动画

示例二:二维散点动态图

示例程序

import matplotlib.pyplot as plt
import matplotlib.animation as animation
from IPython.display import HTML
import numpy as np
%matplotlib inline
plt.style.use('seaborn-pastel')
fig = plt.figure()
class AnimatedScatter(object):
    def __init__(self, numpoints=5):
        self.numpoints = numpoints
        self.stream = self.data_stream()
        self.angle = 0

        self.fig = plt.figure()
        self.fig.canvas.mpl_connect('draw_event',self.forceUpdate)
        self.ax = self.fig.add_subplot(111)
        self.ani = animation.FuncAnimation(self.fig, self.update, interval=100, 
                                       init_func=self.setup_plot, frames=200)

    def change_angle(self):
        self.angle = (self.angle + 1)%360

    def forceUpdate(self, event):
        self.scat.changed()

    def setup_plot(self):
        X = next(self.stream)
        c = ['b', 'r', 'g', 'y', 'm']
        self.scat = self.ax.scatter(X[:,0], X[:,1] , c=c, s=200)
        self.ax.axis([-10, 10, -10, 10])

        return self.scat,

    def data_stream(self):
        data = np.zeros(( self.numpoints , 2 ))
        xy = data[:,:2]
        while True:
            xy += 2 * (np.random.random(( self.numpoints,2)) - 0.5)
            yield data

    def update(self, i):
        data = next(self.stream)
        self.scat._offsets = ( data )
        return self.scat,

    def show(self):
        plt.show()
a = AnimatedScatter()
a.ani.save('test_animation.gif',writer='imagemagick') # 保存gif...
# a.ani.save('test_animation.mp4')  # 保存MP4
# HTML(a.ani.to_html5_video()) # 直接jupyter notebook 网页内播放,也是mp4格式,可另存为

结果展示

matplotlib animation 绘制动画

示例三:三维散点动态图

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

FLOOR = -10
CEILING = 10

class AnimatedScatter(object):
    def __init__(self, numpoints=5):
        self.numpoints = numpoints
        self.stream = self.data_stream()
        self.angle = 0

        self.fig = plt.figure()
        self.fig.canvas.mpl_connect('draw_event',self.forceUpdate)
        self.ax = self.fig.add_subplot(111,projection = '3d')
        self.ani = animation.FuncAnimation(self.fig, self.update, interval=100, 
                                       init_func=self.setup_plot, frames=200)

    def change_angle(self):
        self.angle = (self.angle + 1)%360

    def forceUpdate(self, event):
        self.scat.changed()

    def setup_plot(self):
        X = next(self.stream)
        c = ['b', 'r', 'g', 'y', 'm']
        self.scat = self.ax.scatter(X[:,0], X[:,1], X[:,2] , c=c, s=200)

        self.ax.set_xlim3d(FLOOR, CEILING)
        self.ax.set_ylim3d(FLOOR, CEILING)
        self.ax.set_zlim3d(FLOOR, CEILING)

        return self.scat,

    def data_stream(self):
        data = np.zeros(( self.numpoints , 3 ))
        xyz = data[:,:3]
        while True:
            xyz += 2 * (np.random.random(( self.numpoints,3)) - 0.5)
            yield data

    def update(self, i):
        data = next(self.stream)
        self.scat._offsets3d = ( np.ma.ravel(data[:,0]) , np.ma.ravel(data[:,1]) , np.ma.ravel(data[:,2]) )
        return self.scat,

    def show(self):
        plt.show()

a = AnimatedScatter()
a.ani.save('test_animation.gif',writer='imagemagick') # 保存gif...
# a.ani.save('test_animation.mp4') # 保存MP4
# HTML(a.ani.to_html5_video()) # 直接jupyter notebook 网页内播放,也是mp4格式,可另存为

结果展示

matplotlib animation 绘制动画

最后

还是希望疫情早点过去!

by Toby, 2020-3-12

相关标签: coding