14. PNGアニメーション¶
いよいよ前期の授業は最終回になります。 後期の授業の予習としてアニメーション作成を紹介します。
後期の授業
Pythonを用いて、オブジェクト指向プログラミングを学びながら、 アルゴリズムとデータ構造の理解を深めて予定です。 楽しく学習ができるようにアニメーションを作りながら学びます。
14.1. モジュールの準備¶
Python で画像やアニメーションを扱うためには、ライブラリ(Python ではモジュールと呼ぶ)を使います。
Pillow(PIL) モジュール: Python で画像を簡単に扱うため
APNG モジュール: アニメーション PNG を作成するため
IPython モジュール: 画像/動画を Google Colaboratory 上に表示するため
Google Colaboratory は、あらかじめよく使うモジュールがインストールされています。これらは、何も設定しなくても、import
して使うことができます。
[1]:
from PIL import Image , ImageDraw
import IPython
ただし、APNGモジュールは、インストールされていません。 このような場合は、pip
を使って、インストールしてから、import
します。
[2]:
!pip install APNG
from apng import APNG
Requirement already satisfied: APNG in /usr/local/lib/python3.9/site-packages (0.3.4)
pip/pip3
コンピュータ環境にPython モジュールをインストールするためのUNIXコマンドです。
14.2. PNG 画像¶
まず、PNG画像を作ってみます。
14.2.1. キャンバス¶
画像を描画するキャンバス (canvas) を作ってお絵かきを始めます。
大きさを指定して、キャンバスを作成する
[3]:
canvas = Image.new("RGB", (400,300))
キャンバスの大きさは、動画にすることを考えて、あまり大きくせず、400 x 300 くらいにしておきます。
14.2.2. 図形を描画する¶
実際の描画操作は、描画コンテキスト (draw) を作って行います。(この辺りの仕組みは、Python以外のプログラミング言語でもほぼ同じです。)
キャンバスの描画コンテキストを作る
[4]:
draw = ImageDraw.Draw(canvas)
まずは、長方形 (rectangle) をキャンバス上に描画してみましょう。 fill は、塗りつぶす色を指定してます。
[5]:
draw.rectangle((100,100,200,200), fill='green')
14.2.3. 描画した図形を保存する¶
キャンバスに描画した図形をPNGファイルに保存します。ファイル名は、なんでも構いませんが、拡張子は、.png
にします。
[6]:
canvas.save("rect.png")
(Colab 上に)保存されたPNGファイルは、IPython.display
で表示してみることができます。
[7]:
IPython.display.Image("rect.png")
[7]:
Let’s try
長方形の色や位置、大きさを変えて表示してみよう
14.2.4. 円¶
円も描画する ecllipse は、指定した短形におさまる楕円(円)を描画します。
[8]:
draw.ellipse((250,200, 300, 250),fill=(192, 64, 64))
今回は、色を RGB で指定しています。
14.3. アニメーションを作る¶
アニメーション(動画)は、複数の画像を作成し、パラパラ漫画と同じ原理で作ります。
まず、ボールが転がるアニメーションを作ってみましょう。 x 軸方向に +20 ずつ移動させながら、3枚ほど画像を作ります。
ball0.png を作る
[9]:
canvas = Image.new("RGB", (400,300), color='black')
draw = ImageDraw.Draw(canvas)
draw.ellipse((100, 200, 150, 250),fill=(192, 64, 64))
canvas.save('ball0.png')
IPython.display.Image("ball0.png")
[9]:
ball1.png を作る
[10]:
canvas = Image.new("RGB", (400,300), color='black')
draw = ImageDraw.Draw(canvas)
draw.ellipse((100+20, 200, 150+20, 250),fill=(192, 64, 64))
canvas.save('ball1.png')
IPython.display.Image("ball1.png")
[10]:
ball2.png を作る
[11]:
canvas = Image.new("RGB", (400,300), color='black')
draw = ImageDraw.Draw(canvas)
draw.ellipse((100+40, 200, 150+40, 250),fill=(192, 64, 64))
canvas.save('ball2.png')
IPython.display.Image("ball2.png")
[11]:
Let’s try: 本来、1枚1枚作成してはいけません。
for文を使って、まとめて生成しましょう。
14.4. APNG に変換する¶
Pillow/PILで保存したファイル名からファイルリストを作ります。
[12]:
filelist = ['ball0.png', 'ball1.png', 'ball2.png']
APNG モジュールは、画像ファイルのリストからアニメーション PNG を作成します。delay は、画像 1 枚辺りの速度 (ミリ秒) です。
[13]:
APNG.from_files(filelist, delay=100).save("ball-anime.png")
注意: PNGアニメーションのファイル拡張子は、画像と同じ
.png
です。
Let’s try
実際にアニメーション (APNG) を作成して表示してみよう。 (大したアニメーションでないのでここは期待しないでください。)
IPython.display.Image("ball-anime.png")
14.4.1. ボールを投げるアニメ¶
(例題) ボールがいい感じで放物運動するアニメーションを作ってみましょう。 時刻 t のときの (x,y) を次のようにします。(ここのパラメータは自由に調整して構いません。)
\(x = 10t + 100\) \(y = 2(t−10) +100\)
あとは、時刻を for t in range(20)
: のようにループでまわして、画像を作ります。画像名は、 filelist に追加しておきます。
[14]:
# 放物線を関数で定義しておく
def fy(t):
return (t - 10)**2 + 100
filelist = []
for t in range (20):
canvas = Image.new("RGB", (400,300), color="black")
draw = ImageDraw.Draw(canvas)
x = 100 + 10 * t
y = fy(t)
draw.ellipse((x, y, x+50, y+50),fill=(192, 64, 64))
canvas.save(f"ball{t}.png")
filelist.append(f"ball{t}.png")
APNG.from_files(filelist, delay=100).save("ball-anime.png")
IPython.display.Image("ball-anime.png")
[14]: