search
LoginSignup
83

More than 5 years have passed since last update.

posted at

updated at

matplotlibで簡単にアニメーションをつくる(mp4, gif)

matplotlib.animation: matplotlibベースの、お手軽アニメーション生成ライブラリ。

インストール

@mac
$ pip install matplotlib
$ brew install imagemagick # gif 保存用
$ brew install ffmpeg # mp4 保存用
matplotlib.rcの修正
$ python -c "import matplotlib;print(matplotlib.matplotlib_fname())"
/Users/riki/.pyenv/versions/ML-2.7.13/lib/python2.7/site-packages/matplotlib/mpl-data/matplotlibrc
$ atom /Users/riki/.pyenv/versions/ML-2.7.13/lib/python2.7/site-packages/matplotlib/mpl-data/matplotlibrc

# line 38
- backend : macosx
+ backend : Tkagg

Animationを生成する関数が2種類ある

  • ArtistAnimation: あらかじめ全てのフレームをlistで用意しておく
  • FuncAnimation: 各フレームを動的に生成する

個人的には ArtistAnimationの方がわかりやすいのでこちらをオススメする。
FuncAnimationの方が柔軟ではあるが、ArtistAnimationで不便は特に感じない。

ArtistAnimation

animation.ArtistAnimation(fig, artists, interval=200)
* fig: 大枠。matplotlibのfigureオブジェクト
* artists: 各フレームで描くartistオブジェクト(lineなど)のlistのlist
* interval: 各フレームの再生間隔 [ms]

artists引数をlistのlistにしないといけないところでerrorを出しやすいので注意。(詳細後述)


例1: sin波のアニメーション

anim_sin_wave.py
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

fig = plt.figure()
x = np.arange(0, 10, 0.1)

ims = []
for a in range(50):
    y = np.sin(x - a)
    line, = plt.plot(x, y, "r")
    ims.append([line])

ani = animation.ArtistAnimation(fig, ims)
ani.save('anim.gif', writer="imagemagick")
ani.save('anim.mp4', writer="ffmpeg")
plt.show()

anim.gif

pyplot.plot関数は複数のグラフを一度にプロットできるので、返り値の型がlist。

lines = plt.plot(x1, y1, 'r', x2, y2, 'g', x3, y3, 'b')
print type(lines) # list
print len(lines) # 3
print type(lines[0]) # matplotlib.lines.Line2D

わかりやすさのため、メインコードでは敢えて unpackしてLine2Dオブジェクトを取り出して、そのあと、listに変更してからlistに追加する。

line, = plt.plot(x, y, "r")
ims.append([line])

animationの保存は、以下で行える(gifかmp4の好きな方でやればいい)

ani.save('anim.gif', writer="imagemagick")
ani.save('anim.mp4', writer="ffmpeg")

例2: 2次元画像のアニメーション

dynamic_image.py
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

fig = plt.figure()

def f(x, y):
    return np.sin(x) + np.cos(y)

x = np.linspace(0, 2 * np.pi, 120)
y = np.linspace(0, 2 * np.pi, 100).reshape(-1, 1)
ims = []

for i in range(60):
    x += np.pi / 15.
    y += np.pi / 20.
    im = plt.imshow(f(x, y), animated=True)
    ims.append([im])

ani = animation.ArtistAnimation(fig, ims, interval=50, blit=True,
                                repeat_delay=1000)

ani.save('anim.gif', writer="imagemagick")
ani.save('anim.mp4', writer="ffmpeg")
plt.show()

anim.gif

pyplot.imshow関数は、返り値の型がAxesImageオブジェクトなので、listにしてからlistに追加する。

im = plt.imshow([[]])
print type(im) # matplotlib.image.AxesImage
ims.append([im])

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
83