2016-11-22 89 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

亞倫你是完美的。你解決了我的問題。非常感謝你 –