Встроенные анимации в Jupyter

У меня есть анимация python script (с использованием matplotlib funcAnimation), которая работает в Spyder, но не в Jupyter. Я пробовал следующие различные предложения, такие как добавление "% matplotlib inline" и изменение базы данных matplotlib на "Qt4agg", все без успеха. Я также попробовал запустить несколько анимаций (из Jupyter tutorials), ни одна из которых не сработала. Иногда я получаю сообщение об ошибке, и иногда появляется сюжет, но не оживляет. Кстати, я использовал pyplot.plot() для работы с использованием "% matplotlib inline".

Кто-нибудь знает о рабочем ноутбуке Jupyter с примером простой анимации SIMPLE, который использует funcAnimation. Заранее спасибо за помощь!

[Примечание: я нахожусь в Windows 7]

Ответ 1

Бэкэнд для ноутбуков

'Inline' означает, что графики отображаются в виде png-графики. Эти png-изображения не могут быть анимированы. Хотя в принципе можно было бы создать анимацию, последовательно заменяя png-изображения, это, вероятно, нежелательно.

Решение состоит в том, чтобы использовать бэкэнд для ноутбука, который полностью совместим с FuncAnimation, поскольку он отображает сам рисунок matplotlib:

%matplotlib notebook

jsanimation

Из matplotlib 2.1 on мы можем создать анимацию с использованием 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, чтобы получить анимацию.

Также см. этот ответ для полного обзора.

Ответ 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())

Однако...

У меня было много проблем заставить это работать. По сути, проблема заключалась в том, что вышеописанное использует (по умолчанию) ffmpeg и кодек x264 в фоновом режиме, но они не были правильно настроены на моем компьютере. Решение состояло в том, чтобы удалить их и восстановить их из источника с правильной конфигурацией. Подробнее см. вопрос, который я задал, с рабочим ответом Эндрю Хойссера: Анимация в записной книжке ipython (jupyter) - ValueError: операция ввода-вывода для закрытого файла

Итак, сначала попробуйте решение to_html5_video, описанное выше, и если оно не работает, попробуйте также удалить/перестроить ffmpeg и x264.

Ответ 3

Вот ответ, который я собрал из нескольких источников, включая официальные примеры. Я тестировал последние версии Jupyter и Python.

  • Загрузить FFmpeg (http://ffmpeg.zeranoe.com/builds/)
  • Установите FFmpeg, чтобы вы обновили переменную окружения (http://www.wikihow.com/Install-FFmpeg-on-Windows).
  • Запустите этот script в 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')

Ответ 4

Если у вас есть список изображений и вы хотите анимировать их, вы можете использовать что-то вроде этого:

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(imgs[0])
  anim = animation.FuncAnimation(fig, animate, init_func=init,
                                 frames=len(imgs), 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())