将TensorBoard图像序列转换为视频/GIF

5
我有一个生成一系列matplotlib图形并使用TensorBoard的SummaryWriter()将它们写入磁盘的脚本。TensorBoard可以通过移动滑块前进和后退查看图像序列,但我想将图像序列转换为视频或动画。是否有方法可以实现这一点?
编辑1:这是我的代码当前执行的简化示例。我想将通过.add_figure写入日志文件的图像转换为gif。
import matplotlib.pyplot as plt
import numpy as np
from torch.utils.tensorboard import SummaryWriter

n = 200
nframes = 25
x = np.linspace(-np.pi*4, np.pi*4, n)
tensorboard_writer = SummaryWriter()

for i, t in enumerate(np.linspace(0, np.pi, nframes)):
    plt.plot(x, np.cos(x + t))
    plt.plot(x, np.sin(2*x - t))
    plt.plot(x, np.cos(x + t) + np.sin(2*x - t))
    plt.ylim(-2.5,2.5)
    fig = plt.gcf()
    tensorboard_writer.add_figure(
        tag='temp',
        figure=fig,
        global_step=i,
        close=True)


你可以使用imageio或matplotlib的FuncAnimation,虽然我建议在创建图形并将其传递给动画制作程序之间不要将图像写入磁盘,除非您想保存单个帧。 - William Miller
FuncAnimation 需要同时将图像存储在内存中,是吗? - Rylan Schaeffer
任何从一组帧转换为单个视频文件的过程都需要同时将所有帧存储在内存中。在写入磁盘之间创建冗余读取,除非您想要保留单个帧以及动画文件。 - William Miller
是的,我明白写入和读取内存会涉及到冗余的写入和读取,但这正是我想要的。 - Rylan Schaeffer
1
好的,这种情况下您仍然可以使用imageio或matplotlib的FuncAnimation。我会创建一个示例来演示。 - William Miller
1个回答

2
您可以使用imageio或matplotlib的FuncAnimation从一组表示帧的文件创建动画。例如,我已经根据以下方式创建了一组文件:
import matplotlib.pyplot as plt
import numpy as np

n = 200
nframes = 25
x = np.linspace(-np.pi*4, np.pi*4, n)

for i, t in enumerate(np.linspace(0, np.pi, nframes)):
    plt.plot(x, np.cos(x + t))
    plt.plot(x, np.sin(2*x - t))
    plt.plot(x, np.cos(x + t) + np.sin(2*x - t))
    plt.ylim(-2.5,2.5)
    plt.savefig('frame.'+str(i)+'.png', bbox_inches='tight', dpi=300)
    plt.clf()

这段代码创建了一系列文件,文件名为'frame.n.png',其中n是帧数,本例中为25。在半个周期内,绘制了两个传播的正弦波和所创建的波。

使用FuncAnimation方法,您可以执行以下操作:

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

fig = plt.figure(figsize=(10, 6), dpi=300)
nframes = 25

def animate(i):
    im = plt.imread('frame.'+str(i)+'.png')
    plt.imshow(im)
    plt.axis('off')

anim = FuncAnimation(fig, animate, frames=nframes, interval=(2000.0/nframes))
anim.save('output.gif', writer='imagemagick')

使用imageio方法,您只需执行以下操作:
import imageio

nframes = 25
files = ['frame.'+str(i)+'.png' for i in range(nframes)]

frames = [imageio.imread(f) for f in files]
imageio.mimsave('output.gif', frames, fps=(nframes / 2.0))

无论哪种方法,都会产生这个动画:

enter image description here

然而,与FuncAnimation方法相比,imageio方法速度要快得多:

> $ time python3 imageio.py
real    0m9.483s
user    0m9.484s
sys     0m1.156s

> $ time python3 FuncAnimation.py
real    15m36.151s
user    3m28.375s
sys     12m3.578s

需要注意的是,使用 FuncAnimation 方法生成的文件比使用 imageio 方法生成的文件小得多

2.5M Jan 23 18:36 FuncAnimation.gif
 13M Jan 23 18:08 imageio.gif

如果您更喜欢使用ffmpeg,当然也可以用它来完成这个任务。


哇!非常感谢这一切。不过,我的问题关注的是写入TensorBoard日志文件的图像。您能否修改您的答案以演示如何从这样的文件中读取图像? - Rylan Schaeffer
@RylanSchaeffer,你能否添加一下你使用的代码,通过SummaryWriter将图像写入文件?这样我回答你的后续问题会更容易些。 - William Miller
完成了!我使用了你的代码,尽可能地简化了它。运行上述代码后,磁盘上将会有一个名为“runs/”的目录,并包含tensorboard日志文件。 - Rylan Schaeffer
@RylanSchaeffer 最简单的方法是同时制作动画并将文件写入磁盘,而不是先制作tensorboard文件,然后再读取图形以制作动画。鉴于您在编辑中提供的示例,这将是最佳方法 - 您的实际代码是否有任何原因无法实现? - William Miller
可以做到。只是有点痛苦。我本以为由于Tensorboard提供了按顺序查看图像的功能,可能会有一种简单的方法将图像序列转换为gif。 - Rylan Schaeffer
显示剩余3条评论

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