我目前正在尝试保存由我的模拟生成的mayavi动画,所以我不必每次都重新运行代码来查看它。
plt = points3d(x_coord, y_coord, z_coord)
msplt = plt.mlab_source
@mlab.animate(delay=100)
def anim():
f = mlab.gcf()
while True:
#animation updates here
msplt.set(x = x_coord, y = y_coord, z = z_coord)
yield
anim()
mlab.savefig(filename = 'ani.mp4')
mlab.show()
我试着通过管道编辑器保存它,只是得到它所在的框架的静止,和mlab。Savefig不会生成文件。
下面的方法将同时用于查看动画,将每帧保存为'png',然后将它们转换为电影,但是在这种情况下,放弃播放动画,只是循环使用数据保存图形,然后使用这种方法制作视频可能是最快的。
from mayavi import mlab
import numpy as np
import os
# Output path for you animation images
out_path = './'
out_path = os.path.abspath(out_path)
fps = 20
prefix = 'ani'
ext = '.png'
# Produce some nice data.
n_mer, n_long = 6, 11
pi = np.pi
dphi = pi/1000.0
phi = np.arange(0.0, 2*pi + 0.5*dphi, dphi, 'd')
mu = phi*n_mer
x = np.cos(mu)*(1+np.cos(n_long*mu/n_mer)*0.5)
y = np.sin(mu)*(1+np.cos(n_long*mu/n_mer)*0.5)
z = np.sin(n_long*mu/n_mer)*0.5
# Init plot
plt = mlab.points3d(x[0], y[0], z[0])
padding = len(str(len(x)))
# Define data source and update routine
msplt = plt.mlab_source
@mlab.animate(delay=10)
def anim():
f = mlab.gcf()
for i in range(len(x)):
#animation updates here
msplt.set(x=x[i], y=y[i], z=z[i])
# create zeros for padding index positions for organization
zeros = '0'*(padding - len(str(i)))
# concate filename with zero padded index number as suffix
filename = os.path.join(out_path, '{}_{}{}{}'.format(prefix, zeros, i, ext))
mlab.savefig(filename=filename)
yield
anim()
mlab.view(distance=15)
mlab.show()
import subprocess
ffmpeg_fname = os.path.join(out_path, '{}_%0{}d{}'.format(prefix, padding, ext))
cmd = 'ffmpeg -f image2 -r {} -i {} -vcodec mpeg4 -y {}.mp4'.format(fps,
ffmpeg_fname,
prefix)
print cmd
subprocess.check_output(['bash','-c', cmd])
# Remove temp image files with extension
[os.remove(f) for f in os.listdir(out_path) if f.endswith(ext)]
除了将图像保存到磁盘上然后将它们拼接在一起之外,还可以使用python-ffmpeg
包将它们直接管道到ffmpeg。
import ffmpeg
# Set up the figure
width = 200
height = 200
mlab.options.offscreen = True # Stops the view window popping up and makes sure you get the correct size screenshots.
fig = mlab.figure(size=(width, height))
# ... set up the scene ...
# Define update function
def update_scene(idx):
# -- update the scene
return
# Initialise ffmpeg process
output_args = {
'pix_fmt': 'yuv444p',
'vcodec': 'libx264',
'r': 25,
}
process = (
ffmpeg
.input('pipe:', format='rawvideo', pix_fmt='rgb24', s=f'{width}x{height}')
.output('animation.mp4', **output_args)
.overwrite_output()
.run_async(pipe_stdin=True)
)
fig.scene._lift() # Throws an error without this.
for i in range(100):
update_scene(i)
screenshot = mlab.screenshot(mode='rgb', antialiased=True)
frame = Image.fromarray(screenshot, 'RGB')
process.stdin.write(frame.tobytes())
# Flush video
process.stdin.close()
process.wait()