2021-02-06 Python generates gif animation through matplotlib package and gif package

Python generates gif animation through matplotlib package and gif package

Use matplotlibThere are many ways to generate animated gif, generally conventionally used matplotlibin the animationmodule FuncAnimationfunction implementation. matplotlibI saw the gifintroduction of the third-party animation package on the official website .

gifPackage overview

gifThe package is an animation extension that supports  Altairmatplotliband Plotly.
gifDependence PIL, ie pillow, requirement Pillow>=7.1.2.
Installation gifpackage,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.

gifPackage interpretation

gifThe package is very concise, there is only a single file gif.py, the file mainly contains optionsclasses framesand savetwo functions.

optionsclass

Provide a condensed version Altairmatplotliband Plotlysave or export settings. As matplotliban 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: optionsCreate a matplotlibdictionary in the constructor to save the configuration, and then pass it to the underlying matplotlibpackage.

framesfunction

Decorator function, through the corresponding package to write a custom drawing function to generate a single frame image.

savefunction

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

framesThat is @gif.frame, the sequence of frames generated according to the decorated drawing function, which is customized here as needed.
durationThe duration is determined by the unit unitand mode between, and the default is framesthe time interval between frames.
unitThat is, the duration unit, which supports milliseconds and seconds, and the default is milliseconds.
betweenThat duration calculation mode, default framesi.e., durationthe time interval between frames, startenda mode duration=duration /len(frames), i.e. durationall frames - the duration of the entire animation.

gifPackage generation gif animation practice

 

import randomfrom matplotlib import pyplot as pltimport 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.framedef 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")

image

Take the heart-shaped curve as an example to compare the difference between the gifpackage and the animationmodule to achieve animation

Heart-shaped curve drawing

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

image

gifHow the package is implemented

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", duration=80)

image

matplotlib Conventional FuncAnimationfunction implementation

​​​​​​​

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

matplotlibLow-level PillowWriterclass implementation

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

Through comparison, it can be seen that gifthe implementation of the package is similar to the implementation of the matplotlibmedium utilization PillowWriter, and is more low-level, so that it is more flexible when encountering more complicated drawings.

Guess you like

Origin blog.csdn.net/qingfengxd1/article/details/113725721
gif