我有一系列的图片,我想从中创建一个视频。理想情况下,我可以为每帧指定帧持续时间,但固定的帧速率也可以。我在wxPython中这样做,所以我可以渲染到wxDC或我可以将图像保存到文件,如PNG。是否有一个Python库,将允许我创建一个视频(AVI, MPG等)或一个动画GIF从这些帧?

编辑:我已经尝试过PIL,它似乎不起作用。有人能用这个结论来纠正我吗?这个链接似乎支持我关于PIL的结论:http://www.somethinkodd.com/oddthinking/2005/12/06/python-imaging-library-pil-and-animated-gifs/


当前回答

Smart Manoj回答:从文件夹中的所有图像制作一个.mp4电影

安装:

pip install imageio-ffmpeg
pip install imageio

代码:

import os
import imageio

root = r'path_to_folder_with_images'

images = []    
for subdir, dirs, files in os.walk(root):
    for file in files:
        images.append(imageio.imread(os.path.join(root,file)))

savepath = r'path_to_save_folder'
imageio.mimsave(os.path.join(savepath,'movie.mp4'), images)

PS:确保你的“文件”列表按照你想要的方式排序,如果你已经相应地保存了你的图像,你会节省一些时间

其他回答

真是不可思议……所有人都提出了一些特殊的包来播放动画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()

您可以设置自己的方法来停止动画。如果你想要完整版本的播放/暂停/退出按钮,请告诉我。

注意:我不确定连续帧是从内存还是从文件(磁盘)读取的。在第二种情况下,如果它们都一次读取并保存到一个数组(列表)中,那么效率会更高。(我没兴趣知道!:)

我使用images2gif.py,这很容易使用。它似乎是文件大小的两倍。

26个110kb的PNG文件,我期望26*110kb = 2860kb,但my_gif.GIF是5.7mb

另外,因为GIF是8位的,好看的png在GIF中变得有点模糊

下面是我使用的代码:

__author__ = 'Robert'
from images2gif import writeGif
from PIL import Image
import os

file_names = sorted((fn for fn in os.listdir('.') if fn.endswith('.png')))
#['animationframa.png', 'animationframb.png', 'animationframc.png', ...] "

images = [Image.open(fn) for fn in file_names]

print writeGif.__doc__
# writeGif(filename, images, duration=0.1, loops=0, dither=1)
#    Write an animated gif from the specified images.
#    images should be a list of numpy arrays of PIL images.
#    Numpy images of type float should have pixels between 0 and 1.
#    Numpy images of other types are expected to have values between 0 and 255.


#images.extend(reversed(images)) #infinit loop will go backwards and forwards.

filename = "my_gif.GIF"
writeGif(filename, images, duration=0.2)
#54 frames written
#
#Process finished with exit code 0

以下是26帧中的3帧:

缩小图像会减小尺寸:

size = (150,150)
for im in images:
    im.thumbnail(size, Image.ANTIALIAS)

你试过PyMedia吗?我不是100%确定,但看起来这个教程的例子针对的是你的问题。

对我来说,使它工作的最简单的事情是在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。

我偶然发现了PIL的ImageSequence模块,它提供了更好(更标准)的GIF动画。这次我也使用了Tk的after()方法,这比time.sleep()更好。

from Tkinter import * 
from PIL import Image, ImageTk, ImageSequence

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 = im.info['duration'] # Delay used in the GIF file 
lbl = Label(image=img); lbl.pack() # Create a label where to display images
play = True;
while play:
  for frame in ImageSequence.Iterator(im):
    if not play: break 
    root.after(delay);
    img = ImageTk.PhotoImage(frame)
    lbl.config(image=img); root.update() # Show the new frame/image

root.mainloop()