Python使用互相关算法定位信号序列中模式序列位置的问题求助
问题描述
我正在解决一个互相关应用问题,需要在信号序列中定位指定模式序列的匹配位置。此前我已得到正确求解结果,但在优化代码时未保存之前的正确实现,现在运行互相关函数无法得到正确结果,多次重启内核也未解决。
相关数据文件链接:
当前测试代码:
import numpy as np import matplotlib.pyplot as plt patron = np.loadtxt('patron.txt', delimiter=',', skiprows=1) senal = np.loadtxt('señal.txt', delimiter=',', skiprows=1) Fs=100 ts = np.arange(0,len(senal)) plt.figure(figsize=(20,8)) plt.subplot(3,1,1) plt.plot(ts,patron) plt.subplot(3,1,2) plt.plot(ts,senal) corr = np.correlate(senal,patron,"same") print(np.where(corr == np.amax(corr))) #该输出应为相关值最大的位置,即两个序列匹配度最高的位置 plt.subplot(3,1,3) plt.plot(ts,corr, 'r')
我可以确定此前的结果是正确的:当时得到的最大相关值对应索引为799,将信号序列平移799位后绘制的结果匹配度很高,使用的代码如下:
np.roll(senal,799) plt.plot(senal)
得到的效果如下图所示,最大相关值对应索引799的结果非常直观:
烦请帮忙排查问题,为什么当前使用np.correlate无法得到索引为799的正确结果?
问题排查与解决
问题主要出在三个点:
互相关模式参数选择错误
你当前使用mode="same"参数计算互相关,该模式会将完整互相关结果居中裁剪为和输入长序列等长,得到的索引值并非直接对应的平移偏移量。如果要计算完整的线性互相关,应该使用mode="full"参数,此时最大相关值对应的索引k,实际的平移起始位置为k - len(patron) + 1。线性互相关与周期互相关的逻辑差异
你之前使用np.roll()做的是周期平移,对应的是周期互相关的计算场景,而numpy.correlate默认计算的是线性互相关,二者逻辑存在本质差异:
- 线性互相关默认信号两端外的数值为0,计算边缘位置的相关值时会存在截断误差
- 周期互相关假设信号是周期重复的,和
np.roll()的平移逻辑完全匹配
如果要得到和你之前测试一致的周期互相关结果,可使用FFT快速计算,代码如下:
# 周期互相关计算 fft_senal = np.fft.fft(senal) fft_patron = np.fft.fft(patron) circular_corr = np.fft.ifft(fft_senal * np.conj(fft_patron)).real # 输出最大相关值位置,即可得到799 print(np.argmax(circular_corr))
- 原有验证代码存在笔误
你贴出的验证代码中np.roll(senal,799)没有赋值给变量,直接绘制senal依然是原始信号,正确写法应该是:
shifted_senal = np.roll(senal, 799) plt.plot(shifted_senal)
内容的提问来源于stack exchange,提问作者Gustavo Henrique Foss Neves
相关产品推荐
相关产品推荐

