LGTM --Compose LGTM images with videos and photos and output GIF animation

I tried to output a GIF animation for LGTM with a script from videos and photos taken while traveling. Reduce photos beautifully with antialiasing This is a continuation of the article. The image stabilization is more severe than I expected, so I would like to add image stabilization logic as a future goal. You should be able to do it by extracting the feature points of the image and pattern matching ...

Finished product

b_lgtm.gif

lgtm.gif

Processing flow

  1. Convert video to image with ffmpeg
  2. Reduce the image with PIL
  3. Combine LGTM images with PIL
  4. Convert images to GIF videos with imagemagick

Installation

Confirmed to work only in python2.7 environment of mac

#Install PIL
pip install PIL --allow-external PIL --allow-unverified PIL

#imagemagick install
brew install imagemagick

#install confirmation
convert --version
>>> Version: ImageMagick 6.9.2-5 Q16 x86_64 2015-11-01 http://www.imagemagick.org
>>> Copyright: Copyright (C) 1999-2015 ImageMagick Studio LLC
>>> License: http://www.imagemagick.org/script/license.php
>>> Features: Cipher DPC Modules 
>>> Delegates (built-in): bzlib freetype jng jpeg ltdl lzma png tiff xml zlib

#Install ffmpeg
brew install ffmpeg

Combine LGTM image with image and convert to GIF video

lgtm.py


# -*- coding: utf-8 -*-
import commands
import Image
import re

#Image height pixels when shrinking
PHOTO_HEIGHT = 300

#Folder with images
BASE_DIR = "/Users/XXXX/Desktop/Photos"

#Image regular expression name
PHOTO_REGEX = r"P.*.[jpg|JPG]"

#Image prefix after resizing
PHOTO_RESIZE_PREFIX = "r_"

#LGTM image
LGTM_PATH = "/tmp/lgtm.png "

#Coordinates for compositing LGTM images
LGTM_PASTE_X_Y = (120, 0)


def main():
    #Get full image path
    _cmd = "cd {} && ls".format(BASE_DIR)
    l = commands.getoutput(_cmd)
    l = l.split("\n")
    l = [_l for _l in l if re.match(PHOTO_REGEX, _l)]

    #Generate a folder for output
    assert len(BASE_DIR) > 5, "BASE_DIR is too short"
    commands.getoutput("rm -rf {}/output".format(BASE_DIR))
    commands.getoutput("mkdir {}/output".format(BASE_DIR))

    for _l in l:
        before_path = '{}/{}'.format(BASE_DIR, _l)
        filename = '{}{}'.format(PHOTO_RESIZE_PREFIX, _l)
        after_path = '{}/output/{}'.format(BASE_DIR, filename)
        resize(before_path, after_path, filename=_l)  #Shrink


def resize(before, after, height=PHOTO_HEIGHT, filename="", aa_enable=True, lgtm_enable=True):
    """
Resize the image
    :param str before:Original image file path
    :param str after:Image file path after resizing
    :param int height:Image height after resizing
    :param bool aa_enable:Whether to enable antialiasing
    :param bool lgtm_enable:Whether to enable lgtm image compositing
    :return:
    """
    #Open image readonly
    img = Image.open(before, 'r')
    #Calculate image pixels after resizing
    before_x, before_y = img.size[0], img.size[1]
    x = int(round(float(height / float(before_y) * float(before_x))))
    y = height
    resize_img = img
    if aa_enable:
        #Shrink with antialiasing
        resize_img.thumbnail((x, y), Image.ANTIALIAS)
    else:
        #Shrink without antialiasing
        resize_img = resize_img.resize((x, y))

    #lgtm image composition
    if lgtm_enable:
        lgtm = Image.open(LGTM_PATH)
        resize_img.paste(lgtm, LGTM_PASTE_X_Y, lgtm)  #I'm synthesizing by matching the coordinates

    #Save the resized image
    resize_img.save(after, 'jpeg', quality=100)
    print "RESIZED!:{}[{}x{}] --> {}x{}".format(filename, before_x, before_y, x, y)

#Run
main()

#gif animation generation
cmd = "convert -layers optimize -loop 0 -delay 60 {}/output/*.* {}/lgtm.gif".format(BASE_DIR, BASE_DIR)
output = commands.getoutput(cmd)
print output

Execution result


>>>python ./lgtm.py 
RESIZED!:P1050400.JPG[4592x3448] --> 400x300
RESIZED!:P1050401.JPG[4592x3448] --> 400x300
RESIZED!:P1050402.JPG[4592x3448] --> 400x300
RESIZED!:P1050403.JPG[4592x3448] --> 400x300
RESIZED!:P1050404.JPG[4592x3448] --> 400x300
RESIZED!:P1050405.JPG[4592x3448] --> 400x300
RESIZED!:P1050406.JPG[4592x3448] --> 400x300

Image output of video frame by frame with ffmpeg

sample


$ ffmpeg -i [INPUT_FILE] -f image2 -vcodec png -r 4 "./%03d.png "
-i input file
-f format
-vcodec codec
-r Number of frames per second
%03d 3-digit number

reference

The one I often use with ffmpeg

Recommended Posts

LGTM --Compose LGTM images with videos and photos and output GIF animation
Get media timeline images and videos with Python + Tweepy
Visualize cavity flow with matplotlib and save as gif animation
Extract videos from YouTube and make GIF animations for LGTM from them
[IOS] Disassemble GIF animation with Pythonista3.
Create LGTM images with GIMP! (Python-fu)
Load gif images with Python + OpenCV
Easy animation with matplotlib (mp4, gif)
Upload and download images with falcon
Get tweets with Google Cloud Function and automatically save images to Google Photos
Capturing images with Pupil, python and OpenCV
taichi's Torisetsu ① ~ Output as mp4 and gif ~
Add images to iOS photos with Pythonista
Make a GIF animation with folder monitoring
Importing and exporting GeoTiff images with Python
Cut out and connect images with ImageMagick