LoginSignup
1
1

More than 5 years have passed since last update.

アニメーションGIFから連続したコマの静止画を作りたい

Last updated at Posted at 2018-12-18

アニメーションGIFから連続したコマの静止画(↓こういうやつ)を生成したかったので方法を調べました。
output_2.png

実現方法

ご指摘いただきましたが、ffmpegのコマンドで出来るそうです。
コメント欄参照。

OpenCVを使えばgifのフレー ム単位読み出しとかができるとのことなのでこれを使います。

def read_gif(filename):
    gif = cv2.VideoCapture('sample.gif')
    _, img = gif.read()
    return img  

準備

とりあえず今回は、Python3とOpenCVで実装します。
必要なライブラリをインストールしておきます。

pip3 install opencv-python
pip3 install numpy

一枚の画像作成

あまりスマートじゃないですが、コードは以下のようになりました。
単純にgifのフレームを読み出していって、右の折り返し列が来たら次の行に進めて画像を出力していく感じです。
最終的にマトリクス状の一枚の静止画になります。フレームが足りない部分は黒塗りの画像で埋めます。

combine.py
import cv2
import os
import numpy as np

def make_blank(h, w):
    return np.tile(np.uint8([0,0,0]), (h,w,1))

def combine_gif(filename):
    # gif読み込み
    gif_stream = cv2.VideoCapture(filename)

    # 折り返し列
    split = 10

    # フレーム読み込み処理
    vlist, hlist = [], []
    pre_w, i = 0, 1
    success = True
    while success:
        success, frame = gif_stream.read()

        # n行目を作成するリストに追加
        if frame is not None:
            hlist.append(frame)

        # 折り返し地点(or 読み込みがない)場合、
        if (i % split == 0 or not success) and len(hlist) > 0:

            # widthの差分を計算して黒埋め画像作成
            h, w = cv2.hconcat(hlist).shape[:2]
            diff = pre_w - w
            if diff > 0:
                hlist.append(make_blank(h, diff))

            # 横一列を結合して、行リストに追加
            vlist.append(cv2.hconcat(hlist))
            hlist = []
            pre_w = w

        i += 1

    # 行リストを結合して、画像出力
    vimg =  cv2.vconcat(vlist)
    cv2.imwrite('output.png', vimg)


if __name__ == '__main__':
    combine_gif("sample.gif")

連番画像作成

一枚の画像じゃなくて複数の連番画像を作成する場合は以下のような感じです。

split.py
import cv2
import os

def split_gif(filename):
    # 保存先ディレクトリ作成
    output_dir = "output"
    if not os.path.exists(output_dir):
        os.mkdir(output_dir)

    # GIF読み込み
    gif_stream = cv2.VideoCapture(filename)

    # 連番画像出力
    i = 0
    while True:
        success, frame = gif_stream.read()

        if not success:
            break

        path = os.path.join(output_dir, str(i) + ".png")
        cv2.imwrite(path, frame)
        i += 1

if __name__ == '__main__':
    split_gif("sample.gif")

参考

1
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1