I am in the process of identifying a time shift between two sinusoidal signals in Python. A little research on this has revealed that correlation between the two input signals can solve the problem. However, when working with correlations, I do not understand the result of np.correlate
and scipy.signal.correlate()
as the result is different from the a priori result.
我正在用Python语言识别两个正弦信号之间的时移。这方面的一些研究表明,两个输入信号之间的相关性可以解决这个问题。但是,在处理关联时,我不理解np.correlate和scipy.signal.correlate()的结果,因为该结果与先前的结果不同。
Let
让我们
t = np.arange(0, 10, 0.01)
sig1 = np.sin(t)
sig2 = np.cos(t)
I'd expect pi/2 = 1.571 difference between both signals. However, the following code determines |1.490|.
我预计两个信号之间的pi/2=1.571。但是,以下代码确定|1.490|。
import scipy
import numpy as np
t = np.arange(0, 10, 0.01)
sig1 = np.sin(t)
sig2 = np.cos(t)
# Scipy
#x = scipy.signal.correlate(sig1, sig2, mode='full')
#tx = signal.correlation_lags(len(sig1), len(sig2))
# Numpy
x = np.correlate(sig1, sig2, 'full')
tx = np.linspace(-t[-1], t[-1], 2*len(t)-1)
ndx = np.argmax(np.abs(x))
print(tx[ndx])
>>> -1.4900000000000002
Do I miss something with the modes of the correlation?
我是否遗漏了相关模式中的某些内容?
However, the cosine similarity or least squares optimization gives the correct result. Also the simple comparison of the extrema of both signals works correctly.
但是,余弦相似度或最小二乘优化给出了正确的结果。此外,两个信号的极值的简单比较也是正确的。
Full code including the plot:
包括剧情在内的完整代码:
import scipy
import numpy as np
import matplotlib.pyplot as plt
fig, ax = plt.subplots(3, figsize=(8,6))
t = np.arange(0, 10, 0.01)
sig1 = np.sin(t)
sig2 = np.cos(t)
# Plot 1: Both input signals
ax[0].plot(t, sig1, label='sig1')
ax[0].plot(t, sig2, label='sig2')
ax[0].legend()
ax[0].set_xlabel('time in s')
## Apply correlation between the two given signals
# Scipy
#x = scipy.signal.correlate(sig1, sig2, mode='full')
#tx = signal.correlation_lags(len(sig1), len(sig2))
# Numpy
x = np.correlate(sig1, sig2, 'full')
tx = np.linspace(-t[-1], t[-1], 2*len(t)-1)
# Plot 2: Correlation between two input signals
ax[1].plot(tx, x, label='correlation', c='k')
ndx = np.argmax(np.abs(x))
ax[1].plot(tx[ndx], x[ndx], 'rx')
ax[1].legend()
# Plot 3: Both input signals, sig2 on corrected time values
ax[2].plot(t, sig1, label='sig1')
t_corr = t - tx[ndx] # Correct the time
ax[2].plot(t_corr, sig2, label='sig2')
ax[2].set_xlabel(r'Shift: %.5f' %(tx[ndx]))
ax[2].legend()
print(tx[ndx]) # Display the shift
更多回答
Your code is correct, the problem is the correlation. This method assumes that you have an infinite signal. Then, the shorter is the signal, the larger will be the error.
你的代码是正确的,问题是相关性。此方法假定您有一个无限大的信号。那么,信号越短,误差就越大。
I have executed your code with a longer t
vector and the result has been |1.569999999999709|, which is more similar to pi/2 = 1.571.
我用更长的t向量执行了您的代码,结果是|1.569999999999709|,这更类似于pi/2=1.571。
t = np.arange(0, 10000, 0.01)
If you are sure that the signals are sinusoidal, I would recommend you to use another method of the ones that you have cited.
如果你确定信号是正弦的,我建议你使用你所引用的另一种方法。
更多回答
Thank you for the hint. This solved the issue somehow. But as you said - I'll stick to another method.
谢谢你的提示。这在某种程度上解决了问题。但就像你说的--我会坚持用另一种方法。
我是一名优秀的程序员,十分优秀!