Python generates gif animation through matplotlib package and gif package
Use matplotlib
There are many ways to generate animated gif, generally conventionally used matplotlib
in the animation
module FuncAnimation
function implementation. matplotlib
I saw the gif
introduction of the third-party animation package on the official website .
gif
Package overview
gif
The package is an animation extension that supports Altair
, matplotlib
and Plotly
. gif
Dependence PIL
, ie pillow
, requirement Pillow>=7.1.2
.
Installation gif
package,pip install gif
Animation principle
Everything 动画
is made 帧(frame)
up of, a frame is a still picture, and successive frames form an animation. We usually say the number of frames. Simply put, it is the number of frames of a picture transmitted in 1 second. It can also be understood as the graphics processor can refresh several times per second, which is usually fps(Frames Per Second)
expressed. The key to making animation: how to generate frames and how many frames per second.
gif
Package interpretation
gif
The package is very concise, there is only a single file gif.py
, the file mainly contains options
classes frames
and save
two functions.
options
class
Provide a condensed version Altair
, matplotlib
and Plotly
save or export settings. As matplotlib
an example, provide the following settings.
-
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
Setting method: gif.options.matplotlib["dpi"] = 300
Principle: options
Create a matplotlib
dictionary in the constructor to save the configuration, and then pass it to the underlying matplotlib
package.
frames
function
Decorator function, through the corresponding package to write a custom drawing function to generate a single frame image.
save
function
Generate animation based on frame sequence.
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
That is @gif.frame
, the sequence of frames generated according to the decorated drawing function, which is customized here as needed. duration
The duration is determined by the unit unit
and mode between
, and the default is frames
the time interval between frames. unit
That is, the duration unit, which supports milliseconds and seconds, and the default is milliseconds. between
That duration calculation mode, default frames
i.e., duration
the time interval between frames, startend
a mode duration=duration /len(frames)
, i.e. duration
all frames - the duration of the entire animation.
gif
Package generation gif animation practice
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")
Take the heart-shaped curve as an example to compare the difference between the gif
package and the animation
module to achieve animation
Heart-shaped curve drawing
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()
gif
How the package is implemented
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
Conventional FuncAnimation
function implementation
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
Low-level PillowWriter
class implementation
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()