とある科学の備忘録

とある科学の備忘録

CやPythonのプログラミング、Arduino等を使った電子工作をメインに書いています。また、木製CNCやドローンの自作製作記も更新中です。たまに機械学習とかもやってます。

【Python】グラフをGIFアニメで保存(PIL&Matplotlib)(imagemagick未使用!)

内容

前回、imagemagickというwriterを使って、GIFアニメーションを作成する方法を紹介しました。
shizenkarasuzon.hatenablog.com


ですが、通常のPCにはimagemagickは入っていないため、わざわざインストールしなければなりません。

ですが、imagemagickを使わずにGIFアニメーションを作成する方法があります。


その時に必要になるのが「PIL (Pillow)」というPythonライブラリです。
PILはimagemagickと違ってpipやcondaで簡単にインストールすることができます。

前回の記事ではimagemagickに頼っていたGIFアニメーションの作成を、PILを駆使して行おうというものです。

PILのインストール

まだPILが入っていない場合、コマンドプロンプトで以下のコマンドを実行してください。

pip install pillow

これで、PILがインストールされます。


プログラム

以下のプログラムを実行してください。

import numpy as np
import matplotlib.pyplot as plt
from PIL import Image

class Rendering:
    def __init__(self):
        self.pil_images = []
        self.duration = 100 #1フレームの表示時間(ms)
        self.film_num = 0
        
    def setFig(self):
        canvas = plt.get_current_fig_manager().canvas
        canvas.draw()
        pil_image = Image.frombytes('RGB', canvas.get_width_height(), canvas.tostring_rgb())
        self.pil_images.append(pil_image)
        self.film_num += 1
        
        
    def RenderGIF2(self, fileName = "sample.gif"):
        self.pil_images[0].save(fileName, save_all=True, append_images= self.pil_images[1:], 
                                optimize=False, duration=self.duration, loop=0)
        
        print("-------------- Finished Rendering -----------------")
        print("1フレームあたりの表示時間   = " + str(self.duration / 1000.) + "s")
        print("1秒間で表示するフレーム数  = " + str(1. / self.duration * 1000.)  + "fps")
        print("GIFビデオの長さ           = " + str(self.film_num * self.duration / 1000.) + "s")
        print("---------------------------------------------------")

        
if __name__ is "__main__":
    data_Xaxis = np.array(range(60))
    render = Rendering()
    
    for i in range(10):
        data_Yaxis = np.sin(data_Xaxis / 5 + i * 0.3)
        
        fig = plt.figure(figsize=(5, 5)) #10*10(インチ)に設定
        ax1 = fig.add_subplot(1, 1, 1) #(2行 * 3列)に分割し、1番目の位置
        ax1.plot(data_Yaxis, color = 'blue')
        render.setFig()
        
    render.RenderGIF2("sample.gif") 

実行結果:

f:id:pythonjacascript:20190127161855g:plain

上のような動画が「sample.gif」という名前で保存されればOKです。

一応、作成したGIFアニメーションの詳細を表示するようにしています:

-------------- Rendering Finished -----------------
1フレームあたりの表示時間   = 0.1s
1秒間で表示するフレーム数  = 10.0fps
GIFビデオの長さ           = 1.0s
---------------------------------------------------