J'ai une série d'images dont je veux créer une vidéo. Idéalement, je pourrais spécifier une durée d'image pour chaque image, mais une cadence fixe conviendrait également. Je fais cela dans wxPython, afin que je puisse rendre à un wxDC ou je peux enregistrer les images dans des fichiers, tels que PNG. Existe-t-il une bibliothèque Python qui me permette de créer une vidéo (AVI, MPG, etc.) ou un GIF animé à partir de ces images?
Edit: J'ai déjà essayé PIL et cela ne semble pas fonctionner. Quelqu'un peut-il me corriger avec cette conclusion ou suggérer une autre boîte à outils? Ce lien semble confirmer ma conclusion à propos de PIL: http://www.somethinkodd.com/oddthinking/2005/12/06/python-imaging-library-pil-and-animated-gifs/
Eh bien, maintenant j'utilise ImageMagick. J'enregistre mes images sous forme de fichiers PNG, puis j'appelle le fichier convert.exe d'ImageMagick à partir de Python pour créer un fichier GIF animé. La bonne chose à propos de cette approche est que je peux spécifier une durée de trame pour chaque trame individuellement. Malheureusement, cela dépend de l'installation d'ImageMagick sur la machine. Ils ont un wrapper Python mais il a l'air plutôt nul et non supporté. Toujours ouvert à d'autres suggestions.
Je vous recommande de ne pas utiliser images2gif de visvis car il a des problèmes avec PIL/Pillow et qu'il n'est pas entretenu de manière active (je devrais le savoir, car je suis l'auteur).
Au lieu de cela, veuillez utiliser imageio , qui a été développé pour résoudre ce problème et plus encore, et qui est destiné à rester.
Solution rapide et sale:
import imageio
images = []
for filename in filenames:
images.append(imageio.imread(filename))
imageio.mimsave('/path/to/movie.gif', images)
Pour les films plus longs, utilisez la méthode de diffusion en continu:
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)
Depuis juin 2009, l'article de blog cité à l'origine dispose d'une méthode pour créer des GIF animés dans les commentaires . Téléchargez le script images2gif.py (anciennement images2gif.py , mise à jour avec la permission de @geographika).
Ensuite, pour inverser les images dans un gif, par exemple:
#!/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)
J'ai utilisé images2gif.py qui était facile à utiliser. Il semble cependant que la taille du fichier a doublé ..
26 fichiers PNG de 110 Ko, je m'attendais à 26 * 110 Ko = 2860 Ko, mais mon_gif.GIF était de 5,7 Mo
Aussi parce que le GIF était de 8 bits, le png de Nice est devenu un peu flou dans le GIF
Voici le code que j'ai utilisé:
__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
Voici 3 des 26 cadres:
rétrécir les images réduit la taille:
size = (150,150)
for im in images:
im.thumbnail(size, Image.ANTIALIAS)
Pour créer une vidéo, vous pouvez utiliser 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])
Ce n'est pas une bibliothèque python, mais mencoder peut le faire: Encodage à partir de plusieurs fichiers image en entrée . Vous pouvez exécuter mencoder à partir de python comme ceci:
import os
os.system("mencoder ...")
Avec windows7, python2.7, opencv 3.0, ce qui suit fonctionne pour moi:
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)
Vieille question, beaucoup de bonnes réponses, mais une autre alternative pourrait toujours intéresser ...
Le module numpngw
que j'ai récemment mis en place sur github ( https://github.com/WarrenWeckesser/numpngw ) peut écrire des fichiers PNG animés à partir de tableaux numpy. (Update: numpngw
est maintenant sur pypi: https://pypi.python.org/pypi/numpngw .)
Par exemple, ce script:
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)
crée:
Vous aurez besoin d'un navigateur prenant en charge le format PNG animé (directement ou avec un plugin) pour visualiser l'animation.
Je suis tombé sur ce post et aucune des solutions n’a fonctionné. Voici donc ma solution qui fonctionne
Problèmes avec d’autres solutions jusqu’à présent:
1) Pas de solution explicite quant à la façon dont la durée est modifiée
2) Pas de solution pour l'itération d'annuaire hors service, essentielle pour les GIF
3) Pas d'explication sur la façon d'installer imageio pour python 3
installe imageio comme ceci: python3 -m pip installe imageio
Remarque: vous devrez vous assurer que vos cadres ont une sorte d'index dans le nom du fichier afin qu'ils puissent être triés, sinon vous ne pourrez pas savoir où commence ou finit le 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
Comme Warren l'a dit l'année dernière, c'est une vieille question. Étant donné que les gens semblent toujours consulter la page, j'aimerais les rediriger vers une solution plus moderne. Comme dit blakev ici , il y a un exemple Pillow sur github .
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()
Remarque: Cet exemple est obsolète (gifmaker
n'est pas un module importable, seulement un script). Oreiller a GifImagePlugin (dont la source est sur GitHub ), mais le document sur ImageSequence semble indiquer un support limité (lecture seule)
Comme l’a mentionné un membre ci-dessus, imageio est un excellent moyen de le faire. imageio vous permet également de définir la fréquence d'images. En fait, j'ai écrit une fonction en Python qui vous permet de définir un blocage de la dernière image. J'utilise cette fonction pour les animations scientifiques où la boucle est utile mais pas le redémarrage immédiat. Voici le lien et la fonction:
Comment créer un GIF avec Python
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)
Avez-vous essayé PyMedia ? Je ne suis pas sûr à 100%, mais il ressemble à cet exemple de didacticiel cible votre problème.
Je poste une réponse de plus car c'est plus simple que tout ce qui a été posté jusqu'à présent:
from PIL import Image
width = 300
height = 300
im1 = Image.new("RGBA", (width, height), (255, 0, 0))
im2 = Image.new("RGBA", (width, height), (255, 255, 0))
im3 = Image.new("RGBA", (width, height), (255, 255, 255))
im1.save("out.gif", save_all=True, append_images=[im2, im3], duration=100, loop=0)
en utilisant des images existantes:
from PIL import Image
im1 = Image.open('a.png')
im2 = Image.open('b.png')
im3 = Image.open('c.png')
im1.save("out.gif", save_all=True, append_images=[im2, im3], duration=100, loop=0)
Et, comme les versions trop basses de pillow échouent silencieusement, voici une version bonus avec vérification de version de bibliothèque:
from packaging import version
from PIL import Image
im1 = Image.open('a.png')
im2 = Image.open('b.png')
im3 = Image.open('c.png')
if version.parse(Image.PILLOW_VERSION) < version.parse("3.4"):
print("Pillow in version not supporting making animated gifs")
print("you need to upgrade library version")
print("see release notes in")
print("https://pillow.readthedocs.io/en/latest/releasenotes/3.4.0.html#append-images-to-gif")
else:
im1.save("out.gif", save_all=True, append_images=[
im2, im3], duration=100, loop=0)
La solution la plus simple pour moi consiste à appeler une commande Shell en Python.
Si vos images sont stockées telles que dummy_image_1.png, dummy_image_2.png ... dummy_image_N.png, vous pouvez utiliser la fonction:
import subprocess
def grid2gif(image_str, output_gif):
str1 = 'convert -delay 100 -loop 1 ' + image_str + ' ' + output_gif
subprocess.call(str1, Shell=True)
Il suffit d'exécuter:
grid2gif("dummy_image*.png", "my_output.gif")
Cela construira votre fichier gif my_output.gif.
La tâche peut être complétée en exécutant le script python de deux lignes à partir du même dossier que la séquence de fichiers image. Pour les fichiers au format png, le script est -
from scitools.std import movie
movie('*.png',fps=1,output_file='thisismygif.gif')
Je recherchais un code à une seule ligne et trouvai ce qui suit pour mon application. Voici ce que j'ai fait:
Première étape:Installez ImageMagick à partir du lien ci-dessous
https://www.imagemagick.org/script/download.php
Deuxième étape:Pointez la ligne de commande sur le dossier où sont placées les images (au format .png dans mon cas)
Troisième étape:Tapez la commande suivante
magick -quality 100 *.png outvideo.mpeg
Merci FogleBird pour l'idée!
Je viens d'essayer ce qui suit et j'ai été très utile:
Commencez par télécharger les bibliothèques Figtodat
et images2gif
dans votre répertoire local.
Deuxièmement, rassemblez les figures dans un tableau et convertissez-les en gif animé:
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)
Je suis tombé sur le module ImageSequence de PIL, qui offre une meilleure (et plus standard) information GIF. J'utilise aussi la méthode after () de Tk cette fois, qui est meilleure que 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()
Une fonction simple permettant de créer des 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 __== "__main__":
main()