MatplotlibとNumpyを使って、3次元データを可視化し、それをアニメーション(GIF画像)として保存する方法を紹介します。時系列で変化する3Dデータを表現する際に非常に有効です。
作成されるGIF画像
コード
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from mpl_toolkits.mplot3d import Axes3D # 3Dプロットのために必要
def make_animation(data_frames, filename="animation.gif"):
"""
3Dデータをアニメーション(GIF)として作成し保存する関数。
:param data_frames: 各フレームの3D座標 (X, Y, Z) のリスト。
例: [[X_frame1, Y_frame1, Z_frame1], [X_frame2, Y_frame2, Z_frame2], ...]
:param filename: 保存するGIFファイルのパス。
"""
print("フレームを生成中...")
fig = plt.figure(figsize=(8, 6)) # 図のサイズを指定
ax = fig.add_subplot(111, projection='3d')
# 軸ラベルの設定
ax.set_xlabel('X-axis')
ax.set_ylabel('Y-axis')
ax.set_zlabel('Z-axis')
# 軸の範囲をデータに合わせて自動調整、または手動で設定
# ax.set_xlim(-500, 500) # 例
# ax.set_ylim(-3, 3)
# ax.set_zlim(-3, 3)
ims = [] # 各フレームのArtistオブジェクトを格納するリスト
for i, (X, Y, Z) in enumerate(data_frames):
# プログレスバー表示
progress = (i + 1) * 100 / len(data_frames)
print(f"\r進捗: {progress:.1f}%", end="")
# 3Dプロット。marker='o' で点を表示、linestyle='None' で線を表示しない
# im = ax.plot(X, Y, Z, marker="o", color="red", linestyle='None')
# plot()はリストを返すので、ims.append(im[0])のように要素を取り出す
im, = ax.plot(X, Y, Z, marker="o", color="red", linestyle='None') # カンマでアンパック
ims.append([im]) # ArtistAnimationはリストのリストを期待する
print("\nアニメーションを生成中...")
# アニメーションの作成
# fig: アニメーションの対象となるFigureオブジェクト
# ims: 各フレームのArtistオブジェクトのリスト
# interval: フレーム間の遅延時間(ミリ秒)
# blit: Trueにすると、変更された部分のみを再描画し高速化(ただし、複雑な3Dプロットでは問題を起こす可能性あり)
ani = animation.ArtistAnimation(fig, ims, interval=50, blit=False)
# アニメーションの保存
# writer: アニメーションを保存するためのライター。'ffmpeg' や 'imagemagick' などが必要になる場合がある。
# fps: フレーム/秒
ani.save(filename, writer='pillow', fps=20) # 'pillow' は追加のライブラリ不要でGIF保存可能
print(f"アニメーションを {filename} に保存しました。")
plt.show() # アニメーションを表示
def main():
# サンプルデータの生成
# 時刻tに応じてsin波とcos波が変化する3D軌跡
t = np.linspace(0, 20 * np.pi, 500) # 0から20πまで500点
data_frames = []
for i in range(len(t)):
# 各フレームで1点だけプロットする例
X_val = t[i] / (20 * np.pi) * 5 # X軸は時間経過で変化
Y_val = np.sin(t[i])
Z_val = np.cos(t[i])
data_frames.append([[X_val], [Y_val], [Z_val]]) # 各要素をリストにする
make_animation(data_frames, filename="sin_cos_3d_animation.gif")
if __name__ == '__main__':
main()
コードの解説
matplotlib.animation.ArtistAnimation
:plot
関数が返すArtistオブジェクトのリストを渡すことで、それらのオブジェクトが各フレームで描画されるアニメーションを作成します。fig.add_subplot(111, projection='3d')
: 3Dプロットを作成するために必須です。ax.plot(X, Y, Z, ...)
: 3D空間にデータをプロットします。marker
やcolor
,linestyle
などで表示をカスタマイズできます。ani.save(filename, writer='pillow', fps=20)
: アニメーションをGIFファイルとして保存します。writer='pillow'
: Pillowライブラリを使用してGIFを生成します。別途pip install pillow
が必要ですが、ffmpeg
などの外部ツールをインストールする必要がないため手軽です。fps
: Frames Per Second(1秒あたりのフレーム数)で、アニメーションの速度を調整します。
- プログレスバー:
\r
を使って同じ行を上書きすることで、コンソールにプログレスバーを表示しています。
このコードを参考に、様々な3Dデータをアニメーション化して可視化してみてください。