很多时候需要在程序运行过程中,查看一些数据的动态变化,最容易想到的是像opencv那样直接循环使用imshow()形成动态画面,但是由于matplotlib中的显示模式是阻塞模式,在plt.show()之后程序就会暂停在那,打开一个窗口以后必须关掉才能继续执行,这样用matplotlib画动态图就像播放ppt,关闭一个窗口后弹出下一个。关于matplotlib包的任何信息都可以直接在它官网查询。本文总结了几种方法实现在程序运行中绘制动态图的方法,以画动态正弦曲线为例。
既然plt.show会阻塞后面的程序,那么就把plt.show放在程序最后。另外要在每次plot以前清除上次显示结果,并让画图窗口暂停一段时间来显示。
import matplotlib.pyplot as plt
import numpy as np
POINTS = 100
sin_list = [0] * POINTS
indx = 0
# fig, ax = plt.subplots()
while True:
if indx == 40:
indx = 0
indx += 1
# 更新绘图数据
sin_list = sin_list[1:] + [np.sin((indx / 20) * np.pi)]
# 显示时间
plt.pause(0.01)
# 清除上一次显示
plt.cla()
plt.plot(sin_list)
#plt.show()如果放在这个位置就会卡住
plt.show() #放在最后不会影响之后的代码执行
还可以用plt.draw()代替plt.show(),plt.draw放置的位置就比较多了,也要在程序中清除上次显示结果,并让画图窗口暂停一段时间来显示,画正弦函数动态图例子如下:
import matplotlib.pyplot as plt
import numpy as np
POINTS = 100
sin_list = [0] * POINTS
indx = 0
# fig, ax = plt.subplots()
while True:
if indx == 40:
indx = 0
indx += 1
# 更新绘图数据
sin_list = sin_list[1:] + [np.sin((indx / 20) * np.pi)]
# 显示时间
plt.pause(0.01)
# 清除上一次显示
plt.cla()
plt.plot(sin_list)
# plt.draw()也可以放在这个位置,不会阻塞
plt.draw()
另一种方法是在程序前面用plt.on()开启交互模式,交互模式下plot之后直接显示出来,不再需要用plt.show(),并且显示时画图闪现就继续执行下去,因此也要让窗口暂停一段时间。同样是画正弦函数动态图例子如下:
import matplotlib.pyplot as plt
import numpy as np
POINTS = 100
sin_list = [0] * POINTS
indx = 0
# 开启交互模式
plt.ion()
while True:
if indx == 40:
indx = 0
indx += 1
# 更新绘图数据
sin_list = sin_list[1:] + [np.sin((indx / 20) * np.pi)]
# 显示时间
plt.pause(0.01)
# 清除上一次显示
plt.cla()
plt.plot(sin_list)
上面代码在更新图像时都是全部重新绘图,包括坐标轴以及曲线,每次更新图像可以只用更新曲线,而不更新坐标轴,这样耗时更短,占用资源最少。方法就是获取曲线句柄,这里用plt.sraw()这种方法来举例,直接上代码:
import matplotlib.pyplot as plt
import numpy as np
POINTS = 100
sin_list = [0] * POINTS
indx = 0
fig, ax = plt.subplots()
# 设置坐标轴信息
ax.set_ylim([-2, 2])
ax.set_xlim([0, POINTS])
ax.set_xticks(range(0, 100, 10))
ax.set_yticks(range(-2, 3, 1))
ax.grid(True)
line_sin, = ax.plot(range(POINTS), sin_list)
while True:
if indx == 40:
indx = 0
indx += 1
# 更新绘图数据
sin_list = sin_list[1:] + [np.sin((indx / 20) * np.pi)]
line_sin.set_ydata(sin_list)
plt.pause(0.01)
# 不用再调用plot了,也不用再清除上一次显示结果
还有一种使用FuncAnimation函数绘制动态图的方法,官方文档在这。这种方法效率是最高的,但是一旦执行就陷入到更新曲线的函数中去,一直不断循环更新,不能执行其他代码,可以考虑放入一个线程。
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation # 动图的核心函数
import numpy as np
POINTS = 100
sin_list = [0] * POINTS
indx = 0
fig, ax = plt.subplots()
# 设置坐标轴
ax.set_ylim([-2, 2])
ax.set_xlim([0, POINTS])
ax.set_autoscale_on(False)
ax.set_xticks(range(0, 100, 10))
ax.set_yticks(range(-2, 3, 1))
ax.grid(True)
line_sin, = ax.plot(range(POINTS), sin_list)
# 用来更新line_sin
def update_line(i):
global sin_list, line_sin
sin_list = sin_list[1:] + [np.sin((i / 10) * np.pi)]
line_sin.set_ydata(sin_list)
return [line_sin]
ani = FuncAnimation(fig, update_line, interval=100, frames=500)
plt.show()
https://www.cnblogs.com/zhangwei22/p/9937621.html
https://blog.csdn.net/eaglesimu/article/details/81385910
https://www.cnblogs.com/Shepard/p/9609194.html
https://blog.csdn.net/zbrwhut/article/details/80625702