2017-05-25 66 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