python matplotlib绘制动态曲线 数据流可视化

很多时候需要在程序运行过程中,查看一些数据的动态变化,最容易想到的是像opencv那样直接循环使用imshow()形成动态画面,但是由于matplotlib中的显示模式是阻塞模式,在plt.show()之后程序就会暂停在那,打开一个窗口以后必须关掉才能继续执行,这样用matplotlib画动态图就像播放ppt,关闭一个窗口后弹出下一个。关于matplotlib包的任何信息都可以直接在它官网查询。本文总结了几种方法实现在程序运行中绘制动态图的方法,以画动态正弦曲线为例。

第一种方法:plt.show()放在程序最后

既然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()代替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()

另一种方法是在程序前面用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函数

还有一种使用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

你可能感兴趣的:(python matplotlib绘制动态曲线 数据流可视化)