You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Matplotlib中实现曲线图与图像子图同步动画的问题

Matplotlib动画:曲线与图像偏移不同步问题解决

问题描述

我用Matplotlib创建了包含曲线图和对应图像的Figure,希望两者同步偏移——让图像的白色区域跟随三条曲线重合的位置(多波长干涉图模拟)。将曲线图的三条曲线逐点复制到图像帧的R、G、B通道后,动画中曲线偏移速度明显快于图像颜色变化,调整图像纵横比、修改image extent等操作都未能解决问题。

原代码

from numpy import *
import matplotlib.pyplot as plt
from matplotlib import animation

npts = 501
wavelength_blue = 0.45
wavelength_green = 0.55
wavelength_red = 0.65
z = 1.5 * linspace(-0.75, 0.75, npts)      ## distance in microns
nframes = 100
maxshift = 0.55     ## in microns of distance
img_height = 100
img = 255 * ones((img_height,npts,3), 'uint8')

(fig,axes) = plt.subplots(2, num='propagation_phase_shifted')
p1 = axes[0].plot([], [], 'b-')
p2 = axes[0].plot([], [], 'g-')
p3 = axes[0].plot([], [], 'r-')
axes[0].set_xlim((-0.8,0.8))
axes[0].set_ylim((-0.1,1.1))
p4 = axes[1].imshow(img, extent=[-0.8,0.8,-0.1,1.1], aspect=1/3)

axes[0].xaxis.set_label_position('top')
axes[0].xaxis.set_ticks_position('top')
axes[0].set_xlabel('z-distance (um)')
axes[0].set_ylabel('wave amplitude')
axes[0].tick_params(axis='x', direction='out')
plt.subplots_adjust(hspace=0.05)

def animate(n):
    shift = (n / (nframes - 1.0)) * maxshift
    phi_red = 2.0 * pi * (z-shift) / wavelength_red
    phi_green = 2.0 * pi * (z-shift) / wavelength_green
    phi_blue = 2.0 * pi * (z-shift) / wavelength_blue

    y_red = 0.5 * (1.0 + cos(phi_red))
    y_green = 0.5 * (1.0 + cos(phi_green))
    y_blue = 0.5 * (1.0 + cos(phi_blue))

    for x in range(img_height):
        img[x,:,0] = uint8(255 * y_red)
        img[x,:,1] = uint8(255 * y_green)
        img[x,:,2] = uint8(255 * y_blue)

    p1[0].set_data(z, y_red)
    p2[0].set_data(z, y_green)
    p3[0].set_data(z, y_blue)
    p4.set_data(img)
    return(p1[0],p2[0],p3[0],p4)

anim = animation.FuncAnimation(fig, animate, frames=nframes, interval=20, blit=True)
FFwriter = animation.FFMpegWriter(fps=30)
anim.save('result.mp4', writer=FFwriter)

plt.show()

问题根源

核心问题是曲线的x轴数据范围与图像的extent x范围不匹配:

  • 曲线使用的x数据z = 1.5 * linspace(-0.75, 0.75, npts),实际范围是-1.125 ~ 1.125
  • 上下坐标轴的xlim和图像extent都设置为-0.8 ~ 0.8
    这导致图像的每一列对应x从-0.8到0.8的均匀分布,而曲线的x点是-1.125到1.125的均匀分布,两者的x轴刻度映射错位,偏移时自然无法同步。

修改后的代码

from numpy import *
import matplotlib.pyplot as plt
from matplotlib import animation

npts = 501
wavelength_blue = 0.45
wavelength_green = 0.55
wavelength_red = 0.65
# 关键改动1:让z的范围与xlim、图像extent的x范围完全一致
z = linspace(-0.8, 0.8, npts)      ## distance in microns
nframes = 100
maxshift = 0.55     ## in microns of distance
img_height = 100
img = 255 * ones((img_height,npts,3), 'uint8')

(fig,axes) = plt.subplots(2, num='propagation_phase_shifted')
p1 = axes[0].plot([], [], 'b-')
p2 = axes[0].plot([], [], 'g-')
p3 = axes[0].plot([], [], 'r-')
axes[0].set_xlim((-0.8,0.8))
axes[0].set_ylim((-0.1,1.1))
# 关键改动2:设置aspect为auto,避免固定纵横比导致的显示扭曲
p4 = axes[1].imshow(img, extent=[-0.8,0.8,-0.1,1.1], aspect='auto')

axes[0].xaxis.set_label_position('top')
axes[0].xaxis.set_ticks_position('top')
axes[0].set_xlabel('z-distance (um)')
axes[0].set_ylabel('wave amplitude')
axes[0].tick_params(axis='x', direction='out')
plt.subplots_adjust(hspace=0.05)

def animate(n):
    shift = (n / (nframes - 1.0)) * maxshift
    phi_red = 2.0 * pi * (z-shift) / wavelength_red
    phi_green = 2.0 * pi * (z-shift) / wavelength_green
    phi_blue = 2.0 * pi * (z-shift) / wavelength_blue

    y_red = 0.5 * (1.0 + cos(phi_red))
    y_green = 0.5 * (1.0 + cos(phi_green))
    y_blue = 0.5 * (1.0 + cos(phi_blue))

    # 关键改动3:用矢量赋值替代循环,提升动画渲染效率
    img[:, :, 0] = uint8(255 * y_red)
    img[:, :, 1] = uint8(255 * y_green)
    img[:, :, 2] = uint8(255 * y_blue)

    p1[0].set_data(z, y_red)
    p2[0].set_data(z, y_green)
    p3[0].set_data(z, y_blue)
    p4.set_data(img)
    return(p1[0],p2[0],p3[0],p4)

anim = animation.FuncAnimation(fig, animate, frames=nframes, interval=20, blit=True)
FFwriter = animation.FFMpegWriter(fps=30)
anim.save('result.mp4', writer=FFwriter)

plt.show()

关键改动说明

  1. 统一x轴范围:将z的生成改为linspace(-0.8, 0.8, npts),让曲线的x数据范围与坐标轴xlim、图像extent的x范围完全一致,确保每个z点对应图像的一列,偏移时完全同步。
  2. 优化图像显示:将图像的aspect设置为auto,避免固定纵横比导致的显示扭曲(也可根据需求设置为对应比例)。
  3. 效率优化:用矢量赋值img[:, :, 0] = ...替代循环,大幅提升动画渲染速度。

内容的提问来源于stack exchange,提问作者nzh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 17:45:37