tommy.carstensen
tommy.carstensen

Reputation: 9622

python imageio mp4 video from a set of png images

How do I make an mp4 video from a set of png images with the module imageio? I've tried this:

import imageio
import glob
writer = imageio.get_writer('test.mp4', fps=20)
for png_path in glob.glob('*.png'):
    im = imageio.imread(png_path),
    writer.append_data(im[:, :, 1])
writer.close()

I've also tried replacing im[:, :, 1] with im. What am I doing wrong? I'm happy to use another module.

Upvotes: 9

Views: 29176

Answers (4)

Alex Li
Alex Li

Reputation: 274

Not sure why, but for me, mimsave worked while the get_writer method kept giving a corrupted file. If you have a list of image data (e.g. np.ndarray of shape HxWx3), it looks like this:

imageio.mimsave(mov_path, [image1, image2, image3])

Upvotes: 0

meduz
meduz

Reputation: 4241

Wrapping up answers, a short and simple "pythonesque" solution is to use that function:

import imageio
def make_mp4(moviename, fnames, fps):
    with imageio.get_writer(moviename, mode='I', fps=fps) as writer:
        for fname in fnames:
            writer.append_data(imageio.imread(fname))
return 'done'

in conjunction with a loop my_loop creating the images with a function create_image_as_numpy such as:

fnames = []
np_dtype = np.uint8
for i_loop, _ in enumerate(my_loop):
    imgnp = create_image_as_numpy(...)
    fname = f'/tmp/frame_{i_loop}.png'
    imageio.imwrite(fname, imgnp.astype(np_dtype))

    fnames.append(fname)

make_mp4(video_name, fnames, fps=24)

I like to use the /tmp folder (on Linux and MacOs) as it gets flushed at every reboot. Do do that flushing explictly, one can do:

import os
import imageio
def make_mp4(moviename, fnames, fps):
    with imageio.get_writer(moviename, mode='I', fps=fps) as writer:
        for fname in fnames:
            writer.append_data(imageio.imread(fname))
    for fname in fnames: os.remove(fname)
    return 'done'

Upvotes: 1

HKay
HKay

Reputation: 400

A better version of your code combined with Mr K. would be:

import imageio
import glob
import os
writer = imageio.get_writer('test.mp4', fps=20)
for file in glob.glob(os.path.join(path,f'{name}*.png')):
    im = imageio.imread(file)
    writer.append_data(im)
writer.close()

P.S. Don't forget to add image resizing code before appending them to the video file.

Upvotes: 7

Mr K.
Mr K.

Reputation: 1201

You don't need to modify the image through im[:, :, 1]. For example, the code below takes all images starting with name in a folder specified by path and creates a videofile called "test.mp4"

fileList = []
for file in os.listdir(path):
    if file.startswith(name):
        complete_path = path + file
        fileList.append(complete_path)

writer = imageio.get_writer('test.mp4', fps=20)

for im in fileList:
    writer.append_data(imageio.imread(im))
writer.close()

All images have to be the same size so you should resize them before appending them to the video file. You can modify the fps through fps, I just set it at 20 because I was following your code.

Upvotes: 18

Related Questions