如何在while循环每次迭代时实时更新同一matplotlib绘图
解决方案
你遇到的每次循环新建绘图窗口的问题,核心是没有提前初始化固定画布、未开启matplotlib交互模式,且没有在每帧更新时复用同一个绘图对象。
基础实现(逻辑简单易调试)
先把画布初始化逻辑移到循环外部,开启交互模式,每帧清空上一帧内容后重绘即可,代码修改如下:
import matplotlib.pyplot as plt import pandas as pd import numpy as np # ========== 以下初始化代码放在while循环外部,不要放进循环里 ========== plt.ion() # 开启matplotlib交互模式,绘图不会阻塞后续代码执行 fig, ax = plt.subplots(figsize=(6, 6)) # 创建固定的画布与坐标轴对象,全程复用 # ================================================================== while cap.isOpened(): # 保留你原有的视频读取、mediapipe姿态检测逻辑 pose = results.pose_landmarks.landmark pose_row_x = list(np.array([[landmark.x] for landmark in pose]).flatten()) pose_row_y = list(np.array([[landmark.y] for landmark in pose]).flatten()) pose_row_z = list(np.array([[landmark.z] for landmark in pose]).flatten()) df = pd.DataFrame(data=[pose_row_x, pose_row_y, pose_row_z ]).T df.columns = ["x", "y", "z"] # ========== 每帧更新绘图 ========== ax.cla() # 清空坐标轴上上一帧的绘制内容 # 固定坐标范围,避免每帧自动缩放导致画面抖动,反转y轴匹配图像坐标系 ax.set_xlim(0, 1) ax.set_ylim(1, 0) ax.scatter(df['x'], df['y'], c='red', s=15) # 绘制当前帧的姿态点 plt.draw() # 触发画布重绘 plt.pause(0.001) # 预留GUI刷新时间,设为0会导致窗口卡死无响应
高性能实现(流畅度更高,适合高帧率场景)
如果需要更高的刷新帧率,可以不用每帧清空重建散点对象,直接更新已有散点的坐标数据,减少重绘开销:
import matplotlib.pyplot as plt import pandas as pd import numpy as np # ========== 循环外初始化 ========== plt.ion() fig, ax = plt.subplots(figsize=(6, 6)) ax.set_xlim(0, 1) ax.set_ylim(1, 0) # 提前创建空散点对象 scatter = ax.scatter([], [], c='red', s=15) # ================================= while cap.isOpened(): # 保留原有视频读取、姿态检测、DataFrame构建逻辑 pose = results.pose_landmarks.landmark pose_row_x = list(np.array([[landmark.x] for landmark in pose]).flatten()) pose_row_y = list(np.array([[landmark.y] for landmark in pose]).flatten()) pose_row_z = list(np.array([[landmark.z] for landmark in pose]).flatten()) df = pd.DataFrame(data=[pose_row_x, pose_row_y, pose_row_z ]).T df.columns = ["x", "y", "z"] # ========== 直接更新散点坐标,无需清空重绘 ========== scatter.set_offsets(df[['x', 'y']].values) plt.draw() plt.pause(0.001)
关键注意事项
- 不要把画布、轴对象的初始化代码放进循环,放到循环内就会每次迭代新建窗口,就是你当前遇到的问题
plt.pause()不能省略,否则matplotlib的GUI事件没有处理时间,会出现窗口未响应、画面不刷新的问题- 必须固定坐标轴范围,否则每帧绘图会自动适配数据范围调整缩放,导致画面跳变
- 反转y轴是为了匹配mediapipe输出的图像坐标系(原点在左上角),和你预期的姿态显示方向一致
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

