Programowo generować wideo lub animowany GIF w Pythonie?
Mam serię zdjęć, z których chcę stworzyć film. Idealnie mógłbym określić czas trwania klatki dla każdej klatki, ale stała liczba klatek też byłaby w porządku. Robię to w wxPython, więc mogę renderować do wxDC lub Mogę zapisać obrazy do plików, takich jak PNG. Czy istnieje Biblioteka Pythona, która pozwoli mi stworzyć albo film (AVI, MPG, itp.), albo animowany GIF z tych klatek?
Edit: próbowałem już PIL i chyba nie działa. Czy ktoś może mnie tym poprawić wniosek lub sugestia innego zestawu narzędzi? Ten link zdaje się potwierdzać moje wnioski dotyczące PIL: http://www.somethinkodd.com/oddthinking/2005/12/06/python-imaging-library-pil-and-animated-gifs/
18 answers
Polecam nie używać images2gif z visvis, ponieważ ma problemy z PIL/Pillow i nie jest aktywnie utrzymywany(powinienem wiedzieć, bo jestem autorem).
Zamiast tego użyj imageio , który został opracowany w celu rozwiązania tego problemu i nie tylko, i ma zostać.
Szybkie i brudne rozwiązanie:
import imageio
images = []
for filename in filenames:
images.append(imageio.imread(filename))
imageio.mimsave('/path/to/movie.gif', images)
W przypadku dłuższych filmów, użyj podejścia streamingowego:
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)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-21 04:03:10
Od czerwca 2009 r. pierwotnie cytowany post na blogu ma metodę tworzenia animowanych GIFów w komentarzach . Pobierz skrypt images2gif.py (dawniej images2gif.py , Aktualizacja Dzięki uprzejmości @ geographika).
Następnie, aby odwrócić klatki w gif, na przykład:
#!/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)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-21 04:55:19
Cóż, teraz używam ImageMagick. Zapisuję ramki jako pliki PNG, a następnie wywołuję konwersję ImageMagick.exe z Pythona do tworzenia animowanego GIFA. Fajną rzeczą w tym podejściu jest to, że mogę określić czas trwania klatki dla każdej klatki indywidualnie. Niestety zależy to od zainstalowania ImageMagick na maszynie. Mają wrapper Pythona, ale wygląda dość gównianie i nieobsługiwany. Wciąż otwarty na inne sugestie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-15 21:34:42
Użyłem images2gif.py który był łatwy w użyciu. Wydawało się, że podwojono Rozmiar pliku..
26 plików PNG 110KB, spodziewałem się 26 * 110kb = 2860kb, ale my_gif.GIF 5.7 mb
Również dlatego, że GIF był 8bit, ładne png stały się trochę rozmyte w GIF
Oto kod, którego użyłem:
__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
Oto 3 z 26 klatek:
Zmniejszanie obrazów zmniejszyło rozmiar:
size = (150,150)
for im in images:
im.thumbnail(size, Image.ANTIALIAS)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-29 23:05:34
Aby utworzyć film, możesz użyć 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])
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-30 04:29:45
Tak jak Warren powiedział w zeszłym roku, to stare pytanie. Ponieważ ludzie nadal wydają się oglądać stronę, chciałbym przekierować ich do bardziej nowoczesnego rozwiązania. Jak powiedział blakev tutaj , jest przykład poduszki nagithub .
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()
Uwaga: Ten przykład jest przestarzały (gifmaker
nie jest importowalnym modułem, tylko skryptem). Poduszka ma GifImagePlugin (którego źródło jest na Githubie), ale doc na ImageSequence wydaje się wskazywać ograniczone wsparcie (tylko odczyt)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-22 11:12:14
To nie jest biblioteka Pythona, ale mencoder może to zrobić: Kodowanie z wielu wejściowych plików graficznych . Możesz wykonać mencoder z Pythona w następujący sposób:
import os
os.system("mencoder ...")
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-15 22:24:43
Czy próbowałeś PyMedia ? Nie jestem w 100% pewien, ale wygląda na to, że Ten przykład samouczka dotyczy Twojego problemu.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-07 06:59:24
Z windows7, python2. 7, opencv 3.0, u mnie działa:
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)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-01 12:23:28
Stare pytanie, wiele dobrych odpowiedzi, ale nadal może być zainteresowanie inną alternatywą...
numpngw
moduł, który niedawno umieściłem na GitHubie ( https://github.com/WarrenWeckesser/numpngw ) potrafi zapisywać animowane pliki PNG z tablic numpy. (Update: numpngw
jest teraz na pypi: https://pypi.python.org/pypi/numpngw.)
Na przykład ten skrypt:
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)
Tworzy:
Będziesz potrzebował przeglądarki, która obsługuje animowane PNG (bezpośrednio lub za pomocą wtyczki), aby zobaczyć animację.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-11 18:22:54
Zadanie można wykonać uruchamiając dwuliniowy skrypt Pythona z tego samego folderu co Sekwencja plików graficznych. Dla plików sformatowanych w formacie png skrypt to -
from scitools.std import movie
movie('*.png',fps=1,output_file='thisismygif.gif')
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-02 10:07:11
Najprostszą rzeczą, która sprawia, że działa to dla mnie, jest wywołanie polecenia powłoki w Pythonie.
Jeśli są przechowywane obrazy takie jak dummy_image_1.png, dummy_image_2.png ... dummy_image_N. png, wtedy możesz użyć funkcji:
import subprocess
def grid2gif(image_str, output_gif):
str1 = 'convert -delay 100 -loop 1 ' + image_str + ' ' + output_gif
subprocess.call(str1, shell=True)
Po prostu wykonaj:
grid2gif("dummy_image*.png", "my_output.gif")
To stworzy plik gif my_output.gif.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-15 17:07:25
Szukałem kodu pojedynczej linii i znalazłem następujące działanie dla mojej aplikacji. Oto co zrobiłem:
Pierwszy Krok: zainstaluj ImageMagick z poniższego linku
Https://www.imagemagick.org/script/download.php
Drugi etap: wskaż linię cmd do folderu, w którym znajdują się obrazy (w moim przypadku .format png) są umieszczone
Trzeci Krok: wpisz następujące polecenie
magick -quality 100 *.png outvideo.mpeg
Dzięki FogleBird za pomysł!
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-07 09:40:05
Jak wspomniano powyżej, imageio jest świetnym sposobem na to. imageio pozwala również ustawić liczbę klatek na sekundę, a właściwie napisałem funkcję w Pythonie, która pozwala ustawić przytrzymanie ostatecznej klatki. Używam tej funkcji do animacji naukowych, gdzie pętla jest przydatna, ale natychmiastowy restart nie jest. oto link i Funkcja:
Jak zrobić GIF za pomocą Pythona
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)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-28 20:24:44
Po prostu próbowałem następujących I było bardzo przydatne:
Najpierw pobierz biblioteki Figtodat
i images2gif
do lokalnego katalogu.
Po Drugie Zbierz figury w tablicy i przekonwertuj je na animowany 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)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-24 03:27:03
Natknąłem się na moduł Pil ImageSequence , który oferuje lepszą (i bardziej standardową) aninmację GIF. Używam również metody TK after () Tym Razem, która jest lepsza niż czas .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()
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-27 07:57:20
Natknąłem się na ten post i Żadne z rozwiązań nie zadziałało, więc oto moje rozwiązanie, które działa
Problemy z dotychczasowymi rozwiązaniami:
1) Brak jednoznacznego rozwiązania co do sposobu modyfikacji czasu trwania
2) Brak rozwiązania dla iteracji katalogu out of order, która jest niezbędna dla GIFów
3) brak wyjaśnienia jak zainstalować imageio dla Pythona 3
Zainstaluj imageio TAK: python3-m pip install imageio
Uwaga: będziesz chciał się upewnić, że Twoje ramki mają jakiś indeks w nazwie pliku, aby mogły być sortowane, w przeciwnym razie nie będziesz miał możliwości poznania, gdzie GIF się zaczyna lub kończy
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(path, 'movie.gif'), images, duration = 0.04) # modify duration as needed
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-06 11:59:25
To naprawdę niesamowite ... Wszyscy proponują jakiś specjalny pakiet do odtwarzania animowanego GIFA, w tej chwili można to zrobić z Tkinter i klasycznym modułem PIL!
Oto moja własna metoda animacji GIF (stworzyłem jakiś czas temu). Bardzo proste:
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()
Możesz ustawić własne środki, aby zatrzymać animację. Daj mi znać, jeśli chcesz uzyskać pełną wersję z przyciskami play/pause / quit.
Uwaga: Nie jestem pewien czy kolejne klatki są odczytywane z pamięci czy z plik (dysk). W drugim przypadku byłoby bardziej wydajne, gdyby wszystkie odczytywały się jednocześnie i zapisywały do tablicy (listy). (Nie jestem tak zainteresowany, aby dowiedzieć się! :)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-16 15:18:28