Pythonで画像回転アニメを作成する方法

このQ&Aのポイント
  • Pythonを使用して読み込んだ画像を360度回転するgifアニメを作成したいです。
  • コードを実行すると、'list index out of range'などのエラーが発生します。解決策を教えてください。
  • Colaboratoryを使用しています。
回答を見る
  • ベストアンサー

画像回転アニメ

Pythonで読み込んだ画像を360度回転するgifアニメにしたく見よう見まねで下記コードを書きました。 走り出してしばらくすると” list index out of range”などのエラーが出ます。どうしたらエラーをなくせるでしょうか?ご教示のほどよろしくお願いします。なお、Colaboratoryを使用しています。 import numpy as np import matplotlib.pyplot as plt import matplotlib.animation as animation from matplotlib.animation import PillowWriter from PIL import Image fig = plt.figure(figsize=(8,6),dpi=100) fig,ax=plt.subplots(1,1) ax.set_aspect('equal') rotor=Image.open('/rotor.png') ims = [] for i in range(360): im=rotor.rotate(angle=i,resample=Image.BICUBIC,expand=False) ims.append(im) anim = animation.ArtistAnimation(fig,ims) anim.save('ani.gif',writer="pillow",fps=10)

  • Python
  • 回答数2
  • ありがとう数0

質問者が選んだベストアンサー

  • ベストアンサー
  • asciiz
  • ベストアンサー率70% (6635/9402)
回答No.2

out of range はこのプログラム自体ではなく、呼び出したモジュール内で出ていますね? C:\Users\********\Desktop\python\q9888196>python q9888196.py Traceback (most recent call last): File "C:\Users\********\AppData\Local\Programs\Python\Python38\lib\site-packages\matplotlib\animation.py", line 236, in saving yield self File "C:\Users\********\AppData\Local\Programs\Python\Python38\lib\site-packages\matplotlib\animation.py", line 1160, in save anim._init_draw() # Clear the initial frame File "C:\Users\********\AppData\Local\Programs\Python\Python38\lib\site-packages\matplotlib\animation.py", line 1533, in _init_draw for artist in f: TypeError: 'Image' object is not iterable During handling of the above exception, another exception occurred: Traceback (most recent call last): File "q9888196.py", line 16, in <module> anim.save('ani.gif',writer="pillow") File "C:\Users\********\AppData\Local\Programs\Python\Python38\lib\site-packages\matplotlib\animation.py", line 1177, in save writer.grab_frame(**savefig_kwargs) File "C:\Users********\AppData\Local\Programs\Python\Python38\lib\contextlib.py", line 131, in __exit__ self.gen.throw(type, value, traceback) File "C:\Users********\AppData\Local\Programs\Python\Python38\lib\site-packages\matplotlib\animation.py", line 238, in saving self.finish() File "C:\Users\********\AppData\Local\Programs\Python\Python38\lib\site-packages\matplotlib\animation.py", line 540, in finish self._frames[0].save( IndexError: list index out of range 回答No.1さんご指摘の原因による異常動作だと思いますがPILの使い方よくわかってなくてどう直すのか(汗 とりあえず、こちらのページを参考に、 >Python, PillowでアニメーションGIFを作成、保存 | note.nkmk.me >https://note.nkmk.me/python-pillow-gif/ >anim = animation.ArtistAnimation(fig,ims) >anim.save('ani.gif',writer="pillow",fps=10) を ims[0].save('ani.gif', save_all=True, append_images=ims[1:], loop=0, duration=100) に入れ替えたところ、きちんとGifファイル生成できました。(10fps = 1フレーム 100ms (→duration指定))

dreamquest
質問者

補足

有り難うございました。実は質問した後、同じサイトをみつけims[0].save('ani.gif', save_all=True, append_images=ims[1:], loop=0, duration=100)試しうまくいきました。只、意味が全く分からないのですがこのメソッドはアニメーション化とSaveの機能を持っているのでしょうか。このメソッドはPILのものでしょうか?素人なので変な聞き方になっていたらご容赦ください。

その他の回答 (1)

  • akira1720
  • ベストアンサー率80% (127/158)
回答No.1

なぜ list index out of range エラーになるのかうまく説明できませんが、とりあえず ArtistAnimation の第2引数は Artist オブジェクトのリストでないといけないのに、PIL の Image オブジェクトのリストを渡しているのが問題だと思います。

