2

Hello I just finished to write a code that compute the orbitals of the hydrogen atom. I wrote a for loop to create 300 pictures using the command

plt.savefig("image{i}.png".format(i=i))

Now I wanted to ask what is the easiest way to create a high quality .mp4 or .gif file out of the pictures using python. I saw several tutorials that didn't helped me because the gif was messed up or the quality was too low.

Thank you for your support

Phicalc
  • 55
  • 5
  • bit broad - what did you try? I successfully did animations using GIMP 2 but to an animated gif. There are plenty of aproaches using ffmpeg: https://stackoverflow.com/questions/24961127/how-to-create-a-video-from-images-with-ffmpeg and threads for python like this: [python-make-a-video-using-several-png-images](https://stackoverflow.com/questions/13590976/python-make-a-video-using-several-png-images) – Patrick Artner May 10 '20 at 17:37

2 Answers2

2

The easiest I know is to use imageio's mimwrite.

import imageio
ims = [imageio.imread(f) for f in list_of_im_paths]
imageio.mimwrite(path_to_save_gif, ims)

There are obvious options such as duration, number of loops, etc.
And some other options you can read about in the documentation by using imageio.help('gif').

Hope that helps.

ShlomiF
  • 2,022
  • 1
  • 10
  • 16
  • 1
    I changed list_of_im_paths to "~/Plot" the directory where the .png are saved but I get a syntax error. – Phicalc May 10 '20 at 17:59
  • Um, that's because you need a list of paths, not just a path. How would the list comprehension know that you want to use a list of pngs in that directory?? Try using glob or os.listdir. – ShlomiF May 10 '20 at 18:29
  • @Phicalc, did this answer your question? If so it's customary to accept, so as to benefit the contributor as well as the community as a whole. – ShlomiF May 10 '20 at 20:40
  • @Phicalc , you just need to have a ``plt.savefig("image{i}.png".format(i=i))`` with a ``list_of_im_paths.append("/your_path_to_fig_folder/image{i}.png".format(i=i))`` inside your loop (that creates your figures). This way, you create a list with paths to each figure. (And also, I think you will need to define an empty list ``list_of_im_paths=[]`` just before your loop). – Diving May 21 '22 at 01:43
0

The faster way is to use imageio as in @ShlomiF's answer, but you can do the same thing with pure matplotlib if you so prefer:

import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation

nframes = 25
plt.subplots_adjust(top=1, bottom=0, left=0, right=1)

def animate(i):
    im = plt.imread('image'+str(i)+'.png')
    plt.imshow(im)

anim = FuncAnimation(plt.gcf(), animate, frames=nframes, interval=(2000.0/nframes))
anim.save('output.gif', writer='imagemagick')

But if your first priority is the quality of the output you may want to consider using ffmpeg and convert directly,

ffmpeg -f image2 -i image%d.png output.mp4
ffmpeg -i output.mp4 -vf "fps=10,scale=320:-1:flags=lanczos" -c:v pam -f image2pipe - | \
          convert -delay 10 - -loop 0 -layers optimize output.gif

Changing the scale argument as needed to control the size of the final output, scale=-1:-1 leaves the size unchanged.

William Miller
  • 8,894
  • 3
  • 17
  • 42