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

如何用Python稳健提取双脉冲信号中各脉冲的时间偏移?

解决多脉冲信号的分组时移提取问题

我明白你遇到的困扰了——当信号里包含多组独立移位的脉冲时,常规互相关会因为多个脉冲的叠加相关峰混在一起,根本没法精准提取每组脉冲的时移量。这里有个非常直接的解决方案:针对每组脉冲单独做模板匹配(单脉冲互相关),毕竟你已经知道每组脉冲的原始形状(比如示例里的5Hz和8Hz高斯脉冲),完全可以利用这一点来分离信号。

核心思路

  • 先保留原始的脉冲模板(不要做移位、填充操作),这是匹配的关键参考
  • 对每个目标信号,分别用单个脉冲模板做互相关,找到峰值对应的位置,就是该脉冲在信号中的起始时间点
  • 对应脉冲的时间位置差,就是这组脉冲的时移量

代码实现(基于你的测试代码修改)

import numpy as np
import matplotlib.pyplot as plt
from scipy import signal

N = 200  # 原始未移位脉冲的点数
N_pad = 500  # 最终信号总点数
t = np.linspace(-1, 1, N)  # 原始脉冲的时间向量
dt = t[1]-t[0]  # 时间步长
Fs = 1.0/dt  # 采样频率

# 保留原始脉冲作为匹配模板!这一步绝对不能移位或填充
pulse1_template = signal.gausspulse(t, fc=5)  # 5Hz高斯脉冲模板
pulse2_template = signal.gausspulse(t, fc=8)  # 8Hz高斯脉冲模板

# --- 生成信号1 ---
pulse1_shifted = np.concatenate((pulse1_template, np.zeros(50)), axis=0)
pulse2_shifted = np.concatenate((pulse2_template, np.zeros(100)), axis=0)
pulse1_shifted_padded = np.concatenate((np.zeros(N_pad - len(pulse1_shifted)), pulse1_shifted), axis=0)
pulse2_shifted_padded = np.concatenate((np.zeros(N_pad - len(pulse2_shifted)), pulse2_shifted), axis=0)
sig1 = pulse1_shifted_padded + pulse2_shifted_padded

# --- 生成信号2 ---
pulse1_shifted = np.concatenate((pulse1_template, np.zeros(60)), axis=0)
pulse2_shifted = np.concatenate((pulse2_template, np.zeros(150)), axis=0)
pulse1_shifted_padded = np.concatenate((np.zeros(N_pad - len(pulse1_shifted)), pulse1_shifted), axis=0)
pulse2_shifted_padded = np.concatenate((np.zeros(N_pad - len(pulse2_shifted)), pulse2_shifted), axis=0)
sig2 = pulse1_shifted_padded + pulse2_shifted_padded

# --- 定义模板匹配函数,提取脉冲位置 ---
def find_pulse_position(signal, template, Fs, dt):
    # 计算信号与模板的互相关(valid模式避免边缘无效值)
    corr = signal.correlate(signal, template, mode='valid')
    # 找到互相关峰值对应的索引
    peak_idx = np.argmax(corr)
    # 转换为实际时间位置(要对齐模板的中心,所以加上模板半长的时间)
    pulse_time = peak_idx / Fs + (len(template)/2)*dt
    return pulse_time, corr

# 提取信号1中两个脉冲的位置
pulse1_time_sig1, _ = find_pulse_position(sig1, pulse1_template, Fs, dt)
pulse2_time_sig1, _ = find_pulse_position(sig1, pulse2_template, Fs, dt)

# 提取信号2中两个脉冲的位置
pulse1_time_sig2, _ = find_pulse_position(sig2, pulse1_template, Fs, dt)
pulse2_time_sig2, _ = find_pulse_position(sig2, pulse2_template, Fs, dt)

# --- 计算每组脉冲的时移 ---
time_shift_pulse1 = pulse1_time_sig2 - pulse1_time_sig1
time_shift_pulse2 = pulse2_time_sig2 - pulse2_time_sig1

print(f"5Hz脉冲的时移量:{time_shift_pulse1:.4f} s")
print(f"8Hz脉冲的时移量:{time_shift_pulse2:.4f} s")

# --- 可视化验证 ---
t_full = np.arange(N_pad) * dt

plt.figure(figsize=(12, 8))

# 绘制原始信号及脉冲位置标记
plt.subplot(2,2,1)
plt.plot(t_full, sig1, label="Signal 1")
plt.plot(t_full, sig2, label="Signal 2")
plt.scatter([pulse1_time_sig1, pulse2_time_sig1], 
            [sig1[int(pulse1_time_sig1/dt)], sig1[int(pulse2_time_sig1/dt)]], 
            color='red', s=50, label="Signal 1 脉冲位置")
plt.scatter([pulse1_time_sig2, pulse2_time_sig2], 
            [sig2[int(pulse1_time_sig2/dt)], sig2[int(pulse2_time_sig2/dt)]], 
            color='green', s=50, label="Signal 2 脉冲位置")
plt.legend()
plt.xlabel("Time (s)")
plt.ylabel("Amplitude")
plt.title("信号及脉冲位置标记")

# 5Hz模板与Signal 1的互相关结果
plt.subplot(2,2,2)
corr1_sig1 = signal.correlate(sig1, pulse1_template, mode='valid')
plt.plot(np.arange(len(corr1_sig1))/Fs, corr1_sig1)
plt.axvline(pulse1_time_sig1 - (len(pulse1_template)/2)*dt, color='red', linestyle='--', label="峰值位置")
plt.legend()
plt.xlabel("Time (s)")
plt.ylabel("Cross Correlation")
plt.title("5Hz模板与Signal 1的互相关")

# 8Hz模板与Signal 1的互相关结果
plt.subplot(2,2,3)
corr2_sig1 = signal.correlate(sig1, pulse2_template, mode='valid')
plt.plot(np.arange(len(corr2_sig1))/Fs, corr2_sig1)
plt.axvline(pulse2_time_sig1 - (len(pulse2_template)/2)*dt, color='red', linestyle='--', label="峰值位置")
plt.legend()
plt.xlabel("Time (s)")
plt.ylabel("Cross Correlation")
plt.title("8Hz模板与Signal 1的互相关")

plt.tight_layout()
plt.show()

为什么这个方法能解决问题?

常规互相关是把整个信号作为整体计算,所以会同时出现多组脉冲的相关峰,根本没法区分哪组对应哪组。而针对单个脉冲模板做匹配时,互相关的峰值只会对应信号中同形状的脉冲位置——因为两组脉冲频率不同,它们之间的互相关值极低,完全不会干扰彼此的匹配结果,这样就能精准提取每组脉冲的位置,进而计算出准确的时移量。

扩展场景应对

如果你的脉冲形状未知,但确定是两组不同的脉冲,可以先通过峰值检测提取信号中的所有脉冲位置,再根据脉冲的特征(比如宽度、幅度)分组,最后计算每组的位置差;或者使用**独立成分分析(ICA)**将混合信号分解为单个脉冲的分量,再做互相关分析。

内容的提问来源于stack exchange,提问作者A. Bot

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:19:20