関連するQ&A

  • matplotlibのグラフgif動画の背景透過法

    現在、以下の解説サイトを参考に、 タイマーカウントありのグラフ動画の作成をArtistAnimationにて試みています。 https://www.yutaka-note.com/entry/matplotlib_artist_anim 「plt.show()」による表示だけでなく、gif動画で自動保存したいため、 参考サイトどおり以下のコードを末尾に追加しています。 anim.save("ファイル名.gif", writer="pillow") ただ、背景(グラフ領域と余白部分)を透明化(透過)させたいため、 以下のコードをグラフ領域の作成直後に追加しています。 fig.patch.set_alpha(0.0) すると、自動保存されたgifファイルは、背景の透明化はされているものの、 タイマー文字ならびにグラフ枠線や軸タイトルといったレイアウトが全て上書きされて出力されてしまいました。 (画像参照、タイマー文字は潰れ、グラフレイアウトはジャギーのようになっています。) 「plt.show()」での表示はきちんと背景が透明化された上で想定通りの挙動を示しているため、 原因としては「anim.save()」の部分だと考えているのですが、 色々と試行錯誤しても想定通りの挙動(上書きされずに透明化)が叶いません。 pillowライブラリの構造の関係で無理筋なのかもしれませんが、 gifファイル自動保存の前提を崩さない上で、上手いコーディング方法をご存じの方がもしおられましたら、 教えていただけますと助かります。 (出力後の別途の画像コンバートや、ffmpeg等の外部ツールを入れてのMP4出力は考えていません。 できるだけ簡便な手法を望んでいます。) 【以下、問題としているサンプルコード】 # 1. 必要なモジュールの読み込み import numpy as np from matplotlib import pyplot as plt from matplotlib.animation import ArtistAnimation # 2.グラフ領域の作成 fig, ax = plt.subplots() fig.patch.set_alpha(0.0) #背景部分の透明化 # 3. アニメーション要素のリスト artists = [] for i in range(100): x = np.linspace(0, 4*np.pi) y = np.sin(x - i/100 * 2*np.pi) # アニメーション化する要素の準備 my_line, = ax.plot(x, y,"blue") my_text = ax.text(0, y[0], " ? inlet", color="darkblue", size ="large") my_title = ax.text( 4.5, 1.15, f"Count = {i}", size="xx-large") # アニメーション化する要素をリスト化 artists.append([my_line, my_text, my_title]) # 4. アニメーション化 anim = ArtistAnimation(fig, artists, interval=50) plt.show() anim.save("ファイル名.gif", writer="pillow") #透明化はされるがgifファイル上で文字が上書きされる

  • Jupyter notebook上でのアニメ出力

    Jupyter notebookでグラフを出力しながら実習しているのですが、アニメを表示するところでエラーになります。 jupyte notebookのスクリプト抜粋 fig = plt.figure(figsize=(10,7)) anim = ani.FuncAnimation(fig, animate, frames=int(num_frame), blit=True) anim.save('likelihood.gif', writer='imagemagick', fps=1, dpi=64) ←ここ ↓ 実行結果エラーが出る。 エラーメッセージの抜粋 anim.save('likelihood.gif', writer='imagemagick', fps=1, dpi=64) ←ここ animation.py in _draw_frame(self, framedata) raise RuntimeError('The animation function must return a ''sequence of Artist objects.') 何か前提とされているものをimportしていないのか、あるいは外部のアニメ作成ツールを呼び出して利用したいけどできないと言っているのかだと思うのですが。 メッセージにimagemagickとかgifアニメとか割とおなじみの名前があり、外部を呼び出そうしているなと思ったのですが。pythonは外部のC++コンパイラを利用したりするのでその方向なのかなと思ったのですが。OSはWindows10です。 プロンプトではimagemagickというコマンドは起動しません。一応インストールはしているのですが、インストール先を見てもimagemagickという実行ファイルがないようなのですが。よろしくお願いします。

  • python PIL のインデックスモードでの保存

    python の画像処理ライブラリ PIL にてインデックスモードの画像を読み込んだときの処理について 質問があります。 下記のコードのように png (インデックスモード) の画像を読み込んでピクセルの値を変えて 再びインデックスモードで保存しようと試みました。 しかし、出力された画像には色がついておらず、白黒の画像になっていました。 色の情報が抜けてしまったのですがどこが間違っているかわかりません。 どなたか分かるかたはいらっしゃらないでしょうか。 ご回答いただけたら幸いです。 よろしくお願いします。 from PIL import Image import numpy as np import sys origin = (0,1,4,4,5) to = (0,1,4,4,5) for ID in open(sys.argv[1]): ID = ID.strip() im=Image.open(ID+'.png') print im.info imnp=np.array(im) for (i, j) in zip(origin,to): imnp[imnp==i] = j pil_img = Image.fromarray(np.uint8(imnp),mode="P") pil_img.save(ID+'_con.png','bmp')

  • pythonでの\記号の使い方

    pythonのmatplotlibのpyplotのtitle()分ですが、下記の記述の"\"記号の使い方の意味が完全には分かりかねています。どなたか分かる方、御教示ください。 import matplotlib.pyplot as plt plt.title(r'$\mathrm{Histgram\ of\ Height:}\ \mu=%d,\ \sigma=%d$' % (mu, sigma)) なお、r'~'は「~」の部分をエスケープしないでraw文字として出力することは分かっています。 よろしくお願い致します。

  • pandas-bokehのY軸の値を指数表記にしな

    今回、年寄りの冷や水ですがpythonに興味を持ちいろいろ試しています。htmlでグラフ表示するためpandas-bokehを追加しました。Y軸のデータの桁数が大きい場合グラフの値が自動的に指数表記になります。matplotlib.pyplotの場合は問題がなかったのでちょっと不便です。これを慣れている自然数の表記にしたいのでご教授お願いいたします。参考まで下記にコードを記しておきます。 matplotlib.pyplotの場合 import pandas as pd import matplotlib.pyplot as plt import japanize_matplotlib data = pd.read_csv('py003.csv',encoding="utf-8") #プロットするデータの範囲 df = data.iloc[:,[0,1,2,3]] df.plot(kind='bar',x=df.columns[0],figsize=(7, 5), rot=0,width=0.85,linewidth=1, edgecolor="w") plt.legend(ncol=3) plt.show() pandas-bokehの場合 import pandas as pd import pandas_bokeh pandas_bokeh.output_file("Interactive Plot.html") data = pd.read_csv('py003.csv',encoding="utf-8") df = data.iloc[:,[0,1,2,3]] p_bar = df.plot_bokeh.bar( x=df.columns[0], ylabel="金額 (千円)", title="月別売り上げ", alpha=0.6) ズブの素人ですがよろしくお願いいたします。

  • JAVAの文法について教えてください。

    JAVAを学習しはじめたばかりの初心者です。 下記のプログラムに関してわからないので教えてください。 下記はtest.gif画像を表示するプログラムなのですが、 イメージを表示するために import java.awt.Graphicsをインポートして、 Image im でオブジェクトを宣言するのはわかるのですが、 通常はこの後に im = new Image() のようにインスタンス化する必要があると思うのですが、 このプログラムにはありません。 なぜ不要なのでしょうか? ********************** import java.applet.Applet; import java.awt.Graphics; import java.awt.Image; public class MyImage extends Applet{ Image im; public void init(){ im = getImage( getDocumentBase(), "test/test.gif" ); } public void paint(Graphics g){ g.drawImage( im ,10,10, this); } }

    • ベストアンサー
    • Java
  • matplotlibのプロットに配列を使用する方法

    下記のサイト等を参考にして、PythonのmatplotlibのFuncAnimationにて、 グラフプロットのアニメーションを作ろうとしています。 https://sabopy.com/py/matplotlib-animation-62/ https://www.yutaka-note.com/entry/matplotlib_func_anim 測定データ(n個)毎、および測定時間(m個)毎に、プロットするべきデータがx軸, y軸でそれぞれ存在し、 それらプロットの数値は各々、【plot_data_x[n][m]】, 【plot_data_y[n][m]】という配列に予め格納されているとします。 その上で、 for counter in range(n): for counter in range(m): plot_list[n][m], = ax.plot([], []) for counter in range(n): for counter in range(m): plot_list[n][m].set_data((plot_data_x[n][m], plot_data_y[n][m])) というような形にすると、【set_data】メソッドが正常に機能しないのか、予約後表記にもならず(VSCode環境)エラーで弾かれます。 (あるいは【plot_list[n][m]】が想定通りに初期化されていない?) for文を使わず【plot1_1】,【plot1_2】…のように単一の変数を列挙する形式であれば動作したのですが、 どうしても配列になると動いてくれません。 これはそもそも【ax.plot】や【.set_data】が配列に対応していないのでしょうか。 それともコードのどこかしらに間違いがあるのでしょうか。 お手数をおかけして申し訳ありませんが、 どなたか詳しい方おられましたら配列で動かす手段を教えていただけますと助かります。 よろしくお願いします。

  • インターネット上の画像をJavaで処理する方法について

    こんにちは! いつもお世話になってます(^^) mkimさんのおかげでマウスでブラウザ(IE5.0)上の灰色の部分の座標値を得ることはできました(^o^) 私の質問 http://oshiete1.goo.ne.jp/kotaeru.php3?q=77352 しかし、その灰色の部分に画像を貼り付け、その画像の座標値を得たいのですが、画像をうまく貼り付けることができません。 javaファイルのと同じディレクトリにあるローカルな画像は貼り付けて座標値を得ることができたのですが、インターネット上にある画像を貼り付けることができませんでした。 最終的にはライブカメラの画像を貼り付けようと考えているので、これができないと先に進むことができません。 誰かご存知でしたら教えてください(^^) わかりにくい質問でごめんなさいm(__)m 一応、うまくいかなかったjavaファイルを載せておきます。 // My_Image03.java import java.awt.Graphics; import java.applet.Applet; import java.awt.Image; public class My_Image03 extends Applet { Image im; public void init() { im = getImage(getDocumentBase(), "http://www.honda.co.jp/image/b_hmark.gif"); } public void paint(Graphics g) { g.drawImage(im, 10, 10, this); } } 構文が間違っているのでしょうか? 回答、お待ちしております(^o^)丿

    • ベストアンサー
    • Java
  • jpeg画像でアニメーションを作る

    jpeg画像10枚くらいをつかい、アニメーションを作りたく以下のようなプログラム(全部載せられませんでした)を組んでみました。しかし、画像読み込みにすごく時間がかかり、アニメーションという感じがしないほど、さっと画像が表示されて終わってしまいます。もっと、一枚一枚をゆっくり表示させたく画像読み込みの時間も短縮したいのですが、何か良い方法はありますでしょうか(ちなみに画像のキャンバスサイズは512×384です) import java.applet.*; import java.awt.*; import java.net.*; public class im2a extends Applet implements Runnable{ Image im[] = new Image[10]; URL url; String fn[]={"anime10.jpg","anime11.jpg","anime4.jpg","anime5.jpg",  "anime1.jpg","anime2.jpg","anime1.jpg","anime2.jpg",  "anime8.jpg","anime7.jpg"}; Thread th; MediaTracker mt = new MediaTracker(this); String ms =""; String s =""; int i=0; int j=0; int dt=100; int phase=2 ; boolean ok=false;   public void start(){ th =new Thread(this); th.start(); }    public void readImage(){ ms ="画像入力準備中"; repaint(); for(i=0;i<9;++i){ im[i]=getImage(getDocumentBase(),fn[i]); mt.addImage(im[i],i); ok=false; while(!ok){ try{ Thread.sleep(2000); } catch(InterruptedException ee) { } ok=mt.checkID(i,true); } ms="画像"+i+"読み込み終了"; repaint(); } }

  • Androidプログラムについて

    多数の画像を、パラパラ漫画のように切り替えていく方法について相談があり、投稿させていただきました。 以前、xmlファイルで画像を読み込む方法が簡単だということで、hirotn様にご回答いただき、 動作させることができました。 ありがとうございました。 携帯の実機にインストールし、エラーも出ず動作することも確認できたのですが、 画像を切り替えるタイミングがあまりにも遅くなっており困っています。 画像が多い場合は、メモリ不足等起こっているのでしょうか。 プログラムで解決できる方法があれば教えていただきたく、よろしくお願いします。 (ちなみに、xmlファイルで読み出すファイルは100枚程度(80MB程度)です。 もっと数を増やしたり、画質をよくしたいとも思っております。) ※サンプルは下記で見つけました。 http://monoist.atmarkit.co.jp/mn/articles/1205/21/news003.html (以下、プログラム) package jp.test.animation.frame; import android.app.Activity; import android.content.Context; import android.graphics.drawable.AnimationDrawable; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.ImageView; public class FrameAnimationTestActivity extends Activity { // ボタン Button mBtnAnimation; Button m5BtnAnimFromXML; // ビュー ImageView mImageAnimation; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mBtnAnimation = (Button) findViewById( R.id.button_animation ); m5BtnAnimFromXML = (Button) findViewById( R.id.button_anim_from_xml ); mImageAnimation = (ImageView) findViewById( R.id.image_animation ); mBtnAnimation.setOnClickListener(mClickListener); m5BtnAnimFromXML.setOnClickListener(mClickListener); } View.OnClickListener mClickListener = new View.OnClickListener() { public void onClick(View v) { // アニメーション中なら、停止 Drawable d = mImageAnimation.getBackground(); if( d != null ){ try{ if( ((AnimationDrawable) d).isRunning() ){ ((AnimationDrawable) d).stop(); return; } } catch( RuntimeException e ){ e.printStackTrace(); } } //if( v == mBtnAnimation ){ //frameAnimationTest( //FrameAnimationTestActivity.this, mImageAnimation ); //} if( v == m5BtnAnimFromXML ){ frameAnimationFromXMLTest( mImageAnimation ); } } }; // フレームアニメーションを XML から読み込む void frameAnimationFromXMLTest( View v ){ // リソースからアニメーションを読み込み、ビューに設定 v.setBackgroundResource( R.drawable.droid_jump ); // ビューからアニメーションを取り出し AnimationDrawable anim = (AnimationDrawable)v.getBackground(); // アニメーション開始 anim.start(); } }

専門家に質問してみよう