web-dev-qa-db-ja.com

matplotlibのimshow()ウィンドウをインタラクティブに更新する方法は?

私はコンピュータービジョンアルゴリズムに取り組んでおり、各ステップでnumpy配列がどのように変化するかを示したいと思います。

現在機能しているのは、コードの最後に単純なimshow( array )がある場合、ウィンドウに最終画像が表示されて表示されるということです。

しかし、私がやりたいのは、イメージが各反復で変化するときにimshowウィンドウを更新して表示することです。

例えば、私がやりたいことは:

_import numpy as np
import matplotlib.pyplot as plt
import time

array = np.zeros( (100, 100), np.uint8 )

for i in xrange( 0, 100 ):
    for j in xrange( 0, 50 ):
        array[j, i] = 1

        #_show_updated_window_briefly_
        plt.imshow( array )
        time.sleep(0.1)
_

問題は、この方法では、Matplotlibウィンドウがアクティブにならず、計算全体が終了した後にのみアクティブになるということです。

ネイティブmatplotlibとpyplotの両方を試しましたが、結果は同じです。コマンドをプロットするために.ion()スイッチを見つけましたが、ここでは機能していないようです。

Q1。 numpy配列(実際にはuint8グレースケール画像)の更新を継続的に表示する最良の方法は何ですか?

Q2。 動的画像の例 のように、アニメーション機能でこれを行うことは可能ですか?ループ内で関数を呼び出したいので、アニメーション関数でこれを実現する方法がわかりません。

34
hyperknot

常にimshowを呼び出す必要はありません。オブジェクトの_set_data_メソッドを使用する方がはるかに高速です。

_myobj = imshow(first_image)
for pixel in pixels:
    addpixel(pixel)
    myobj.set_data(segmentedimg)
    draw()
_

draw()は、バックエンドが画像を更新することを確認する必要があります。

PDATE:質問は大幅に変更されました。そのような場合、別の質問をすることをお勧めします。 2番目の質問に対処する方法を次に示します。

Matplotlibのアニメーションは、増加する1つの次元(時間)のみを処理するため、二重ループは処理しません。インデックスを単一のインデックスに変換する必要があります。以下に例を示します。

_import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation

nx = 150
ny = 50

fig = plt.figure()
data = np.zeros((nx, ny))
im = plt.imshow(data, cmap='Gist_gray_r', vmin=0, vmax=1)

def init():
    im.set_data(np.zeros((nx, ny)))

def animate(i):
    xi = i // ny
    yi = i % ny
    data[xi, yi] = 1
    im.set_data(data)
    return im

anim = animation.FuncAnimation(fig, animate, init_func=init, frames=nx * ny,
                               interval=50)
_
35
tiago

ニーズに合った便利なスクリプトを実装しました。試してみてください こちら

動的な正弦波を描く例:

import numpy as np

def redraw_fn(f, axes):
  amp = float(f) / 3000
  f0 = 3
  t = np.arange(0.0, 1.0, 0.001)
  s = amp * np.sin(2 * np.pi * f0 * t)
  if not redraw_fn.initialized:
    redraw_fn.l, = axes.plot(t, s, lw=2, color='red')
    redraw_fn.initialized = True
  else:
    redraw_fn.l.set_ydata(s)

redraw_fn.initialized = False

videofig(100, redraw_fn)
1
Bily