我有一系列的图片,我想从中创建一个视频。理想情况下,我可以为每帧指定帧持续时间,但固定的帧速率也可以。我在wxPython中这样做,所以我可以渲染到wxDC或我可以将图像保存到文件,如PNG。是否有一个Python库,将允许我创建一个视频(AVI, MPG等)或一个动画GIF从这些帧?
编辑:我已经尝试过PIL,它似乎不起作用。有人能用这个结论来纠正我吗?这个链接似乎支持我关于PIL的结论:http://www.somethinkodd.com/oddthinking/2005/12/06/python-imaging-library-pil-and-animated-gifs/
对我来说,使它工作的最简单的事情是在Python中调用shell命令。
如果您的图像存储为dummy_image_1.png, dummy_image_2.png…dummy_image_N.png,然后你可以使用函数:
import subprocess
def grid2gif(image_str, output_gif):
str1 = 'convert -delay 100 -loop 1 ' + image_str + ' ' + output_gif
subprocess.call(str1, shell=True)
执行:
grid2gif("dummy_image*.png", "my_output.gif")
这将构造你的gif文件my_output.gif。
正如上面提到的一个成员,imageio是一种很好的方法。imageio还允许你设置帧速率,我实际上用Python写了一个函数,允许你设置最后一帧的暂停。我将此函数用于科学动画,其中循环是有用的,但立即重新启动不是。下面是链接和函数:
如何使用Python制作GIF
import matplotlib.pyplot as plt
import os
import imageio
def gif_maker(gif_name,png_dir,gif_indx,num_gifs,dpi=90):
# make png path if it doesn't exist already
if not os.path.exists(png_dir):
os.makedirs(png_dir)
# save each .png for GIF
# lower dpi gives a smaller, grainier GIF; higher dpi gives larger, clearer GIF
plt.savefig(png_dir+'frame_'+str(gif_indx)+'_.png',dpi=dpi)
plt.close('all') # comment this out if you're just updating the x,y data
if gif_indx==num_gifs-1:
# sort the .png files based on index used above
images,image_file_names = [],[]
for file_name in os.listdir(png_dir):
if file_name.endswith('.png'):
image_file_names.append(file_name)
sorted_files = sorted(image_file_names, key=lambda y: int(y.split('_')[1]))
# define some GIF parameters
frame_length = 0.5 # seconds between frames
end_pause = 4 # seconds to stay on last frame
# loop through files, join them to image array, and write to GIF called 'wind_turbine_dist.gif'
for ii in range(0,len(sorted_files)):
file_path = os.path.join(png_dir, sorted_files[ii])
if ii==len(sorted_files)-1:
for jj in range(0,int(end_pause/frame_length)):
images.append(imageio.imread(file_path))
else:
images.append(imageio.imread(file_path))
# the duration is the time spent on each image (1/duration is frame rate)
imageio.mimsave(gif_name, images,'GIF',duration=frame_length)
我看到这篇文章,没有一个解决方案是有效的,所以这里是我的解决方案是有效的
到目前为止,其他解决方案存在的问题:
1)对于如何修改持续时间没有明确的解决方案
2)对于乱序目录迭代没有解决方案,而乱序目录迭代对于动图是必不可少的
3)没有说明如何为python3安装imageio
像这样安装imageio: python3 -m PIP Install imageio
注意:你要确保你的帧在文件名中有某种索引,这样它们就可以排序,否则你就无法知道GIF从哪里开始或结束
import imageio
import os
path = '/Users/myusername/Desktop/Pics/' # on Mac: right click on a folder, hold down option, and click "copy as pathname"
image_folder = os.fsencode(path)
filenames = []
for file in os.listdir(image_folder):
filename = os.fsdecode(file)
if filename.endswith( ('.jpeg', '.png', '.gif') ):
filenames.append(filename)
filenames.sort() # this iteration technique has no built in order, so sort the frames
images = list(map(lambda filename: imageio.imread(filename), filenames))
imageio.mimsave(os.path.join('movie.gif'), images, duration = 0.04) # modify duration as needed
真是不可思议……所有人都提出了一些特殊的包来播放动画GIF,目前它可以用Tkinter和经典的PIL模块!
这是我自己的GIF动画方法(我之前创建的)。非常简单:
from Tkinter import *
from PIL import Image, ImageTk
from time import sleep
def stop(event):
global play
play = False
exit()
root = Tk()
root.bind("<Key>", stop) # Press any key to stop
GIFfile = {path_to_your_GIF_file}
im = Image.open(GIFfile); img = ImageTk.PhotoImage(im)
delay = float(im.info['duration'])/1000; # Delay used in the GIF file
lbl = Label(image=img); lbl.pack() # Create a label where to display images
play = True; frame = 0
while play:
sleep(delay);
frame += 1
try:
im.seek(frame); img = ImageTk.PhotoImage(im)
lbl.config(image=img); root.update() # Show the new frame/image
except EOFError:
frame = 0 # Restart
root.mainloop()
您可以设置自己的方法来停止动画。如果你想要完整版本的播放/暂停/退出按钮,请告诉我。
注意:我不确定连续帧是从内存还是从文件(磁盘)读取的。在第二种情况下,如果它们都一次读取并保存到一个数组(列表)中,那么效率会更高。(我没兴趣知道!:)