2017-05-25 71 views
2

我目前正在開發一個行爲系統,它將利用移動的酒吧,旋轉酒吧,交替的領域,甚至小型隨機移動物體。最初所有這些都是在matlab中編程的,並且效果很好。然而,由於與最終將使用代碼的硬件不兼容,該項目已被轉移到python。OpenCV或matplotlib動畫建設?

我已經開始使用python中的matplotlib模塊編程系統,並取得了一些好成績。我利用matplotlib中的動畫函數來產生快速移動物體的一致且流暢的運動。然而,當我深入研究用matplotlib進行編程時,我注意到了一些問題。其中一個特別的是物體的流體運動並不像以前想象的那樣流暢。

因爲我將利用opencv作爲行爲系統的另一部分,所以我想知道opencv是否比matplotlib具有任何特別的優勢,特別是關於繪製速率和動畫。

我會在下面進行更詳細的介紹。

這是構建動畫腳本的一部分,注意這個版本崩潰了,我還沒有弄清楚爲什麼。

import numpy as np 
import matplotlib.pyplot as plt 
import matplotlib.patches as patches 
import matplotlib.animation as animation 
import time 

fig = plt.figure() 
ax = fig.add_subplot(111) 
fig.patch.set_facecolor([0,0,0]) 
fig.tight_layout() 

plt.xlim(-100, 100) 
plt.ylim(-100, 100) 
plt.axis('off') 

# List of variables 
width = 1 
bars = 20 
spacing = 20 
step = .01 
direction = -1 

RB = [] # Establish RB as a Python list 
for a in range(bars): 
    RB.append(patches.Rectangle((a*spacing-200,-100), width, 200, 
      color=[1,0,0], alpha=0.50)) 

def init(): 
    for a in range(bars): 
     ax.add_patch(RB[a]) 
    return RB 

def animate(i): 
    for i in range(bars): 
     temp = np.array(RB[i].get_xy()) 
     if temp[0] > 200: 
      temp[0] = -199 
     elif temp[0] < -200: 
      temp[0] = 199 
     else: 
      temp[0] = temp[0] + step*direction; 
     RB[i].set_xy(temp) 
    return RB 

t = time.time() 
plt.show() 

while t < timewidow 
    anim = animation.FuncAnimation(fig, animate, 
          init_func=init, 
          frames=30, 
          interval=1, 
          blit=True) 

fig.clf() 

做功的代碼就在這裏。只是每個單獨的對象不會彼此同步移動。

import numpy as np 
import matplotlib.pyplot as plt 
import matplotlib.patches as patches 
import matplotlib.animation as animation 
import time 

fig = plt.figure() 
ax = fig.add_subplot(111) 
fig.patch.set_facecolor([0,0,0]) 
fig.tight_layout() 

plt.xlim(-100, 100) 
plt.ylim(-100, 100) 
plt.axis('off') 

# List of variables 
width = 1 
bars = 20 
spacing = 20 
step = .01 
direction = -1 

RB = [] # Establish RB as a Python list 
for a in range(bars): 
    RB.append(patches.Rectangle((a*spacing-200,-100), width, 200, 
      color=[1,0,0], alpha=0.50)) 

def init(): 
    for a in range(bars): 
     ax.add_patch(RB[a]) 
    return RB 

def animate(i): 
    for i in range(bars): 
     temp = np.array(RB[i].get_xy()) 
     if temp[0] > 200: 
      temp[0] = -199 
     elif temp[0] < -200: 
      temp[0] = 199 
     else: 
      temp[0] = temp[0] + step*direction; 
     RB[i].set_xy(temp) 
    return RB 

anim = animation.FuncAnimation(fig, animate, 
          init_func=init, 
          frames=30, 
          interval=1, 
          blit=True) 
plt.show() 

回答

2

在while循環中做動畫看起來很奇怪。因此,走的路將肯定是第二代碼版本。

動畫看起來不同步的原因實際上並不涉及重繪或類似的時間。這更多的是插值的效果。矩形的寬度和位置需要四捨五入到屏幕像素。取決於時間步長,矩形位置因此可以偏離一個像素;此外,條的寬度可以偏離2個像素(每邊加/減1)。這導致不希望的動畫。

爲了克服這個問題,你需要考慮像素。確保軸範圍是一個整數並且等於屏幕上的像素數。然後使條寬爲一個像素的倍數。使用interval參數控制動畫的速度,以代替步驟FuncAnimation。恰好使用一個像素作爲步長。

一個完整的例子:

import numpy as np 
import matplotlib.pyplot as plt 
import matplotlib.patches as patches 
import matplotlib.animation as animation 

fig = plt.figure(figsize=(5,3), dpi=100) #figure is 500 pixels wide 
ax = fig.add_subplot(111) 
fig.patch.set_facecolor([0,0,0]) 
fig.subplots_adjust(left=.04, right=1-.04) #axes is now 460 pixels wide 

plt.xlim(-230, 230) # distribute 460 pixels over x range 
plt.ylim(-100, 100) 
plt.axis('off') 

# List of variables 
width = 4 
spacing = 20 
bars = int(460/spacing) # make sure bars fit into range 
direction = -1 

RB = [] # Establish RB as a Python list 
for a in range(bars): 
    RB.append(patches.Rectangle((a*spacing-230,-100), width, 200, 
      color=[1,0,0], alpha=0.50)) 

def init(): 
    for a in range(bars): 
     ax.add_patch(RB[a]) 
    return RB 

def animate(i): 
    for j in range(bars): 
     temp = np.array(RB[j].get_xy()) 
     if temp[0] >= 230: #### use >= instead of > to mimic exactly one step 
      temp[0] = -229 
     elif temp[0] <= -230: 
      temp[0] = 229 
     else: 
      temp[0] = temp[0] + direction # each step should be one pixel 
     RB[j].set_xy(temp) 
    return RB 

anim = animation.FuncAnimation(fig, animate, 
          init_func=init, 
          frames=20, 
          interval=10, # control speed with thie interval 
          blit=True) 
plt.show() 

enter image description here

+0

沒想到這個方面,謝謝指點出來。第一組代碼中while循環的目的是試圖在短時間內動畫並讓它停止運行。但是,當我試圖按順序運行代碼plt.show() - > animate - > plt.clf。這個數字會出現並立即消失。 –

+1

要停止動畫,您可以使用'anim.event_source.stop()',參見[這個問題](https://stackoverflow.com/questions/16732379/stop-start-pause-in-python-matplotlib-animation) 。你可以通過點擊鼠標或[另一個計時器]來觸發它(https://matplotlib.org/examples/event_handling/timers.html) – ImportanceOfBeingErnest