当前位置 : 主页 > 编程语言 > python >

Python通过matplotlib包和gif包生成gif动画

来源:互联网 收集:自由互联 发布时间:2022-10-26
使用​​matplotlib​​​生成gif动画的方法有很多,一般常规使用​​matplotlib​​​的​​animation​​​模块的​​FuncAnimation​​​函数实现。在​​matplotlib​​​官网看到了第三方动

使用​​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")

Python通过matplotlib包和gif包生成gif动画_函数实现

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

from matplotlib import pyplot as plt
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)
fig = plt.figure(figsize=(5, 3), dpi=100)
plt.scatter(x, y)
plt.show()

心形曲线绘制


from matplotlib import pyplot as pltimport numpy as np
t = np.linspace(0, 6, 100)x = 16 * np.sin(t) ** 3y = 13 * np.cos(t) - 5 * np.cos(2 * t) - 2 * np.cos(3 * t) - np.cos(4 * t)fig = plt.figure(figsize=(5, 3), dpi=100)plt.scatter(x, y)plt.show()

Python通过matplotlib包和gif包生成gif动画_函数实现_02

​​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)


import numpy as npimport giffrom matplotlib import pyplot as plt
t = np.linspace(0, 6, 100)x = 16 * np.sin(t) ** 3y = 13 * np.cos(t) - 5 * np.cos(2 * t) - 2 * np.cos(3 * t) - np.cos(4 * t)
@gif.framedef 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", duratinotallow=80)

Python通过matplotlib包和gif包生成gif动画_自定义_03

​​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, "love21.gif", dpi=100):
for i in range(1, len(x)):
plot_love(x[i], y[i])
writer.grab_frame()

from matplotlib import pyplot as pltimport matplotlib.animation as animationimport numpy as np
t = np.linspace(0, 6, 100)x = 16 * np.sin(t) ** 3y = 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, "love21.gif", dpi=100): for i in range(1, len(x)): plot_love(x[i], y[i]) writer.grab_frame()

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

上一篇:Python自动化办公-处理Excel文档
下一篇:没有了
网友评论