Jupyter中的内联动画

65
我有一个Python动画脚本(使用Matplotlib的funcAnimation),在Spyder中可以运行但在Jupyter中却不行。我尝试过添加“%matplotlib inline”和将Matplotlib后端更改为“Qt4agg”等各种建议,但都没有成功。我还尝试了运行几个示例动画(来自Jupyter教程),但都无法正常工作。有时会出现错误消息,有时绘图出现,但没有动画效果。顺便说一下,我已经使用“%matplotlib inline”使pyplot.plot()起作用。

是否有人知道一个工作良好的Jupyter笔记本,其中包含使用funcAnimation的简单内联动画示例。

[注意:我使用的是Windows 7]

6个回答

96

笔记本后端

“内嵌”表示图表以png格式显示。这些png图像无法进行动画处理。虽然原则上可以通过不断替换png图像来构建动画,但这可能是不可取的。

一种解决方案是使用笔记本后端,它与FuncAnimation完全兼容,因为它自己呈现matplotlib图。

%matplotlib notebook

JavaScript动画

从matplotlib 2.1开始,我们可以使用JavaScript创建动画。这类似于ani.to_html5()的解决方案,但它不需要任何视频编解码器。

from IPython.display import HTML
HTML(ani.to_jshtml())

一些完整的示例:

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

t = np.linspace(0,2*np.pi)
x = np.sin(t)

fig, ax = plt.subplots()
ax.axis([0,2*np.pi,-1,1])
l, = ax.plot([],[])

def animate(i):
    l.set_data(t[:i], x[:i])

ani = matplotlib.animation.FuncAnimation(fig, animate, frames=len(t))

from IPython.display import HTML
HTML(ani.to_jshtml())

另外,将jsanimation设为显示动画的默认选项。
plt.rcParams["animation.html"] = "jshtml"

最后只需简单地声明ani以获得动画。

此外,请参见此答案以获取完整概述。


7
AttributeError: 'FuncAnimation'对象没有'to_jshtml'属性。 - ctrl-alt-delor
1
to_jshtml 函数是在 matplotlib 2.1.0 版本中添加的: https://matplotlib.org/users/prev_whats_new/whats_new_2.1.0.html !pip install matplotlib --upgrade - Salain
1
当我将示例程序复制到网络中时,第一次执行它时可以正常运行。第二次返回动画和一个空图,但我似乎无法摆脱它。它是从哪里来的? - Alice Schwarze
6
请将 plt.close() 放在 ani = ... 的声明后面,以消除初始图。第二个 ani 然后启动动画。 - hahnec
我该如何制作一个成功的HTML文件来展示动画呢?我尝试过jupyter nbconvert --html <notebook.ipyb>,但是它没有显示任何输出。 - Gabe Morris
显示剩余2条评论

17

在此教程中有一个简单的示例,链接如下:http://louistiao.me/posts/notebooks/embedding-matplotlib-animations-in-jupyter-notebooks/

总之,为了实现上述教程,你需要像这样做:

from matplotlib import animation
from IPython.display import HTML

# <insert animation setup code here>

anim = animation.FuncAnimation()  # With arguments of course!
HTML(anim.to_html5_video())

然而...

我在让它工作上遇到了很多麻烦。实际上,问题在于上述内容使用(默认)ffmpegx264编解码器来处理视频,但这些在我的机器上配置不正确。解决方法是卸载它们,并从源代码重新构建它们以获得正确的配置。有关更多详细信息,请参见我提出的问题,Andrew Heusser给出了一个有效的答案:Animations in ipython (jupyter) notebook - ValueError: I/O operation on closed file

因此,首先尝试上述的to_html5_video解决方案,如果它不起作用,还可以尝试卸载/重建ffmpegx264


16

另一种选择:

import matplotlib.animation
import matplotlib.pyplot as plt
import numpy as np
plt.rcParams["animation.html"] = "jshtml"
plt.rcParams['figure.dpi'] = 150  
plt.ioff()
fig, ax = plt.subplots()

x= np.linspace(0,10,100)
def animate(t):
    plt.cla()
    plt.plot(x-t,x)
    plt.xlim(0,10)

matplotlib.animation.FuncAnimation(fig, animate, frames=10)

enter image description here


4
由于某些原因,这会分别提供静态图像和动画。 - Coddy
@Coddy 添加 %matplotlib inline 后,代码将输出动画而不是静态图像。 - undefined

7

以下是我从多个来源(包括官方示例)整理出来的答案。我已经测试了最新版本的Jupyter和Python。

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from IPython.display import HTML

#=========================================
# Create Fake Images using Numpy 
# You don't need this in your code as you have your own imageList.
# This is used as an example.

imageList = []
x = np.linspace(0, 2 * np.pi, 120)
y = np.linspace(0, 2 * np.pi, 100).reshape(-1, 1)
for i in range(60):
    x += np.pi / 15.
    y += np.pi / 20.
    imageList.append(np.sin(x) + np.cos(y))

#=========================================
# Animate Fake Images (in Jupyter)

def getImageFromList(x):
    return imageList[x]

fig = plt.figure(figsize=(10, 10))
ims = []
for i in range(len(imageList)):
    im = plt.imshow(getImageFromList(i), animated=True)
    ims.append([im])

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

# Show the animation
HTML(ani.to_html5_video())

#=========================================
# Save animation as video (if required)
# ani.save('dynamic_images.mp4')

3
如果您有一组图像,并希望通过它们进行动画制作,可以使用以下代码:
from keras.preprocessing.image import load_img, img_to_array
from matplotlib import animation
from IPython.display import HTML
import glob

%matplotlib inline

def plot_images(img_list):
  def init():
    img.set_data(img_list[0])
    return (img,)

  def animate(i):
    img.set_data(img_list[i])
    return (img,)

  fig = figure()
  ax = fig.gca()
  img = ax.imshow(img_list[0])
  anim = animation.FuncAnimation(fig, animate, init_func=init,
                                 frames=len(img_list), interval=20, blit=True)
  return anim

imgs = [img_to_array(load_img(i)) for i in glob.glob('*.jpg')]

HTML(plot_images(imgs).to_html5_video())

1
为了使其正常工作,您需要将ffmpeg下载到您的操作系统中,然后使用plt.rcParams['animation.ffmpeg_path'] = '/usr/bin/ffmpeg'。请将/usr/bin/ffmpeg'替换为您操作系统中ffmpeg二进制文件的路径。 - Ruthvik Vaila

0
感谢Kolibril。我终于可以在Jupyter和Google Colab上运行动画了。 我修改了一些代码,生成了随机线条的动画。
import matplotlib.animation
import matplotlib.pyplot as plt
from itertools import count
import random

plt.rcParams["animation.html"] = "jshtml"
plt.rcParams['figure.dpi'] = 150  

fig, ax = plt.subplots()
x_value = []
y_value = []
index = count();
def animate(t):
    x_value.append(next(index))
    y_value.append(random.randint(0,10))
    ax.cla()
    ax.plot(x_value,y_value)
    ax.set_xlim(0,10)

matplotlib.animation.FuncAnimation(fig, animate, frames=10, interval = 500)

在此输入图片描述


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接