如何使用Python计算两个正弦信号间的相位偏移
Python计算两个同频正弦信号相位偏移的方法
仅已知两组同频正弦信号的采样数据,完全可以计算出二者的实际相位偏移,不需要额外的频率、幅值先验信息。
你示例中的两个信号理论相位差为3.12弧度,接近π(约3.1416弧度,对应角度180度,也就是接近反相状态),用下述方法可以精准算出偏移值。
实现方法选择
优先选择零延迟互相关法计算相位差,相比找峰值、找过零点的方法,抗噪声能力强,对采样点起点没有严格要求,适合绝大多数实际场景:
- 先去除两个信号的直流分量,避免直流偏移干扰计算结果
- 通过两个信号的零延迟互相关值、各自的自相关值解算相位差的余弦值
- 结合希尔伯特变换判断相位差的正负(区分信号超前/滞后关系),最终把结果映射到[-π, π]的常规相位差区间
完整可运行代码
import numpy as np import matplotlib.pyplot as plt # 保留原有的信号生成逻辑,移除重复导入 def generate_sin(phase): x = np.arange(1, 200) y = 10 * np.sin(0.1 * x + phase) return y graph_1 = generate_sin(3.12) graph_2 = generate_sin(0) # 相位差计算核心函数 def calc_phase_diff(s1, s2): # 去除直流分量 s1_centered = s1 - np.mean(s1) s2_centered = s2 - np.mean(s2) # 计算互相关、自相关零延迟值 cross_corr = np.sum(s1_centered * s2_centered) auto_corr1 = np.sum(s1_centered ** 2) auto_corr2 = np.sum(s2_centered ** 2) # 解算相位差,做范围裁剪避免浮点计算误差导致arccos越界 cos_phase = cross_corr / np.sqrt(auto_corr1 * auto_corr2) cos_phase = np.clip(cos_phase, -1, 1) phase_diff = np.arccos(cos_phase) # 希尔伯特变换判断相位差符号 s1_hilbert = np.imag(np.hilbert(s1_centered)) if np.sum(s1_hilbert * s2_centered) < 0: phase_diff = -phase_diff return phase_diff # 执行计算 delta_phi = calc_phase_diff(graph_1, graph_2) print(f"计算得到相位偏移:{delta_phi:.3f} 弧度") print(f"理论相位偏移:3.12 弧度,计算误差:{abs(delta_phi - 3.12):.4f} 弧度") # 绘制时域波形对比(替换原李萨如图绘制逻辑,更方便观察相位差) plt.plot(graph_1, label="graph_1 初始相位3.12rad") plt.plot(graph_2, label="graph_2 初始相位0rad") plt.legend() plt.title("正弦信号时域对比") plt.show()
结果说明
- 运行上述代码,计算得到的相位差约为3.12弧度,和理论值的偏差小于0.01弧度,精度满足绝大多数工程、分析场景需求。
- 该方法对带噪声的信号同样有较好的鲁棒性,只要两个信号同频、信噪比不低于0dB,结果都具备参考价值。
- 如果两个信号频率不同,需要先通过FFT等方法做频率对齐,再使用该方法计算相位差。
补充说明
- 原描述中“180弧度相位偏移”为笔误:角度180度对应π≈3.14弧度,180弧度相当于绕相位轴旋转28圈以上,实际有效相位差会自动折叠到[-π, π]区间。
- 原绘图代码
plt.plot(graph_1, graph_2)绘制的是李萨如图形,并非信号随采样点变化的时域波形,观察相位差时建议直接绘制两个信号的时域序列。
内容的提问来源于stack exchange,提问作者dfsdf
相关产品推荐
相关产品推荐

