Python matplotlib包和gif包生成gif动画实战对比

作者:mighty13 时间:2022-08-09 14:09:45 

前言

使用matplotlib生成gif动画的方法有很多,一般常规使用matplotlib的animation模块的FuncAnimation函数实现。

在matplotlib官网看到了第三方动画包gif的介绍。

gif包概述

gif包是支持 Altair, matplotlib和Plotly的动画扩展。

gif依赖PIL,即pillow,要求Pillow>=7.1.2。

安装gif包,pip install gif

动画原理

所有动画都是由帧(frame)构成的,一帧就是一幅静止的画面,连续的帧就形成动画。我们通常说帧数,简单地说,就是在1秒钟时间里传输的图片的帧数,也可以理解为图形处理器每秒钟能够刷新几次,通常用fps(Frames Per Second)表示。

制作动画的关键:如何生成帧,每秒多少帧。

gif包解读

gif包非常简洁,只有一个单独的文件gif.py,文件主要包含options类、frames和save两个函数。

options类

提供精简版 的Altair, matplotlib和Plotly的保存或输出设置。以matplotlib为例,提供以下设置。

  • dpi (int): The resolution in dots per inch

  • facecolor (colorspec): The facecolor of the figure

  • edgecolor (colorspec): The edgecolor of the figure

  • transparent (bool): If True, the axes patches will all be transparent

设置方法:gif.options.matplotlib["dpi"] = 300

原理:options在构造函数中创建matplotlib字典保存配置,随后传递给底层的matplotlib包。

frames函数

装饰器函数,通过对应包编写自定义绘图函数生成单帧图像。

save函数

根据帧序列生成动画。

