使用 Python 以编程方式生成视频或动画 GIF?

2025-01-09 08:47:00
admin
原创
108
摘要:问题描述:我有一系列图像,我想用它们制作视频。理想情况下,我可以为每一帧指定一个帧持续时间,但固定的帧速率也可以。我在 wxPython 中执行此操作,因此我可以渲染到 wxDC,也可以将图像保存到文件(如 PNG)。是否有 Python 库允许我从这些帧制作视频(AVI、MPG 等)或动画 GIF?编辑:我...

问题描述:

我有一系列图像,我想用它们制作视频。理想情况下,我可以为每一帧指定一个帧持续时间,但固定的帧速率也可以。我在 wxPython 中执行此操作,因此我可以渲染到 wxDC,也可以将图像保存到文件(如 PNG)。是否有 Python 库允许我从这些帧制作视频(AVI、MPG 等)或动画 GIF?

编辑:我已经尝试过 PIL,但似乎不起作用。有人可以纠正我的这个结论或建议另一个工具包吗?此链接似乎支持我关于 PIL 的结论: http: //www.somethinkodd.com/oddthinking/2005/12/06/python-imaging-library-pil-and-animated-gifs/


解决方案 1:

我建议不要使用 visvis 的 images2gif,因为它与 PIL/Pillow 存在问题并且没有积极维护(我应该知道,因为我是作者)。

相反,请使用imageio,它的开发是为了解决这个问题以及更多问题,并且打算保留下来。

快速而肮脏的解决方案:

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)

要编辑每帧持续时间,可以使用 kwarg duration以毫秒为单位)或fps。这些 kwarg 可以用于mimsave()get_writer()

解决方案 2:

以下是仅使用PIL (使用以下方式安装:)的方法pip install Pillow

import glob
import contextlib
from PIL import Image

# filepaths
fp_in = "/path/to/image_*.png"
fp_out = "/path/to/image.gif"

# use exit stack to automatically close opened images
with contextlib.ExitStack() as stack:

    # lazily load images
    imgs = (stack.enter_context(Image.open(f))
            for f in sorted(glob.glob(fp_in)))

    # extract  first image from iterator
    img = next(imgs)

    # https://pillow.readthedocs.io/en/stable/handbook/image-file-formats.html#gif
    img.save(fp=fp_out, format='GIF', append_images=imgs,
             save_all=True, duration=200, loop=0)

查看文档:https ://pillow.readthedocs.io/en/stable/handbook/image-file-formats.html#gif

解决方案 3:

好吧,现在我正在使用 ImageMagick。我将帧保存为 PNG 文件,然后从 Python 调用 ImageMagick 的 convert.exe 来创建动画 GIF。这种方法的好处是,我可以为每个帧单独指定帧持续时间。不幸的是,这取决于机器上是否安装了 ImageMagick。他们有一个 Python 包装器,但它看起来很糟糕,而且不受支持。仍然接受其他建议。

解决方案 4:

截至 2009 年 6 月,最初引用的博客文章在评论中提供了一种创建动画 GIF 的方法。下载脚本images2gif.py(以前称为images2gif.py,由 @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)

解决方案 5:

我使用了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 帧:

这是 26 帧中的 3 帧

缩小图像会减小尺寸:

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

较小的 gif

解决方案 6:

要制作视频,你可以使用opencv,

#load your frames
frames = ...
#create a video writer
writer = cvCreateVideoWriter(filename, -1, fps, frame_size, is_color=1)
#and write your frames in a loop if you want
cvWriteFrame(writer, frames[i])

解决方案 7:

我偶然看到了这篇文章,但没有任何解决方案有效,所以这是我的解决方案,确实有效

到目前为止,其他解决方案存在的问题:

1)没有关于如何修改持续时间的明确解决方案

2)没有解决无序目录迭代的问题,这对于 GIF 至关重要

3)没有解释如何为 python 3 安装 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

解决方案 8:

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)  

标识不同文件名的索引的起始和终止值+1

imgs = glob.glob("*.png") #do this if you want to read all files ending with .png

我的文件是:snap596.png,snap597.png ...... snap690.png

frames = []
for i in imgs:
    new_frame = Image.open(i)
    frames.append(new_frame)

