在Python中以编程方式生成视频或动画GIF?
我有一系列的图像,我想创建一个视频。理想情况下,我可以为每个帧指定一个帧持续时间,但固定的帧速率也可以。我在wxPython中执行此操作,因此我可以渲染到wxDC或将图像保存到文件中,如PNG。是否有Python库允许我从这些帧创建视频(AVI、MPG等)或动画GIF在Python中以编程方式生成视频或动画GIF?,python,video,wxpython,animated-gif,Python,Video,Wxpython,Animated Gif,我有一系列的图像,我想创建一个视频。理想情况下,我可以为每个帧指定一个帧持续时间,但固定的帧速率也可以。我在wxPython中执行此操作,因此我可以渲染到wxDC或将图像保存到文件中,如PNG。是否有Python库允许我从这些帧创建视频(AVI、MPG等)或动画GIF 编辑:我已经试过PIL,但它似乎不起作用。有人能用这个结论纠正我吗?或者建议另一个工具包?这个链接似乎支持了我关于PIL的结论:好吧,现在我正在使用ImageMagick。我将帧保存为PNG文件,然后从Python中调用Image
编辑:我已经试过PIL,但它似乎不起作用。有人能用这个结论纠正我吗?或者建议另一个工具包?这个链接似乎支持了我关于PIL的结论:好吧,现在我正在使用ImageMagick。我将帧保存为PNG文件,然后从Python中调用ImageMagick的convert.exe创建动画GIF。这种方法的好处是,我可以为每个帧单独指定一个帧持续时间。不幸的是,这取决于机器上安装的ImageMagick。他们有一个Python包装器,但它看起来很糟糕,不受支持。仍然可以接受其他建议。它不是python库,但mencoder可以做到这一点:。您可以从python中执行mencoder,如下所示:
import os
os.system("mencoder ...")
你试过了吗?我不是100%确定,但它似乎针对您的问题。要创建视频,您可以使用
截至2009年6月,最初引用的博客文章已经有了一种制作动画GIF的方法。下载脚本(以前,由@geographika提供更新) 然后,要反转gif中的帧,例如:
#!/usr/bin/env python
from PIL import Image, ImageSequence
import sys, os
filename = sys.argv[1]
im = Image.open(filename)
original_duration = im.info['duration']
frames = [frame.copy() for frame in ImageSequence.Iterator(im)]
frames.reverse()
from images2gif import writeGif
writeGif("reverse_" + os.path.basename(filename), frames, duration=original_duration/1000.0, dither=0)
我用的是很容易用的。不过,它似乎确实使文件大小增加了一倍
26个110kb的PNG文件,我期望26*110kb=2860kb,但我的_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)
该任务可以通过从与图片文件序列相同的文件夹中运行两行python脚本来完成。对于png格式的文件,脚本为-
from scitools.std import movie
movie('*.png',fps=1,output_file='thisismygif.gif')
老问题,很多好答案,但可能还有其他选择的兴趣 我最近在github()上安装的
numpngw
模块可以从numpy数组编写动画PNG文件。(更新:numpngw
现在位于pypi:)
例如,此脚本:
import numpy as np
import numpngw
img0 = np.zeros((64, 64, 3), dtype=np.uint8)
img0[:32, :32, :] = 255
img1 = np.zeros((64, 64, 3), dtype=np.uint8)
img1[32:, :32, 0] = 255
img2 = np.zeros((64, 64, 3), dtype=np.uint8)
img2[32:, 32:, 1] = 255
img3 = np.zeros((64, 64, 3), dtype=np.uint8)
img3[:32, 32:, 2] = 255
seq = [img0, img1, img2, img3]
for img in seq:
img[16:-16, 16:-16] = 127
img[0, :] = 127
img[-1, :] = 127
img[:, 0] = 127
img[:, -1] = 127
numpngw.write_apng('foo.png', seq, delay=250, use_palette=True)
创建:
您需要一个支持动画PNG(直接或带有插件)的浏览器来查看动画。在windows7、python2.7、opencv 3.0中,我可以使用以下功能:
import cv2
import os
vvw = cv2.VideoWriter('mymovie.avi',cv2.VideoWriter_fourcc('X','V','I','D'),24,(640,480))
frameslist = os.listdir('.\\frames')
howmanyframes = len(frameslist)
print('Frames count: '+str(howmanyframes)) #just for debugging
for i in range(0,howmanyframes):
print(i)
theframe = cv2.imread('.\\frames\\'+frameslist[i])
vvw.write(theframe)
我建议不要使用visvis的Images2GF,因为它与PIL/枕头有问题,并且没有积极维护(我应该知道,因为我是作者) 相反,请使用,这是为了解决这个问题和更多,并打算留下来 快速而肮脏的解决方案:
import imageio
images = []
for filename in filenames:
images.append(imageio.imread(filename))
imageio.mimsave('/path/to/movie.gif', images)
对于较长的电影,请使用流媒体方式:
import imageio
with imageio.get_writer('/path/to/movie.gif', mode='I') as writer:
for filename in filenames:
image = imageio.imread(filename)
writer.append_data(image)
就像沃伦去年说的,这是一个老问题。由于人们似乎仍在查看页面,我想将他们重定向到更现代的解决方案。正如blakev所说,这上面有一个枕头的例子
注意:此示例已过时(
gifmaker
不是可导入的模块,只是一个脚本)。枕头有一个(其来源是),但似乎表示支持有限(仅限阅读)我刚刚尝试了以下方法,非常有用:
首先将库Figtodat
和images2gif
下载到本地目录
其次,收集阵列中的图形并将其转换为动画gif:
import sys
sys.path.insert(0,"/path/to/your/local/directory")
import Figtodat
from images2gif import writeGif
import matplotlib.pyplot as plt
import numpy
figure = plt.figure()
plot = figure.add_subplot (111)
plot.hold(False)
# draw a cardinal sine plot
images=[]
y = numpy.random.randn(100,5)
for i in range(y.shape[1]):
plot.plot (numpy.sin(y[:,i]))
plot.set_ylim(-3.0,3)
plot.text(90,-2.5,str(i))
im = Figtodat.fig2img(figure)
images.append(im)
writeGif("images.gif",images,duration=0.3,dither=0)
对我来说,最简单的事情就是在Python中调用shell命令 如果您的图像被存储,例如dummy\u image\u 1.png、dummy\u image\u 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。我正在寻找一个单行代码,发现以下代码适用于我的应用程序。以下是我所做的: 第一步:从下面的链接安装ImageMagick 第二步:将cmd行指向放置图像(在我的例子中是.png格式)的文件夹 第三步:键入以下命令
谢谢雾鸟的主意 真是难以置信。。。所有人都在为播放动画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()
从Tkinter导入*
从PIL导入图像,ImageTk
从时间上导入睡眠
def停止(事件):
全球游戏
播放=错误
退出()
root=Tk()
root.bind(“,stop)#按任意键停止
GIFfile={path_to_your_GIF_file}
im=Image.open(文件);img=图像tk.照片图像(im)
延迟=浮动(即时信息['duration'])/1000;#GIF文件中使用的延迟
lbl=标签(图像=img);lbl.pack()#创建用于显示图像的标签
玩=真;帧=0
游戏时:
睡眠(延迟);
帧+=1
尝试:
im.seek(帧);img=图像tk.照片图像(im)
lbl.config(image=img);root.update()#显示新的帧/图像
除EOFError外:
帧=0#重新启动
root.mainloop()
您可以设置自己停止动画的方法。如果您想获得带有播放/暂停/退出按钮的完整版本,请告诉我
注意:我不确定连续帧是从内存还是从文件(磁盘)读取的。在第二种情况下,如果它们都同时读取并保存到一个数组(列表)中,则效率会更高。(我不太想知道!:)我发现了PIL的ImageSequence模块,它提供了更好(更标准)的GIF信息。这次我还使用了Tk的after()方法,它比time.sleep()好
从Tkinter导入*
从PIL导入图像、ImageTk、ImageSequence
def停止(事件):
全球游戏
玩
grid2gif("dummy_image*.png", "my_output.gif")
magick -quality 100 *.png outvideo.mpeg
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()
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()
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)
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
import imageio
import pathlib
from datetime import datetime
def make_gif(image_directory: pathlib.Path, frames_per_second: float, **kwargs):
"""
Makes a .gif which shows many images at a given frame rate.
All images should be in order (don't know how this works) in the image directory
Only tested with .png images but may work with others.
:param image_directory:
:type image_directory: pathlib.Path
:param frames_per_second:
:type frames_per_second: float
:param kwargs: image_type='png' or other
:return: nothing
"""
assert isinstance(image_directory, pathlib.Path), "input must be a pathlib object"
image_type = kwargs.get('type', 'png')
timestampStr = datetime.now().strftime("%y%m%d_%H%M%S")
gif_dir = image_directory.joinpath(timestampStr + "_GIF.gif")
print('Started making GIF')
print('Please wait... ')
images = []
for file_name in image_directory.glob('*.' + image_type):
images.append(imageio.imread(image_directory.joinpath(file_name)))
imageio.mimsave(gif_dir.as_posix(), images, fps=frames_per_second)
print('Finished making GIF!')
print('GIF can be found at: ' + gif_dir.as_posix())
def main():
fps = 2
png_dir = pathlib.Path('C:/temp/my_images')
make_gif(png_dir, fps)
if __name__ == "__main__":
main()
ffmpeg -i input.mp4 output.gif
pip install imageio-ffmpeg
pip install imageio
import imageio
images = []
for filename in filenames:
images.append(imageio.imread(filename))
imageio.mimsave('movie.mp4', images)
from PIL import Image
import glob #use it if you want to read all of the certain file type in the directory
imgs=[]
for i in range(596,691):
imgs.append("snap"+str(i)+'.png')
print("scanned the image identified with",i)
imgs = glob.glob("*.png") #do this if you want to read all files ending with .png
frames = []
for i in imgs:
new_frame = Image.open(i)
frames.append(new_frame)
frames[0].save('fire3_PIL.gif', format='GIF',
append_images=frames[1:],
save_all=True,
duration=300, loop=0)