2017/10/17

Python Tips:アニメーション GIF から静止画をまとめて抽出したい

Python でアニメーション GIF ( animated GIF )からフレーム画像を抽出する方法をご紹介します。

早速結論ですが、 Python の画像処理用ライブラリ Pillow を使うのが比較的かんたんです。他にも方法は無数にあるかと思いますが、私は Pillow でやるのがスムーズでした。

Pillow は画像処理ライブラリ PIL のフォークで、 PIL が対応していない Python 3.x に対応しているのがポイントです。 Pillow は pip でインストールするときには名称 Pillow でインストールしますが、スクリプトの中で import するときは PIL と同じ PIL という名前を使用します。

$ pip install Pillow

from PIL import Image

Pillow のドキュメントサイトはこちらです。

Pillow — Pillow (PIL Fork) documentation

実際に、 Pillow を使ってアニメーション GIF を分解する方法を見てみましょう。

# coding: utf-8

'''アニメーション GIF のフレーム画像(静止画)を抽出する
'''

from pathlib import Path
from PIL import Image, ImageSequence

# 分割したいアニメーション GIF 画像
IMAGE_PATH = 'target.gif'
# 分割した画像の出力先ディレクトリ
DESTINATION = 'splitted'
# 現在の状況を標準出力に表示するかどうか
DEBUG_MODE = True


def main():
    frames = get_frames(IMAGE_PATH)
    write_frames(frames, IMAGE_PATH, DESTINATION)


def get_frames(path):
    '''パスで指定されたファイルのフレーム一覧を取得する
    '''
    im = Image.open(path)
    return (frame.copy() for frame in ImageSequence.Iterator(im))


def write_frames(frames, name_original, destination):
    '''フレームを別個の画像ファイルとして保存する
    '''
    path = Path(name_original)

    stem = path.stem
    extension = path.suffix

    # 出力先のディレクトリが存在しなければ作成しておく
    dir_dest = Path(destination)
    if not dir_dest.is_dir():
        dir_dest.mkdir(0o700)
        if DEBUG_MODE:
            print('Destionation directory is created: "{}".'.format(destination))

    for i, f in enumerate(frames):
        name = '{}/{}-{}{}'.format(destination, stem, i + 1, extension)
        f.save(name)
        if DEBUG_MODE:
            print('A frame is saved as "{}".'.format(name))


if __name__ == '__main__':
    main()

このスクリプトを実行すると、アニメーション GIF ファイル target.gif の静止画をすべて抽出して splitted というフォルダに書き出してくれます。元の GIF 画像には変更を加えることなく、抽出した画像を、末尾に連番をつけた形でファイルとして切り出します。

ポイントは PIL.ImageSequence.Iterator クラスです。 PIL.Image で開いた画像をこのコンストラクタに渡すと、アニメーション GIF 内の各フレーム(静止画)を返すイテレータオブジェクトを生成してくれます。

便利ですねー。


参考


逆に、静止画を組み合わせてアニメーション GIF を作る方法については、次の Stack Overflow ページでやりとりされています。興味のある方はこちらもよろしければ。

Programmatically generate video or animated GIF in Python? - Stack Overflow

ライブラリ Pillow の使い方についての日本語の解説はこちらのページが丁寧でわかりやすいです。

Python 3.5 対応画像処理ライブラリ Pillow (PIL) の使い方 - Librabuch

0 件のコメント: