如何使用matplotlib FuncAnimation实现numpy数组滑动窗口的动画展示
滑动窗口信号峰值检测动画实现方案
核心逻辑
frames参数直接传入所有滑动窗口的起始偏移量,范围为0到len(信号数组)-窗口长度,每个frame值对应当前窗口的左边界- 初始化函数仅创建空的线条、散点对象,固定y轴范围避免画面跳动
- 逐帧更新函数接收frame作为参数,按窗口范围切片信号数据,筛选出落在该区间内的峰值,更新绘图对象的数据即可
效果示例

完整可运行代码
import neurokit2 as nk from sklearn.preprocessing import MinMaxScaler import matplotlib.pyplot as plt from scipy.signal import find_peaks from matplotlib.animation import FuncAnimation # 配置参数 WINDOW_SIZE = 500 # 5秒窗口,对应100Hz采样率 SAMPLING_RATE = 100 # 生成模拟数据、检测峰值 data = nk.ecg_simulate(duration = 50, sampling_rate = SAMPLING_RATE, noise = 0.05, random_state = 1) scaler = MinMaxScaler() scaled_arr = scaler.fit_transform(data.reshape(-1,1)).squeeze() peak_x, peak_info = find_peaks(scaled_arr, height = .66, distance = 60, prominence = .5) peak_y = peak_info['peak_heights'] # 初始化画布 fig, ax = plt.subplots(figsize=(10,4)) # 初始化空绘图对象 line, = ax.plot([], [], lw=1) scatter = ax.scatter([], [], s=20, c='red') # 固定轴范围 ax.set_ylim(scaled_arr.min()-0.05, scaled_arr.max()+0.05) ax.set_xlim(0, WINDOW_SIZE) ax.set_xlabel('窗口内时间点') ax.set_ylabel('归一化信号值') def init(): line.set_data([], []) scatter.set_offsets([]) return line, scatter def update(frame): # 切片当前窗口的信号 window_signal = scaled_arr[frame : frame+WINDOW_SIZE] line.set_data(range(WINDOW_SIZE), window_signal) # 筛选当前窗口内的峰值 mask = (peak_x >= frame) & (peak_x < frame + WINDOW_SIZE) current_peak_x = peak_x[mask] - frame # 转为窗口内相对坐标 current_peak_y = peak_y[mask] scatter.set_offsets(list(zip(current_peak_x, current_peak_y))) return line, scatter # 生成动画 ani = FuncAnimation( fig, update, frames=range(0, len(scaled_arr)-WINDOW_SIZE), init_func=init, interval=20, # 每帧间隔20ms,对应1倍速滑动 blit=True, repeat=False ) plt.show() # 如需保存为视频可取消下方注释 # ani.save('peak_demo.mp4', writer='ffmpeg', fps=50)
内容的提问来源于stack exchange,提问作者fednem
相关产品推荐
相关产品推荐

