寻找两个信号之间的差异

4
我有两个信号,我们称它们为'a'和'b'。它们都是几乎相同的信号(从同一输入记录并包含相同的信息),但由于我在两个不同的时间记录了它们,因此'b'被未知量时间偏移。显然,每个信号中都有随机噪声。
目前,我正在使用交叉相关来计算时间偏移,但是我仍然得到了不正确的结果。
这是我用来计算时间偏移的代码:
function [ diff ] = FindDiff( signal1, signal2 )
%FINDDIFF Finds the difference between two signals of equal frequency 
%after an appropritate time shift is applied
%   Calculates the time shift between two signals of equal frequency 
%   using cross correlation, shifts the second signal and subtracts the
%   shifted signal from the first signal. This difference is returned.
length = size(signal1);

if (length ~= size(signal2))
    error('Vectors must be equal size');
end

t = 1:length;
tx = (-length+1):length;
x = xcorr(signal1,signal2);
[mx,ix] = max(x);
lag = abs(tx(ix));
shifted_signal2 = timeshift(signal2,lag);
diff = signal1 - shifted_signal2;

end

function [ shifted ] = timeshift( input_signal, shift_amount )
input_size = size(input_signal);
shifted = (1:input_size)';
for i = 1:input_size
    if i <= shift_amount
        shifted(i) = 0;
    else
        shifted(i) = input_signal(i-shift_amount);
    end
end

end

plot(FindDiff(a,b));

然而,该函数的结果是一个周期波,而不是随机噪声,因此滞后仍然可能不准确。我想发布绘图的图片,但imgur当前无法合作。
除了交叉相关之外,是否有更准确的计算滞后的方法,或者有没有办法改善交叉相关的结果?

实际上,如果您要比较两个相同大小的信号,则xcorr无法正常工作,因为它将从将信号1与仅填充了零(或者可能是最后一个值,但这仍然不是比较两个信号的好方法)的信号2的一部分进行比较。您应该将信号段与较大的信号进行比较,然后确定子信号在较大信号中的位置。此外,您正在覆盖“length”内置函数并且不必要地形成t和tx。 - JustinBlaber
@jucestain 我认为那不正确。我们在交叉相关中看的唯一事情是它的最大值,所以开头的那些零不会有影响。而且当一个信号对自身进行操作时,我知道这些函数能够完美地工作。 - Kyle
你是否尝试过查看整个相关性而不仅仅是它的最大值?如果处理现实世界中的嘈杂信号,有可能您的实时偏移并未产生最大相关性。 - Dedek Mraz
@KyleRogers 阅读有关交叉相关如何工作的内容。它是一个滑动点积。如果您正在比较两个相同大小的向量,您认为它们在开头或结尾将如何进行比较?其中一个向量将被填充。从简要查看xcorr输出,它似乎用零填充了其中一个向量。此外,当您说“开头的那些零不会产生影响”时,相关系数将使用这些值计算,因此它们无疑会产生影响,特别是因为您的实现没有使用归一化。 - JustinBlaber
@jucestain 我的代码实际上完全正确。我认为结果不正确的原因与仪器产生的周期性噪声有关,而不是高斯噪声。 - Kyle
4个回答

7

互相关通常是确定两个信号之间时间滞后的最简单方法。峰值位置指示了两个信号最相似的时间偏移量。

%// Normalize signals to zero mean and unit variance
s1 = (signal1 - mean(signal1)) / std(signal1);
s2 = (signal2 - mean(signal2)) / std(signal2);

%// Compute time lag between signals
c = xcorr(s1, s2);                       %// Cross correlation
lag = mod(find(c == max(c)), length(s2)) %// Find the position of the peak

请注意,这两个信号必须首先被归一化到相同的能量水平,以避免结果产生偏差。
顺便说一下,不要使用“diff”作为变量名。在MATLAB中已经有一个同名的内置函数

我如何从延迟中判断信号2是否可以在信号1中找到? - Z T
1
@ZoltanSzabo,决定你所询问的内容的是互相关的峰值而不是“滞后”。峰值表示两个信号最相似的位置,或者换句话说,一个信号和另一个类似信号之间的时间偏移量。缺少这样的峰值意味着信号不相似。 - Eitan T
谢谢,我可以通过相关性的最大索引获得峰值。你知道如何获取一些百分比来显示两个信号的相似程度吗?例如,我有两个几乎相似的信号。第一个信号的长度约为130kbyte,但算法在125kbyte左右找到了峰值,所以看起来它已经找到了匹配,但我知道这些信号并不真正相似。因此,我需要一些百分比。 - Z T
1
@ZoltanSzabo,有许多方法可以测量信号相似性。其中之一是比较频率成分...我建议您查看官方MATLAB文档网站上的此示例 - Eitan T

3
现在Matlab有两个函数:
一个称为finddelay 另一个称为alignsignals,我相信它可以实现你想要的。

考虑到新函数的存在,这应该被认为是解决此问题的最佳方案。 - Kyle

1

corr函数计算向量(v1, v2)的点积。如果它不能很好地处理您的信号,建议尝试最小化差值的平方和(即abs(v1 - v2))。

 signal = sin(1:100);
 signal1 = [zeros(1, 10) signal];
 signal2 = [signal zeros(1, 10)];

 for i = 1:length(signal1)
     signal1shifted = [signal1 zeros(1, i)];
     signal2shifted = [zeros(1, i) signal2];
     d2(i) = sum((signal1shifted - signal2shifted).^2);
 end

 [fval lag2] = min(d2);

 lag2

它的计算复杂度比交叉计算更差,但可以通过使用FFT加速。据我所知,欧几里得距离无法做到这一点。

更新:删除了关于周期信号交叉相关的错误想法。


0

你可以尝试在频域中进行匹配滤波

function [corr_output] = pc_corr_processor (target_signal, ref_signal)
L = length(ref_signal);
N = length(target_signal);

matched_filter = flipud(ref_signal')';
matched_filter_Res = fft(matched_filter,N);
corr_fft = matched_filter_Res.*fft(target_signal);
corr_out = abs(ifft(corr_fft));

匹配滤波器的最大相关输出值的峰值索引应该给出滞后量。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接