Jupyter 中的内联动画

Posted

技术标签:

【中文标题】Jupyter 中的内联动画【英文标题】:Inline animations in Jupyter 【发布时间】:2017-09-12 16:40:33 【问题描述】:

我有一个 python 动画脚本(使用 matplotlib 的 funcAnimation),它在 Spyder 中运行,但不在 Jupyter 中。我尝试了各种建议,例如添加“%matplotlib inline”并将 matplotlib 后端更改为“Qt4agg”,但均未成功。我还尝试过运行几个示例动画(来自 Jupyter 教程),但都没有奏效。有时我会收到一条错误消息,有时情节会出现,但没有动画。顺便说一句,我已经让 pyplot.plot() 使用“%matplotlib inline”工作。

有谁知道有一个使用 funcAnimation 的简单内联动画示例的工作 Jupyter 笔记本。提前感谢您的帮助!

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

【问题讨论】:

【参考方案1】:

笔记本后端

'Inline' 表示绘图显示为 png 图形。那些 png 图片不能动画化。虽然原则上可以通过连续替换 png 图像来构建动画,但这可能是不希望的。

一种解决方案是使用笔记本后端,它与FuncAnimation 完全兼容,因为它可以渲染 matplotlib 图形本身:

%matplotlib notebook

js动画

从 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来获取动画。

另请参阅this answer 了解完整概述。

【讨论】:

AttributeError: 'FuncAnimation' 对象没有属性 'to_jshtml' 在 matplotlib 2.1.0 版本中添加了 to_jshtml:matplotlib.org/users/prev_whats_new/whats_new_2.1.0.html!pip install matplotlib --upgrade 当我将示例复制到网络中时,它在我第一次执行时运行良好。第二次返回动画和一个我似乎无法摆脱的空图。它来自哪里? @AliceSchwarze 将plt.close() 放在ani = ... 声明之后以摆脱初始情节。然后第二个ani 启动动画。【参考方案2】:

本教程中有一个简单的示例: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的卸载/重建。

【讨论】:

【参考方案3】:

另一种选择:

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)

【讨论】:

【参考方案4】:

这是我从多个来源(包括官方示例)汇总的答案。我使用最新版本的 Jupyter 和 Python 进行了测试。

下载FFmpeg (http://ffmpeg.zeranoe.com/builds/) 安装 FFmpeg 确保更新环境变量 ( http://www.wikihow.com/Install-FFmpeg-on-Windows )。 在下面的 Jupyter 中运行此脚本。变量imageList 是唯一需要修改的东西。它是图像列表(您的输入)。
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')

【讨论】:

【参考方案5】:

如果您有一个图像列表并希望通过它们制作动画,您可以使用以下内容:

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

【讨论】:

为了让它工作,你必须下载 ffmpeg 到你的操作系统,然后plt.rcParams['animation.ffmpeg_path'] = '/usr/bin/ffmpeg'。将/usr/bin/ffmpeg' 替换为您操作系统中ffmpeg 二进制文件的路径。

以上是关于Jupyter 中的内联动画的主要内容,如果未能解决你的问题,请参考以下文章

在jupyter笔记本中设置markdown内联的字体大小

是否可以使用 pyqtgraph 函数在 Jupyter Notebook 上内联绘图?

在 Jupyter 中使用 plotly 在离线模式下创建动画图表

尝试使用 matplotlib 内联绘图时,为啥在 jupyter notebook 中出现 NonGuiException?

当我使用内联 sql 魔术时,jupyter notebook pyspark sparkmagic 错误

为 Jupyter 笔记本调整 Julia 内核中的绘图大小