Python 如何从matplotlib中的图像阵列制作视频?

Python 如何从matplotlib中的图像阵列制作视频?,python,matplotlib,animation,video-processing,Python,Matplotlib,Animation,Video Processing,我有几张图片显示了事物是如何随时间变化的。我使用以下代码将它们可视化为同一绘图上的多个图像: import matplotlib.pyplot as plt import matplotlib.cm as cm img = [] # some array of images fig = plt.figure() for i in xrange(6): fig.add_subplot(2, 3, i + 1) plt.imshow(img[i], cmap=cm.Greys_r)

我有几张图片显示了事物是如何随时间变化的。我使用以下代码将它们可视化为同一绘图上的多个图像:

import matplotlib.pyplot as plt
import matplotlib.cm as cm

img = [] # some array of images
fig = plt.figure()
for i in xrange(6):
    fig.add_subplot(2, 3, i + 1)
    plt.imshow(img[i], cmap=cm.Greys_r)

plt.show()
然后得到如下结果:


这是好的,但我宁愿动画他们得到。如何使用python实现这一点,最好(不一定)使用matplotlib,例如,您可以使用
plt.savefig(“文件%d.png”%I)
将图像导出到png,然后使用ffmpeg生成视频


对于我自己的未来,以下是我的结局:

def generate_video(img):
    for i in xrange(len(img)):
        plt.imshow(img[i], cmap=cm.Greys_r)
        plt.savefig(folder + "/file%02d.png" % i)

    os.chdir("your_folder")
    subprocess.call([
        'ffmpeg', '-framerate', '8', '-i', 'file%02d.png', '-r', '30', '-pix_fmt', 'yuv420p',
        'video_name.mp4'
    ])
    for file_name in glob.glob("*.png"):
        os.remove(file_name)

我实现了一个方便的脚本,适合你和新来者。试试看

例如:

imagelist = YOUR-IMAGE-LIST
def redraw_fn(f, axes):
    img = imagelist[f]
    if not redraw_fn.initialized:
        redraw_fn.im = axes.imshow(img, animated=True)
        redraw_fn.initialized = True
    else:
        redraw_fn.im.set_array(img)
redraw_fn.initialized = False

videofig(len(imagelist), redraw_fn, play_fps=30)

另一种解决方案是使用
matplotlib.animation
中的
AnimationArtist
,如中所述。根据您的示例进行调整将是

import matplotlib.pyplot as plt
import matplotlib.cm as cm
import matplotlib.animation as animation

img = [] # some array of images
frames = [] # for storing the generated images
fig = plt.figure()
for i in xrange(6):
    frames.append([plt.imshow(img[i], cmap=cm.Greys_r,animated=True)])

ani = animation.ArtistAnimation(fig, frames, interval=50, blit=True,
                                repeat_delay=1000)
# ani.save('movie.mp4')
plt.show()

您可以尝试延迟按顺序绘制图像(帧)。如果有许多帧,在
plt.pause()
函数中减少帧之间的等待时间可能是有意义的

# need this line if you're using jupyter notebooks
%matplotlib notebook

x = [] # Some array of images
fig = plt.figure()
viewer = fig.add_subplot(111)
plt.ion() # Turns interactive mode on (probably unnecessary)
fig.show() # Initially shows the figure

for i in range(len(x)):
    viewer.clear() # Clears the previous image
    viewer.imshow(x[i]) # Loads the new image
    plt.pause(.1) # Delay in seconds
    fig.canvas.draw() # Draws the image to the screen

您可以使用
Agg
接口从matplotlib导出图像

参见以下示例:

以下是您的完整代码:

# imports
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import cv2

# Use Agg backend for canvas
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas

# create OpenCV video writer
video = cv2.VideoWriter('video.mp4', cv2.VideoWriter_fourcc('A','V','C','1'), 1, (mat.shape[0],mat.shape[1]))

# loop over your images
for i in xrange(len(img)):

    fig = plt.figure()
    plt.imshow(img[i], cmap=cm.Greys_r)

    # put pixel buffer in numpy array
    canvas = FigureCanvas(fig)
    canvas.draw()
    mat = np.array(canvas.renderer._renderer)
    mat = cv2.cvtColor(mat, cv2.COLOR_RGB2BGR)

    # write frame to video
    video.write(mat)

# close video writer
cv2.destroyAllWindows()
video.release()

这是一个可复制的函数,如果您正在处理长视频并且正在使用流式迭代器(来自)

输入import Iterator,可选,Tuple
从pathlib导入路径
将matplotlib导入为mpl
将matplotlib.pyplot作为plt导入
将numpy作为np导入
def write_动画(
itr:迭代器[np.array],
输出文件:路径,
dpi:int=50,
fps:int=30,
标题:str=“动画”,
注释:可选[str]=无,
编写器:str=“ffmpeg”,
)->无:
“”“函数,用于从输入张量流写入动画。”。
Args:
itr:图像迭代器,生成具有形状(H、W、C)的图像。
输出文件:输出文件的路径。
dpi:输出图像的每英寸点数。
fps:视频的每秒帧数。
标题:视频元数据的标题。
注释:视频元数据的注释。
编写器:要使用的Matplotlib动画编写器(如果使用
默认设置,请确保已在计算机上安装“ffmpeg”
系统)。
"""
第一次=下一次(itr)
高度、宽度=第一个形状
图,ax=plt.子批次(图尺寸=(宽度/dpi,高度/dpi))
#确保图像周围没有多余的空间。
图:子批次调整(
左=0,
底部=0,
右=1,
top=1,
wspace=None,
hspace=None,
)
#使用给定的元数据创建编写器。
Writer=mpl.animation.writers[Writer]
元数据={
“头衔”:头衔,
“艺术家”:“姓名”,
“评论”:评论,
}
mpl_writer=编写器(
fps=fps,
metadata={k:v代表k,v在metadata.items()中,如果v不是None},
)
使用mpl_writer.saving(图,out_文件,dpi=dpi):
im=ax.imshow(first\u img,interpolation=“nearest”)
mpl_writer.grab_frame()
对于itr中的img:
im.set_数据(img)
mpl_writer.grab_frame()

除了提供代码外,最好能解释解决方案并添加一些细节。这里的ims是什么?@PyWalker2797 a打字错误。现在应该修好了。