保存为永久循环的 GIF 文件

frames[0].save('fire3_PIL.gif', format='GIF',
    append_images=frames[1:],
    save_all=True,
    duration=300, loop=0)

我发现 imageio 存在闪烁问题,此方法解决了该问题。

解决方案 9:

安装

pip install imageio-ffmpeg
pip install imageio

代码

import imageio
images = []
for filename in filenames:
    images.append(imageio.imread(filename))
imageio.mimsave('movie.mp4', images)

与 gif 相比,保存为 mp4 时质量有所提高,大小也从 8Mb 减少到 80Kb

解决方案 10:

就像 Warren去年说的那样,这是一个老问题。由于人们似乎仍在查看该页面,我想将他们重定向到更现代的解决方案。就像 blakev在这里说的那样,github上有一个 Pillow 示例。

 import ImageSequence
 import Image
 import gifmaker
 sequence = []

 im = Image.open(....)

 # im is your original image
 frames = [frame.copy() for frame in ImageSequence.Iterator(im)]

 # write GIF animation
 fp = open("out.gif", "wb")
 gifmaker.makedelta(fp, frames)
 fp.close()

注意:此示例已过时(gifmaker不是可导入的模块,仅是脚本)。Pillow 有一个GifImagePlugin(其源代码在 GitHub 上),但ImageSequence 上的文档似乎表明支持有限(仅供阅读)

解决方案 11:

老问题,有很多好的答案,但可能仍然对另一种选择感兴趣......

numpngw我最近在 github 上发布的模块(https://github.com/WarrenWeckesser/numpngw )可以从 numpy 数组写入动画 PNG 文件。(更新numpngw现在在 pypi 上: https: //pypi.python.org/pypi/numpngw。)

例如这个脚本:

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

您需要一个支持动画 PNG(直接支持或者通过插件支持)的浏览器才能观看动画。

解决方案 12:

正如上面一位成员提到的,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)

使用此方法的示例 GIF

解决方案 13:

虽然它不是一个 Python 库,但是 mencoder 可以做到这一点:从多个输入图像文件进行编码。您可以像这样从 Python 执行 mencoder:

import os

os.system("mencoder ...")

解决方案 14:

您尝试过PyMedia吗?我不是 100% 确定,但看起来本教程示例针对您的问题。

解决方案 15:

使用 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)

解决方案 16:

对我来说,让它工作的最简单的方法是在 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。

解决方案 17:

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:确保您的“文件”列表按您想要的方式排序,如果您已经按顺序保存了图像,您将节省一些时间

解决方案 18:

可以通过从与图片文件序列相同的文件夹中运行两行 Python 脚本来完成此任务。对于 png 格式的文件,脚本为 -

from scitools.std import movie
movie('*.png',fps=1,output_file='thisismygif.gif')

解决方案 19:

我正在寻找一行代码,发现以下内容适用于我的应用程序。以下是我所做的:

第一步: 从下面的链接安装 ImageMagick

https://www.imagemagick.org/script/download.php

在此处输入图片描述

第二步: 将 cmd 行指向放置图像(在我的情况下为 .png 格式)的文件夹

在此处输入图片描述

第三步: 输入以下命令

magick -quality 100 *.png outvideo.mpeg

在此处输入图片描述

感谢 FogleBird 的想法!

解决方案 20:

制作 GIF 的简单函数:

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()

解决方案 21:

我刚刚尝试了以下方法并且非常有用:

首先下载库Figtodatimages2gif到本地目录。

其次,将图形收集到一个数组中,并将其转换为动画 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)

解决方案 22:

我偶然发现了 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()

解决方案 23:

这真是令人难以置信......所有人都在提议使用一些特殊的包来播放动画 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()

您可以自行设置停止动画的方式。如果您想要获得带有播放/暂停/退出按钮的完整版本,请告诉我。

注意:我不确定连续帧是从内存还是从文件(磁盘)读取的。在第二种情况下,如果一次性读取所有帧并保存到数组(列表)中,效率会更高。(我不太想知道!:)

解决方案 24:

我知道您询问将图像转换为 gif 的问题;但是,如果原始格式是 MP4,则可以使用FFmpeg:

ffmpeg -i input.mp4 output.gif
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用