前言
使用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函数
根据帧序列生成动画。
1
2
3
4
5
6
7
8
|
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动画实践
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
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包的实现方式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
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函数实现方式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
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类实现方式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
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实现方式类似,更偏底层一些,这样遇到比较复杂的绘图时更灵活。
总结
到此这篇关于Python matplotlib包和gif包生成gif动画实战对比的文章就介绍到这了,更多相关matplotlib包和gif包生成gif内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!
原文链接:https://blog.csdn.net/mighty13/article/details/111565092