[英]Find time shift of two signals using cross correlation
I have two signals which are related to each other and have been captured by two different measurement devices simultaneously.我有两个相互关联的信号,并且同时被两个不同的测量设备捕获。 Since the two measurements are not time synchronized there is a small time delay between them which I want to calculate.由于这两个测量值不是时间同步的,因此我想计算它们之间的一小段时间延迟。 Additionally, I need to know which signal is the leading one.此外,我需要知道哪个信号是领先的。
The following can be assumed:可以假设如下:
I though of using-cross correlation for that purpose.我想为此目的使用互相关。 Any suggestions how to implement that in Python are very appreciated.非常感谢如何在 Python 中实现该功能的任何建议。
Please let me know if I should provide more information in order to find the most suitable algorithmn.请让我知道我是否应该提供更多信息以找到最合适的算法。
A popular approach : timeshift is the lag corresponding to the maximum cross-correlation coefficient. 一种流行的方法:时移是对应于最大互相关系数的滞后。 Here is how it works with an example:以下是它如何与示例一起使用:
import matplotlib.pyplot as plt
from scipy import signal
import numpy as np
def lag_finder(y1, y2, sr):
n = len(y1)
corr = signal.correlate(y2, y1, mode='same') / np.sqrt(signal.correlate(y1, y1, mode='same')[int(n/2)] * signal.correlate(y2, y2, mode='same')[int(n/2)])
delay_arr = np.linspace(-0.5*n/sr, 0.5*n/sr, n)
delay = delay_arr[np.argmax(corr)]
print('y2 is ' + str(delay) + ' behind y1')
plt.figure()
plt.plot(delay_arr, corr)
plt.title('Lag: ' + str(np.round(delay, 3)) + ' s')
plt.xlabel('Lag')
plt.ylabel('Correlation coeff')
plt.show()
# Sine sample with some noise and copy to y1 and y2 with a 1-second lag
sr = 1024
y = np.linspace(0, 2*np.pi, sr)
y = np.tile(np.sin(y), 5)
y += np.random.normal(0, 5, y.shape)
y1 = y[sr:4*sr]
y2 = y[:3*sr]
lag_finder(y1, y2, sr)
In the case of noisy signals, it is common to apply band-pass filters first.在噪声信号的情况下,通常首先应用带通滤波器。 In the case of harmonic noise, they can be removed by identifying and removing frequency spikes present in the frequency spectrum.在谐波噪声的情况下,可以通过识别和消除频谱中存在的频率尖峰来消除它们。
Numpy 具有适合您需求的函数correlate
: https : //docs.scipy.org/doc/numpy/reference/generated/numpy.correlate.html
To complement Reveille's answer above (I reproduce his algorithm), I would like to point out some ideas for preprocessing the input signals.为了补充 Reveille 上面的回答(我复制了他的算法),我想指出一些预处理输入信号的想法。 Since there seems to be no fit-for-all (duration in periods, resolution, offset, noise, signal type,...) you may play with it.由于似乎没有适合所有人(周期中的持续时间、分辨率、偏移量、噪声、信号类型……),您可以使用它。 In my example the application of a window function improves the detected phase shift (within resolution of the discretization).在我的示例中,应用 window function 改进了检测到的相移(在离散化的分辨率内)。
import numpy as np
from scipy import signal
import matplotlib.pyplot as plt
r2d = 180.0/np.pi # conversion factor RAD-to-DEG
delta_phi_true = 50.0/r2d
def detect_phase_shift(t, x, y):
'''detect phase shift between two signals from cross correlation maximum'''
N = len(t)
L = t[-1] - t[0]
cc = signal.correlate(x, y, mode="same")
i_max = np.argmax(cc)
phi_shift = np.linspace(-0.5*L, 0.5*L , N)
delta_phi = phi_shift[i_max]
print("true delta phi = {} DEG".format(delta_phi_true*r2d))
print("detected delta phi = {} DEG".format(delta_phi*r2d))
print("error = {} DEG resolution for comparison dphi = {} DEG".format((delta_phi-delta_phi_true)*r2d, dphi*r2d))
print("ratio = {}".format(delta_phi/delta_phi_true))
return delta_phi
L = np.pi*10+2 # interval length [RAD], for generality not multiple period
N = 1001 # interval division, odd number is better (center is integer)
noise_intensity = 0.0
X = 0.5 # amplitude of first signal..
Y = 2.0 # ..and second signal
phi = np.linspace(0, L, N)
dphi = phi[1] - phi[0]
'''generate signals'''
nx = noise_intensity*np.random.randn(N)*np.sqrt(dphi)
ny = noise_intensity*np.random.randn(N)*np.sqrt(dphi)
x_raw = X*np.sin(phi) + nx
y_raw = Y*np.sin(phi+delta_phi_true) + ny
'''preprocessing signals'''
x = x_raw.copy()
y = y_raw.copy()
window = signal.windows.hann(N) # Hanning window
#x -= np.mean(x) # zero mean
#y -= np.mean(y) # zero mean
#x /= np.std(x) # scale
#y /= np.std(y) # scale
x *= window # reduce effect of finite length
y *= window # reduce effect of finite length
print(" -- using raw data -- ")
delta_phi_raw = detect_phase_shift(phi, x_raw, y_raw)
print(" -- using preprocessed data -- ")
delta_phi_preprocessed = detect_phase_shift(phi, x, y)
Without noise (to be deterministic) the output is没有噪声(确定性),output 是
-- using raw data --
true delta phi = 50.0 DEG
detected delta phi = 47.864788975654 DEG
...
-- using preprocessed data --
true delta phi = 50.0 DEG
detected delta phi = 49.77938053468019 DEG
...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.