我有一段代码可以从笔记本电脑的音频插孔中获取实时音频信号,并在进行一些基本过滤后绘制图形。我面临的问题是,随着程序的运行,实时绘图变得越来越慢。
有什么建议让这种绘图更快并以恒定速率进行?我认为动画功能会使它更快,但无法根据我的要求制定
import pyaudio
import numpy as np
import time
import matplotlib.pyplot as plt
import scipy.io.wavfile
from scipy.signal import butter, lfilter
import wave
plt.rcParams["figure.figsize"] = 8,4
RATE = 44100
CHUNK = int(RATE/2) # RATE / number of updates per second
#Filter co-efficients
nyq = 0.5 * RATE
low = 3000 / nyq
high = 6000 / nyq
b, a = butter(7, [low, high], btype='band')
#Figure structure
fig, (ax, ax2) =plt.subplots(nrows=2, sharex=True)
x = np.linspace(1, CHUNK, CHUNK)
extent = [x[0] - (x[1] - x[0]) / 2., x[-1] + (x[1] - x[0]) / 2., 0, 1]
def soundplot(stream):
t1=time.time()
data = np.array(np.fromstring(stream.read(CHUNK),dtype=np.int32))
y1 = lfilter(b, a, data)
ax.imshow(y1[np.newaxis, :], cmap="jet", aspect="auto")
plt.xlim(extent[0], extent[1])
plt.ylim(-50000000, 50000000)
ax2.plot(x, y1)
plt.pause(0.00001)
plt.cla() # which clears data but not axes
y1 = []
print(time.time()-t1)
if __name__=="__main__":
p=pyaudio.PyAudio()
stream=p.open(format=pyaudio.paInt32,channels=1,rate=RATE,input=True,
frames_per_buffer=CHUNK)
for i in range(RATE):
soundplot(stream)
stream.stop_stream()
stream.close()
p.terminate()
答案 0 :(得分:4)
评论有点长,因为你要求提出建议,我认为这是一个半完整的答案。如果您需要超出此处的想法,可以在线获取有关使用matplotlib进行实时绘图的更多信息和示例。该库不是为此设计的,但它是可能的。
第一步,分析代码。您可以使用
执行此操作import cProfile
cProfile.run('soundplot(stream)')
这将显示大部分时间花在哪里。 如果不这样做,我会提供一些提示,但请注意,分析可能会显示其他原因。
首先,您希望消除函数soundplot
中的冗余函数调用。以下两个都是不必要的:
plt.xlim(extent[0], extent[1])
plt.ylim(-50000000, 50000000)
可以在初始化代码中调用它们一次。 imshow
会自动更新这些内容,但为了提高速度,您不应每次都调用它。相反,在一些初始化代码 outside 中,函数使用im=imshow(data, ...)
,其中数据的大小与您要绘制的大小相同(尽管可能不需要)。然后,在soundplot
中使用im.set_data(y1[np.newaxis, :])
。不必每次迭代都重新创建图像对象,这将极大地加快速度。
由于图像对象在每次迭代中都会保留,因此您还需要删除对cla()
的调用,并将其替换为show()
或draw()
以使图形绘制为更新的图像。您可以使用line.set_ydata(y)
在第二轴上对该行执行相同操作。
请发布它运行的前后费率,如果有帮助请告诉我。
编辑:对类似代码进行一些快速分析表明速度提升100-500倍,主要来自删除cla()
。
另外看一下你的代码,它放慢速度的原因是第一个轴上没有调用cla
。最终会在该轴上绘制数百张图像,从而减慢matplotlib的爬行速度。