抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

Background

matlab给我们提供了plot,ezplot,fplot,polar,bar,bar3,plot3,mesh,surf一系列绘图的办法,python也给我们matplotlib.pyplot库可以画各种各样的静态图形,可我们有的时候想展示曲线的运动情况,像放动画一样展现出来,甚至还想保存为gif或者mp4之类的文件,这就不得不提到我们今天的主题了:动画实验;

Content

matlab绘图基本算法

不像matplotlib中可以调用animation模块,matlab只能调用绘图的api来实现逐帧绘制;

绘制的基本思想是:

  1. 确定动画的画布;
  2. 确定动画的帧数;
  3. 清空当前的图形;
  4. 绘制当前帧的图形;
  5. 暂停一小会以免动画太快;

有了这些思想,在matlab就可以绘图了,不过想要利用python的库,还需要一些基本知识;

FuncAnimation基础介绍

animation 有个核心类: FuncAnimation ;

FuncAnimation(fig, func, frames, init_func, interval, blit)

  • fig: 绘制动图的画布名称

    这个参数通常由先前的figure()函数创建;

  • func: 回调函数

    更新新一帧的方式,这个函数返回当前帧的绘制对象,请注意返回值不只一个

    一般计算出新的坐标后,利用绘制对象的set_data方法去更新它;

  • frames: 动画的帧数

    参数常见值为n:int,相当于range(n),但事实上也可以取值 iterable,generator,None

  • init_func: 初始帧

    func类似,返回初始帧的绘制对象。

  • interval: 帧长

    决定帧更新频率,单位:ms

  • blit: 选择更新所有点,还是仅更新产生变化的点。

通过这些参数可以看到,基本和matlab手动实现所需要的准备工作是差不多的;

保存动图文件

在matlab中,一般将动画保存到.avi文件中,这是由matlab提供的接口决定的,一般方法如下:

  1. obj=VidioWriter('test.avi'):产生VidioWriter对象,同时起一个名字
  2. open(obj):打开obj对象;
  3. writeVidio(obj,frame):将当前帧存到obj中;
  4. close(obj):关闭obj对象

而在python中,你只需要安装一些依赖项即可,如果用 FuncAnimation 生成的动图,注意参数fps--frames per second:

  • mp4:执行 pip install ffmpeg
  • gif: 执行 pip install Wand
ani.save("test.mp4", fps=20, writer="ffmpeg")
ani.save("test.gif", fps=50, writer="imagemagick")

Example

实现正方形旋转,保存文件;

我们知道,对于列向量,逆时针旋转角,得到新的向量,我们分别采用两种语言实现:

matlab:

P=[0 1 1 0 0;0 0 1 1 0];
obj = VideoWriter('test.avi');
open(obj);
for t = linspace(0, 3*pi/4, 100)
    M = [cos(t) -sin(t);sin(t) cos(t)];
    PP = M*P;
    plot(PP(1,:),PP(2,:),'r');
    axis equal;
    axis([-2 2 -2 2]);
    frame = getframe(gcf);
    writeVideo(obj, frame);
    pause(0.05);
end
close(obj);

来看一下我们的test.avi(突然发现它在Typora里预览不了...)

python:

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

fig = plt.figure(figsize = (6, 6))
ax = fig.add_subplot(1, 1, 1)
p = np.array([[0,1,1,0,0],[0,0,1,1,0]])
square, = ax.plot(p[0], p[1], color = 'red', animated=True)
frames = np.linspace(0, 3*np.pi/4, 100)

def init():
    ax.set_xlim(-2, 2)
    ax.set_ylim(-2, 2)
    return square,

def update(t):
    M = np.array([[np.cos(t), -np.sin(t)],[np.sin(t), np.cos(t)]])
    pp = M @ p
    ax.set_aspect('equal')  
    square.set_data(pp[0], pp[1])
    return square,

ani = FuncAnimation(fig, update, frames=frames, init_func=init, interval=50, blit=True)
# plt.show()
ani.save("test.gif", fps=25, writer="imagemagick")

test

Remark

又水了一篇...

评论




博客内容遵循 [署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 协议](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh)
本站使用 Volantis 作为主题 字数统计:318.5k
<