用于动画制作的OpenCV或matplotlib?

时间:2017-05-25 08:08:26

标签: python opencv matplotlib

我目前正在开发一种行为系统,它将利用移动条,旋转条,交替场,甚至是小型随机移动物体。最初所有这些都是在matlab中编写的,效果很好。但是由于与最终将使用代码的硬件不兼容,该项目已经转移到python。

我已经开始使用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()

1 个答案:

答案 0 :(得分:3)

在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