使用OpenCV还是matplotlib来制作动画?

3
我目前正在开发一个行为系统,它将利用移动条、旋转条、交替场甚至小的随机移动物体。最初,这些都是使用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个回答

3
在 while 循环中进行动画似乎相当奇怪。因此,应该选择第二个代码版本。
动画看起来不同步的原因实际上与重绘时间或类似事项无关。这更像是插值的效果。矩形的宽度和位置需要四舍五入为屏幕像素。根据时间步长,矩形位置可能会偏离一个像素;此外,条形的宽度可以偏离 2 个像素(每侧加减一)。这会导致不期望的动画效果。
为了解决这个问题,您需要考虑像素。确保轴范围是整数,并等于屏幕上的像素数。然后将条形宽度设置为一个像素的倍数。使用 FuncAnimationinterval 参数控制动画的速度,而不是步骤。使用恰好一个像素作为步长。
以下是完整的示例:
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


没有考虑到这个方面,感谢您指出。第一组代码中while循环的目的是尝试在短时间内对图形进行动画处理,然后停止运行。但是当我尝试按顺序运行plt.show()-->animate-->plt.clf时,图形会显示出来,然后立即消失。 - Hojo.Timberwolf
1
要停止动画,您可以使用anim.event_source.stop(),请参见此问题。您可以通过鼠标单击或另一个计时器触发此操作。 - ImportanceOfBeingErnest

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接