技術的なコードは時にGIF等で動きを付けて結果を出した方が理解が深まる場合があります。ここではPythonでGIFファイルを扱う時に便利な処理をまとめていきます。
こんにちは。wat(@watlablog)です。ここではPythonでGIFを扱う時の備忘録をとっていきます!
GIF動画を作る時に便利な処理
複数画像からGIFを作るコード
matplotlibでは「Pythonのmatplotlibアニメーションで楕円の軌跡!」で紹介したように、直接GIF動画作成ができますが、個人的には画像の生成とGIF動画の作成は別々で覚えておいた方が便利だと思うので、個別に紹介します。
まずは以下のコードが基本のGIF作成関数です。
in_dirに置いた複数画像(連番にしておく必要あり)からGIFを作ります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
from PIL import Image import os import glob # GIFアニメーションを作成 def create_gif(in_dir, out_filename): path_list = sorted(glob.glob(os.path.join(*[in_dir, '*']))) # ファイルパスをソートしてリストする imgs = [] # 画像をappendするための空配列を定義 # ファイルのフルパスからファイル名と拡張子を抽出 for i in range(len(path_list)): img = Image.open(path_list[i]) # 画像ファイルを1つずつ開く imgs.append(img) # 画像をappendで配列に格納していく # appendした画像配列をGIFにする。durationで持続時間、loopでループ数を指定可能。 imgs[0].save(out_filename, save_all=True, append_images=imgs[1:], optimize=False, duration=100, loop=0) # GIFアニメーションを作成する関数を実行する create_gif(in_dir='input', out_filename='animation.gif') |
matplotlibでプロットを複数画像保存する
以下のコードはmatplotlibの.savefigでプロットを保存する部分を関数にした物です。ファイル名の決め方等、この方法が好きなのでここにメモします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
import numpy as np import os from matplotlib import pyplot as plt # matplotlibで画像を複数保存する関数 def plot_img_generator(dir, frame): # 各フレームで速度を足しながら画像を作っていくループ for i in range(frame): print(i) # 現在のフレーム数をコンソールに表示 # サンプル波形を生成(ここに本来やりたい処理を書く) x = np.arange(0, 10, 0.01) y = np.sin(2 * np.pi * 1 * x - i) # ここからグラフ描画------------------------------------- # フォントの種類とサイズを設定する。 plt.rcParams['font.size'] = 14 plt.rcParams['font.family'] = 'Times New Roman' # 目盛を内側にする。 plt.rcParams['xtick.direction'] = 'in' plt.rcParams['ytick.direction'] = 'in' # グラフの上下左右に目盛線を付ける。 fig = plt.figure() ax1 = fig.add_subplot(111) ax1.yaxis.set_ticks_position('both') ax1.xaxis.set_ticks_position('both') # 軸のラベルを設定する。 ax1.set_xlabel('x') ax1.set_ylabel('y') # スケールの設定をする。 ax1.set_xticks(np.arange(0, 10, 1)) ax1.set_xlim(0, 5) ax1.set_ylim(-1, 1) # データプロット ax1.plot(x, y, label='signal', color='red') # レイアウト設定 fig.tight_layout() # グラフを表示する。 #plt.show() # dirフォルダが無い時に新規作成 if os.path.exists(dir): pass else: os.mkdir(dir) # 画像保存パスを準備 path = os.path.join(*[dir, str("{:05}".format(i)) + '.png']) # 画像を保存する plt.savefig(path) plt.close() # --------------------------------------------------- plot_img_generator(dir='input', frame=10) |
GIFにすると以下のような物が出来ます。
動画から静止画を抽出する
再生ボタンを押さないと動かない動画形式のファイルよりも、パワポとかに貼ると自動で動くGIFの方が欲しい時があります。
そんな時は以下のPythonコードで動画を静止画にしましょう。関数に入力動画のファイルパス、静止画を保存するフォルダパス、間引き数(何個飛ばしか)、静止画の拡張子をとる事が可能です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
import cv2 import numpy as np import os def m_slice(mov_path, dir, step, extension): movie = cv2.VideoCapture(mov_path) # 動画の読み込み Fs = int(movie.get(cv2.CAP_PROP_FRAME_COUNT)) # 動画の全フレーム数を計算 path_head = 'out_' # 静止画のファイル名のヘッダー ext_index = np.arange(0, Fs, step) # 静止画を抽出する間隔 for i in range(Fs - 1): # フレームサイズ分のループを回す flag, frame = movie.read() # 動画から1フレーム読み込む check = i == ext_index # 現在のフレーム番号iが、抽出する指標番号と一致するかチェックする # frameを取得できた(flag=True)時だけ処理を行う if flag == True: # もしi番目のフレームが静止画を抽出するものであれば、連番ファイル名を付けて保存する if True in check: path_out = os.path.join(*[dir, path_head + str("{:05}".format(i)) + extension]) cv2.imwrite(path_out, frame) return # 関数実行:引数=(ファイル名のパス、保存先のフォルダパス、ステップ数、静止画拡張子) m_slice(mov_path='movie.mp4', dir='movie', step=10, extension='.png') |
このコードを実行すると、例えば以下のmp4動画が、
複数の画像になるので、上記GIF化コードでGIFファイル化する事が出来ます。
ちなみに、このコードはGIF画像を再び複数画像にする事も可能です。その場合は動画ファイルmov_pathにGIFファイルを指定して下さい。
まとめ
今回はコンパクトな内容ですが、以外と久々に使うと連番ファイル処理の部分とか、動画処理部分とかを忘れてしまう事があるため記事にしました。
GIF関連で新しい処理を覚えたらここにメモっていこうと思います。
これで動きのあるGIFファイルを自由に扱えそうです!
Twitterでも関連情報をつぶやいているので、wat(@watlablog)のフォローお待ちしています!
コメント