Timelapse video from static images

Tags: timelapse python image processing

Getting things in order

For one of my nonprofit's projects, I used a DSLR camera on a tripod to capture the transformation of a common garden green bean seed from germination to small seedling. If it interests you, you can find the code on GitHub here.

Unfortunately, an earlier iteration of the code I wrote to control the camera did not account for the fact that the script may need to restart at one point or another during the ~3 week period I was recording the timelapse. This created some issues with filenames, specifically images being overwritten by newer photographs or given duplicate names.

This is problematic because the photos need to be sorted in order before they can stitched together into one cohesive video. I had hoped to use a file naming convention that would make this simple, but for the above reasons, I'll need to resort to parsing the EXIF data to determine the correct chronological order of the photographs.

Sorting files using EXIF metadata

Luckily writing a script to rename the files based on the original creation datetime of the image isn't too difficult. First we establish where the images are located and where we want them to be saved. For me it was:

# The directory where our images are located
PHOTO_DIRECTORY = '/home/ave/Documents/Work/CTS/timelapse/Images/'
# The directory we want to save our renamed images
PROCESSED_DIRECTORY = 'processed/'

We'll to import a few packages for the processing:

from datetime import datetime
import os
import PIL.Image
import PIL.ExifTags

Now we need to iterate through the images in specified in the directory we designated above. We'll also be sure to exclude any other directories that may be located there:

for file in os.listdir(PHOTO_DIRECTORY):
    # Make sure to skip directories-- we are only interested in image files
    path = os.path.join(PHOTO_DIRECTORY, file)
    if os.path.isdir(path):
        continue
    print('Processing ', file)

From here, it's just a matter of reading the 'DateTimeOriginal' key in the EXIF data and using it as the new filename:

img = PIL.Image.open(PHOTO_DIRECTORY + file)
    exif_date = {
        PIL.ExifTags.TAGS[k]: v for k, v in img._getexif().items() if k in PIL.ExifTags.TAGS
        and PIL.ExifTags.TAGS[k] == 'DateTimeOriginal'
    }
    image_time = datetime.strptime(exif_date['DateTimeOriginal'], '%Y:%m:%d %H:%M:%S')
    # Name the new file using the timestamp from the EXIF data
    new_filename = image_time.strftime('%m-%d-%Y_%H-%M') + '.jpeg'
    img.save(PHOTO_DIRECTORY + PROCESSED_DIRECTORY + new_filename, 'JPEG')
    print('Saveing as {} to {}.'.format(new_filename, PHOTO_DIRECTORY + PROCESSED_DIRECTORY))

And we now have a directory filled with our image files named by the time they were shot which makes them easy to sort in the correct order. This has the added benefit of eliminating any duplicate images that may have existed in the original directory.

Converting images to video

For the video conversion, I followed this handy guide from the Raspberry Pi Foundation. The default settings included in this guide work well for YouTube but if you'd like to tweak them for an alternative YouTube format, you may want to refer to their style guide.

From the directory with your processed images, making the video involves just two commands assuming you have the package mencoder already installed:

ls *.jpg > stills.txt

mencoder -nosound -ovc lavc -lavcopts vcodec=mpeg4:aspect=16/9:vbitrate=8000000 -vf scale=1920:1080 -o timelapse.avi -mf type=jpeg:fps=24 mf://@stills.txt

That's it! If you want to check out the code in it's entirety or propose any improvements of your own, you can check out the code on GitHub.