def save(frames, path, duration=100, unit="milliseconds", between="frames", loop=True):
   """Save decorated frames to an animated gif.
   - frames (list): collection of frames built with the gif.frame decorator
   - path (str): filename with relative/absolute path
   - duration (int/float): time (with reference to unit and between)
   - unit {"ms" or "milliseconds", "s" or "seconds"}: time unit value
   - between {"frames", "startend"}: duration between "frames" or the entire gif ("startend")
   - loop (bool): infinitely loop the animation

frames即根据@gif.frame装饰的绘图函数生成的帧的序列,此处根据需要自定义。

duration即持续时间,由单位unit和模式between决定,默认为frames为帧间的时间间隔。

unit即持续时间单位,支持毫秒和秒,默认为毫秒。

between即持续时间计算模式,默认frames即duration为帧之间的时间间隔,startend模式时duration=duration /len(frames),即duration为所有帧—整个动画的持续时间。

gif包生成gif动画实践

import random
from matplotlib import pyplot as plt
import gif

# 构造数据
x = [random.randint(0, 100) for _ in range(100)]
y = [random.randint(0, 100) for _ in range(100)]
#设置选项
gif.options.matplotlib["dpi"] = 300
#使用gif.frame装饰器构造绘图函数,即如何生成静态的帧
@gif.frame
def plot(i):
   xi = x[i*10:(i+1)*10]
   yi = y[i*10:(i+1)*10]
   plt.scatter(xi, yi)
   plt.xlim((0, 100))
   plt.ylim((0, 100))
# 构造帧序列frames,即把生成动画的所有帧按顺序放在列表中
frames = []
for i in range(10):
   frame = plot(i)
   frames.append(frame)
# 根据帧序列frames,动画持续时间duration,生成gif动画
gif.save(frames, 'example.gif', duration=3.5, unit="s", between="startend")

以心形曲线为例比较gif包和animation模块实现动画的差异

gif包的实现方式

import numpy as np
import gif
from matplotlib import pyplot as plt

t = np.linspace(0, 6, 100)
x = 16 * np.sin(t) ** 3
y = 13 * np.cos(t) - 5 * np.cos(2 * t) - 2 * np.cos(3 * t) - np.cos(4 * t)

@gif.frame
def plot_love(x, y):
   plt.figure(figsize=(5, 3), dpi=100)
   plt.scatter(x, y, 60, c="r", alpha=0.7, marker=r"$\heartsuit$")
   plt.axis("off")

frames = []
for i in range(1, len(x)):
   of = plot_love(x[:i], y[:i])
   frames.append(of)

gif.save(frames, "love.gif", duration=80)

matplotlib 常规FuncAnimation函数实现方式

from matplotlib import pyplot as plt
import matplotlib.animation as animation
import numpy as np

t = np.linspace(0, 6, 100)
x = 16 * np.sin(t) ** 3
y = 13 * np.cos(t) - 5 * np.cos(2 * t) - 2 * np.cos(3 * t) - np.cos(4 * t)
data=[i for i in zip(x,y)]

def plot_love(data):
   x, y = data
   plt.scatter(x, y, 60, c="r", alpha=0.7, marker=r"$\heartsuit$")

fig=plt.figure(figsize=(5, 3), dpi=100)
plt.axis("off")
animator = animation.FuncAnimation(fig, plot_love, frames=data, interval=80)
animator.save("love.gif", writer='pillow')

matplotlib底层PillowWriter类实现方式

from matplotlib import pyplot as plt
import matplotlib.animation as animation
import numpy as np

t = np.linspace(0, 6, 100)
x = 16 * np.sin(t) ** 3
y = 13 * np.cos(t) - 5 * np.cos(2 * t) - 2 * np.cos(3 * t) - np.cos(4 * t)

def plot_love(x,y):
   plt.scatter(x, y, 60, c="r", alpha=0.7, marker=r"$\heartsuit$")

fig=plt.figure(figsize=(5, 3), dpi=100)
plt.axis("off")

writer = animation.PillowWriter(fps=15)
with writer.saving(fig, "love1.gif"):
   for i in range(1, len(x)):
       of = plot_love(x[i], y[i])
       writer.grab_frame()

比较结果

通过比较可知gif包的实现方式和matplotlib中利用PillowWriter实现方式类似,更偏底层一些,这样遇到比较复杂的绘图时更灵活。

来源:https://blog.csdn.net/mighty13/article/details/111565092

标签:matplotlib,gif,包
0
投稿

猜你喜欢

  • BOF、EOF 属性

    2009-05-11 12:37:00
  • Mysql最新版8.0.21下载安装配置教程详解

    2024-01-21 23:58:17
  • 10张动图学会python循环与递归问题

    2023-08-23 10:55:42
  • div+css实现圆角边框

    2007-10-21 08:55:00
  • python 筛选数据集中列中value长度大于20的数据集方法

    2023-05-27 03:55:02
  • 使用Python求解最大公约数的实现方法

    2021-03-20 07:58:51
  • Python学习之流程控制与条件判断总结

    2023-08-20 13:37:02
  • uniapp实现支付功能

    2023-08-21 13:53:47
  • asp如何做一个随机密码产生器?

    2010-07-12 18:57:00
  • Python二分查找+字符串模板+textwrap模块,

    2023-03-12 11:12:44
  • python基于Opencv实现人脸口罩检测

    2021-11-18 02:45:16
  • Python爬取豆瓣视频信息代码实例

    2021-10-28 06:41:46
  • Python实现多行注释的另类方法

    2021-04-28 21:49:12
  • keras在构建LSTM模型时对变长序列的处理操作

    2021-12-06 19:17:31
  • 快速了解Python相对导入

    2023-07-29 18:35:30
  • vue3 使用defineAsyncComponent与component标签实现动态渲染组件思路详解

    2024-05-02 16:32:38
  • python从PDF中提取数据的示例

    2021-10-15 21:46:05
  • python使用正则表达式来获取文件名的前缀方法

    2023-02-08 07:37:58
  • Pyqt5 实现跳转界面并关闭当前界面的方法

    2023-02-02 13:59:19
  • 十行Python代码制作一个视频倒放神器

    2022-02-03 13:40:15
  • asp之家 网络编程 m.aspxhome.com