2016-11-22 293 views
-1

我需要你的帮助,解决我最近处理它的问题。 我可以绘制从我的手机蓝牙传输并通过我的笔记本电脑的COM端口接收的串行数据。乍一看,它似乎是好的,但最多它可以每260毫秒(〜3 fps)绘制。但手机每100毫秒发送一次数据。我很确定这个问题来源于“情节”和“身材”命令,这让我感到困惑。我很感激,如果有人可以纠正我的代码:在Matplotlib中使用动画功能缓慢绘图,Python

from Tkinter import * 
import serial 
import matplotlib.pyplot as plt 
import matplotlib.animation as animation 
fig = plt.figure() 
ax1 = fig.add_subplot(1, 1, 1) 
ser = serial.Serial("COM4", baudrate=115200, timeout=0.1) 
cnt=0 
xComponent=[] 
plt.ylim(0,30) 
while (ser.inWaiting() == 0): # Wait here until there is data 
    pass 
def animate(i): 

    BluetoothString = ser.readline() 
    ser.flush() 
    dataArray = BluetoothString.split(',') 
    x = float(dataArray[2]) # we only need 3rd component 
    xComponent.append(x) 
    print xComponent 
    ax1.clear() 
    ax1.plot(xComponent) 
    plt.ylim(0,25) 
    global cnt 
    if (cnt > 16): 
     xComponent.pop(0) 
    else: 
     cnt = cnt + 1 

ani = animation.FuncAnimation(fig, animate, interval=0) 
plt.show() 
+0

这段代码什么都不做。 “FuncAnimation”在哪里? – furas

+0

@furas它来自[mpl](http://matplotlib.org/api/animation_api.html#matplotlib.animation.FuncAnimation) – Aaron

+0

我知道'FuncAnimation'是来自'mpl',但我确实在你的代码中看到它。但我看到你改变了代码。 – furas

回答

1

很难说你的特殊情况,任何事情,因为我们没有您所使用的串行连接的部分。

然而,绘图应该比matplotlib中的3 fps快得多,如果这只是一个有一些点的线图。 一两件事你可以直接尝试不要在每个迭代步骤重新绘制的一切,但一旦绘制它,然后只用.set_data()

下面的例子是密切相关的代码更新数据,并以90 fps的在我的机器上运行。所以,也许你会尝试一下,看看它是否有助于加速你的情况。

import matplotlib.pyplot as plt 
import matplotlib.animation as animation 
import time 

fig = plt.figure() 
ax1 = fig.add_subplot(1, 1, 1) 

cnt=0 
xComponent=[] 

line, = ax1.plot([0], [0]) 
text = ax1.text(0.97,0.97, "", transform=ax1.transAxes, ha="right", va="top") 

plt.ylim(0,25) 
plt.xlim(0,100) 
last_time = {0: time.time()} 
def animate(i): 

    if len(xComponent)>100: 
     xComponent.pop(0) 
    y = i % 25 
    xComponent.append(y) 

    line.set_data(range(len(xComponent)) ,xComponent) 
    new_time = time.time() 
    text.set_text("{0:.2f} fps".format(1./(new_time-last_time[0]))) 
    last_time.update({0:new_time}) 


ani = animation.FuncAnimation(fig, animate, interval=0) 
plt.show() 
+0

哇,非常感谢你“ImportanceOfBeingErnest”。我可以看到巨大的速度在我的代码:-) –

0

我不想踩脚趾任何这里,因为@ImportanceOfBeingErnest钉它,但添加blitting他跳下例如我的帧率从50到300这里是如何做到这一点在他的例子:我留下评论在这里我所做的更改

import matplotlib.pyplot as plt 
import matplotlib.animation as animation 
import time 

fig = plt.figure() 
ax1 = fig.add_subplot(1, 1, 1) 

cnt=0 
xComponent=[] 

line, = ax1.plot([0], [0]) 
text = ax1.text(0.97,0.97, "", transform=ax1.transAxes, ha="right", va="top") 

plt.ylim(0,25) 
plt.xlim(0,100) 
last_time = {0: time.time()} 

def animateinit(): #tells our animator what artists will need re-drawing every time 
    return line,text 

def animate(i): 

    if len(xComponent)>100: 
     xComponent.pop(0) 
    y = i % 25 
    xComponent.append(y) 

    line.set_data(range(len(xComponent)) ,xComponent) 
    new_time = time.time() 
    text.set_text("{0:.2f} fps".format(1./(new_time-last_time[0]))) 
    last_time.update({0:new_time}) 
    return line,text #return the updated artists 

#inform the animator what our init_func is and enable blitting 
ani = animation.FuncAnimation(fig, animate, interval=0,init_func=animateinit, blit=True) 
plt.show() 

在MPL每个绘制调用是相当昂贵的,所以如果我们能够尽可能我们可以看到一个巨大的速度提升为小画。通过告诉动画师只重绘某些元素,我们避免了重新绘制诸如轴标记,轴标签,计算缩放等事物。这些事情看起来很简单,但其中有很多,而且开销很快累加起来。

+1

我没有说blitting在许多情况下不会有用。当数据每100毫秒到达一次(最大10fps)时,看起来有点矫枉过正。由于没有blitting的例子已经达到了人脑无法检测到的帧率,因此可能不需要它。 (就我个人而言,我会尽量避免blitting,因为当你需要照顾缩放,调整大小等等时,它也会导致大量开销代码。如果可能需要blitting,我会直接从Matplotlib更改为pyqtgraph,它) – ImportanceOfBeingErnest

+0

@ImportanceOfBeingErnest我不熟悉像串口通过蓝牙这样的东西,所以我个人会赞成加速数据在不规则时间间隔出现的情况下,希望能够减少溢出的风险缓冲..只是以为我会加入,因为它只有4条线,知道该怎么做是件好事 – Aaron

+0

亚伦你是完美的。你解决了我的问题。非常感谢你 –