LoginSignup
2
2

More than 3 years have passed since last update.

PythonでPillowを使ってGIFファイルを作る

Last updated at Posted at 2019-11-24

コンター図をパラパラ漫画みたいにしたGIF動画を作ったので備忘録。
環境はPython 3.6.8

matplotlib.animation

matplotlib.animationで動くグラフは作れるみたい。

GIFファイルとして保存するにはwriterにimagemagickを使うのが普通の様子。

imagemagick

windowsにインストールする場合、ちょっと面倒な様子。

インストールしようとして参考にさせていただいたページ。
https://higuma.github.io/2016/08/31/imagemagick-1/

PythonのライブラリPillow

Pillowについて参考にさせていただいたサイト。

インストールとか
https://note.nkmk.me/python-pillow-basic/

GIFの作り方
https://note.nkmk.me/python-pillow-gif/

作ってみる

import_lib.py

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import os
from PIL import Image, ImageDraw  

こんな感じのデータを用意する。

スクリーンショット 2019-11-24 21.48.30.png

座標はこんな感じを想定
image.png

test_data.py

test_data = pd.DataFrame({'key':range(10),
                          't1': [10] * 10,
                          't2': [i * 10 + 10 for i in range(10)],
                          't3': [i * 10 + 20 for i in range(10)],
                          't4': [5] * 10,
                          't5': [i * 10 + 5 for i in range(10)],
                          't6': [i * 10 + 15 for i in range(10)],
                          't7': [3] * 10,
                          't8': [i * 10 + 2 for i in range(10)],
                          't9': [i * 10 + 10 for i in range(10)]})

t = ['t' + str(int(i)) for i in range(1, 10)]
x = [i * 10 for i in range(1, 4)] * 3
y = [10] * 3 + [20] * 3 + [30] * 3

コンター図を作る用のデータ抽出関数を作っておく

create_function.py

def f_contour_data(df, timing):
    # コンター図を描きたいタイミングの行のデータを抽出
    df0 = df[df['key'] == timing].copy()  
    # 抽出したデータを使いやすいようにindexを0にしておく
    df0.reset_index(drop = True, inplace = True)

    x = [10, 20, 30] # コンター図のx軸
    y = [10, 20, 30] # コンター図のy軸

    # 番号のリストを作る
    # [[t1, t2, t3], [t4, t5, t6], [t7, t8, t9]]
    # これをつくる
    l_T = []
    for i in range(len(y)):
        T = ['t' + str(int(j + i * 3)) for j in range(1, 4)]
        l_T.append(T)

    # x軸の2darrayをつくる
    x0 = np.empty((0, len(y))) # 空のndarrayをつくる
    for i in range(len(y)):
        x0 = np.append(x0, np.array([x]), axis = 0) # xをndarrayに換えてx0に追加
    # y軸の2darrayをつくる
    y0 = np.empty((0, len(y)))
    for i in range(len(y)):
        y0 = np.append(y0, np.array([[y[i]] * 3]), axis = 0)

    # z軸の2darrayをつくる    
    z0 = np.empty((0, len(y)))
    for i in range(len(y)):
        temp = []
        T = l_T[i]
        for s in T:
            temp.append(df0[s][0])
        z0 = np.append(z0, np.array([temp]), axis = 0)                           
    return x0, y0, z0, l_T # l_Tは確認用 削除してもOK

これを使ってコンター図をテキトーに描くとこんな感じになる。

create_contour.py
x0, y0, z0, l_t = f_contour_data(df = test_data, timing = 0)

plt.figure()
p = plt.contourf(x0, y0, z0, cmap = 'jet')
cbar = plt.colorbar(p)

image.png

あとはこれをループでどんどん作って保存していく。

loop.py

l_img = [] # コンター図の.pngのpathをいれるようのリスト
os.makedirs('Contour_gif/', exist_ok = True) # グラフ保存用のフォルダ―を作る
lv = [i * 10 for i in range(14)]
for i in range(10):
    x0, y0, z0, l_tc = f_contour_data(df = test_data, timing = i)
    plt.figure()
    p = plt.contourf(x0, y0, z0, lv, ![test.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84834/dd6833da-c69d-95de-f016-f0a7e6082a08.gif)
cmap = 'jet')
    cbar = plt.colorbar(p)
    plt.title('key = ' + str(int(i)))
    save_path = 'Contour_gif/key_' + str(int(i)) + '.png'
    plt.savefig(save_path, bbox_inches="tight") # 作ったグラフを保存
    l_img.append(save_path) # コンター図の順番を確実に維持したいのでココでリストに追加しておく

images = [] # 開いたpngを入れておくよう。
# 別にl_imgの範囲は指定しなくてもOK 画像の容量によっては怒られるけど。。。
for s in l_img[0:151]:
        im = Image.open(s)
        images.append(im)
        # images[0]を起点に残りをつなげる durationで切り替わりの時間(msec) loop = 0 で無限ループ
        images[0].save('test.gif',
                       save_all = True, append_images = images[1: len(images)],
                       duration = 500, loop = 0, optimaize = False)

こんな感じのGIFファイルができる。

test.gif

2
2
0

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
2
2