ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

MATLAB xcorr无偏估计:信号时延估计与互相关分析实践

2026/8/2 9:51:40 拓冰建站 浏览量
MATLAB xcorr无偏估计:信号时延估计与互相关分析实践

1. 从一次信号匹配的困惑说起

最近在做一个传感器数据对齐的项目,遇到了一个典型问题:两个传感器采集同一物理事件,但由于启动时间、时钟漂移和传输延迟,它们的时间序列在时间轴上对不齐。我需要找到一个精确的时延量,把两个信号“拉”到同一个时间基准上。这听起来像是信号处理里的经典问题——互相关分析。在MATLAB里,xcorr函数几乎是做这件事的首选工具。但当我第一次兴冲冲地使用默认参数xcorr(signal1, signal2)并拿到结果时,却陷入了更深的困惑:计算出的互相关系数序列,其幅值随着时延的增大而明显衰减,这让我对时延估计的置信度产生了怀疑。难道大时延下的相关性真的更弱?还是我的用法有问题?

经过一番折腾,我才意识到问题出在了一个关键但常被忽略的参数上:‘unbiased’(无偏估计)。默认情况下,xcorr计算的是有偏估计,而这个“偏”正是导致幅值衰减的元凶。这篇文章,我就来彻底拆解一下xcorr函数,特别是这个“无偏估计”参数到底在干什么,为什么它在很多实际场景下(比如我的时延估计)是更合理的选择。我们会从原理、公式、到MATLAB代码实操和结果对比,一步步把这件事说清楚。无论你是正在处理通信系统的同步问题,还是在做振动分析、声源定位、或像我一样的多传感器数据融合,理解xcorr和无偏估计,都能让你对结果更有把握。

2. 互相关分析:它到底是什么,以及我们为何需要它

在深入代码之前,我们必须先建立清晰的物理概念。互相关函数,描述的是两个信号在不同相对时移下的相似程度。你可以把它想象成一个“滑动内积”的过程:固定一个信号,让另一个信号在时间轴上滑动,在每个滑动位置上,计算两个信号重叠部分对应点的乘积之和。

2.1 离散互相关的数学定义

对于两个长度为N的有限长离散信号序列 (x[n]) 和 (y[n]),它们的互相关序列 (R_{xy}[m]) 定义为:

[ R_{xy}[m] = \sum_{n=-\infty}^{\infty} x[n] \cdot y^*[n-m] ]

对于实信号(我们大部分情况遇到的),共轭符号*可以忽略。这里的 (m) 就是时延(或滞后)。注意下标顺序:(R_{xy}[m]) 表示将 (y[n]) 相对于 (x[n]) 延迟 (m) 个样本点。当 (m>0) 时,(y) 在时间上落后于 (x);当 (m<0) 时,(y) 领先于 (x)。

这个定义是理论上的,对于有限长信号,求和范围实际上是重叠的部分。这就引出了核心问题:在滑动过程中,两个信号的重叠长度是变化的。当完全对齐时,重叠长度为N;当滑动到一端时,可能只重叠了1个点。这个变化的重叠长度,正是理解有偏与无偏估计的关键。

2.2 互相关能解决的实际问题

互相关分析绝不是一个纯粹的数学游戏,它在工程和科研中应用极广:

  • 时延估计(Time Delay Estimation, TDE):这是我遇到的核心问题。通过寻找互相关函数峰值的位置 (m_{peak}),可以直接得到信号 (y) 相对于信号 (x) 的时延。这在雷达测距、声源定位(如麦克风阵列)、地质勘探中至关重要。
  • 信号检测与模板匹配:在嘈杂的背景中,判断是否包含某个已知的特定信号模式(例如,心电图中的异常波形、通信中的特定导频序列)。将接收信号与模板信号做互相关,相关峰的出现和高度即指示了模板的存在和强度。
  • 系统辨识:通过计算系统输入信号与输出信号的互相关,并结合输入的自相关,可以估计系统的冲激响应。
  • 速度测量(多普勒):比较发射信号与回波信号的互相关,峰值位置的偏移量对应了时延(距离),而峰值本身的展宽或子结构则可能包含多普勒频移信息。

理解这些应用场景,能让我们在选用xcorr时,更清楚自己到底想从数据中获取什么信息,从而做出正确的参数选择。

3. MATLAB xcorr函数详解:默认行为与“有偏”陷阱

让我们进入MATLAB的世界。xcorr函数的基本语法是[r, lags] = xcorr(x, y),其中xy是输入序列,r是计算出的互相关序列,lags是对应的时延向量。

3.1 默认计算方式:有偏估计

默认情况下,xcorr计算的是有偏的样本互相关估计。对于长度为N的有限长信号,其计算公式为:

[ R_{xy}^{biased}[m] = \frac{1}{N} \sum_{n} x[n] y[n-m] ]

注意,这里的分母是常数 (N),即信号的总长度,而不是当前时延 (m) 下实际参与计算的重叠样本数。这就是“有偏”的根源。

为了更直观,我们构造一个简单的例子。假设有两个短序列,方便我们手动验证。

% 示例1:理解有偏估计 x = [1, 2, 3]; y = [0, 1, 2]; % y可以看作是x的某种变形 [r_biased, lags] = xcorr(x, y); % 默认有偏 disp('有偏估计结果:'); disp(table(lags‘, r_biased‘, ‘VariableNames‘, {‘时延‘, ‘互相关系数‘}));

运行后,你会得到从lags = -2lags = 2的5个相关系数值。让我们手动计算lags = -1这个点(即y领先x一个样本):此时,x的索引范围是n=1到3,y的索引范围是n-(-1)=n+1,即n=1时y取索引2,n=2时y取索引3,n=3时y取索引4(超出长度,补零)。所以重叠的有效部分是x(1:2)和y(2:3)。 手动计算:( (11 + 22) / 3 = (1+4)/3 = 5/3 \approx 1.6667)。MATLAB输出结果应该与此一致。

关键问题出现了:在lags = -1时,实际只有2个样本点发生了有效乘积求和,但分母却用了总长度3。这意味着,在时延绝对值较大的区域(信号重叠部分少),每个数据点被赋予的权重(1/N)与零时延处是相同的,但参与求和的点数却少得多。这会导致估计出的相关系数向零衰减

这种衰减不是信号本身的特性,而是由估计方法引入的数学假象。在有偏估计中,(E[R_{xy}^{biased}[m]] = (N-|m|)/N * R_{xy}^{true}[m]),其中 (R_{xy}^{true}[m]) 是理论真值。期望值等于真值乘以一个三角窗 ((N-|m|)/N)。这就是为什么互相关序列图看起来像一个三角形包络,峰值在零时延,两端衰减到零。

3.2 有偏估计带来的误导

这种衰减会严重干扰我们的判断:

  1. 时延估计置信度下降:如果你要寻找的互相关峰不在零时延附近,而是在较大时延处,那么该峰的幅值会因为这种“三角窗”效应而被严重压低。你可能会怀疑这个弱峰是否真的是有效信号,而不是噪声。
  2. 幅度信息失真:在需要根据相关峰高度进行量化分析(比如信号强度估计)的场景下,有偏估计给出的幅度是失真的,不能直接用于比较不同时延下的相关强度。
  3. 频谱分析的基础不牢:根据维纳-辛钦定理,功率谱密度是自相关函数的傅里叶变换。如果使用有偏的自相关估计,其傅里叶变换会产生泄漏,导致功率谱估计出现偏差。

因此,在大多数寻求真实相关性度量或需要进行后续频谱分析的场合,默认的有偏估计并不是最佳选择。

4. 无偏估计的引入:为何以及如何修正

为了解决有偏估计的衰减问题,我们需要一个在统计意义上更优的估计量——无偏估计。

4.1 无偏估计的数学原理

无偏估计的核心思想很直观:在每一个时延 (m) 上,用实际参与计算的重叠样本数 (N-|m|) 作为归一化分母。其公式为:

[ R_{xy}^{unbiased}[m] = \frac{1}{N - |m|} \sum_{n} x[n] y[n-m] ]

这样,每个时延下的相关系数,都是基于该时延下所有有效数据点的平均相关性。从统计上讲,这个估计量的期望值等于理论真值,即 (E[R_{xy}^{unbiased}[m]] = R_{xy}^{true}[m]),因此被称为“无偏”。

在MATLAB中,我们通过添加参数‘unbiased’来调用它:

[r_unbiased, lags] = xcorr(x, y, ‘unbiased‘);

4.2 有偏 vs. 无偏:一个直观的对比实验

让我们用一组更接近真实场景的信号来对比。生成一个包含两个不同频率正弦波的信号作为源,然后创建它的一个延迟且有噪声的版本。

% 示例2:有偏与无偏估计的对比 Fs = 1000; % 采样率 1kHz t = 0:1/Fs:1-1/Fs; % 1秒时间向量 f1 = 50; % 50Hz f2 = 120; % 120Hz x = sin(2*pi*f1*t) + 0.5*sin(2*pi*f2*t); % 源信号 delay_samples = 100; % 设定100个样本的延迟 y = [zeros(1, delay_samples), x(1:end-delay_samples)]; % 产生延迟信号 y = y + 0.5*randn(size(y)); % 加入高斯白噪声 % 计算有偏和无偏互相关 [r_biased, lags] = xcorr(x, y); [r_unbiased, ~] = xcorr(x, y, ‘unbiased‘); % 找到峰值位置 [~, idx_biased] = max(abs(r_biased)); [~, idx_unbiased] = max(abs(r_unbiased)); estimated_delay_biased = lags(idx_biased); estimated_delay_unbiased = lags(idx_unbiased); fprintf(‘真实延迟: %d 个样本\n‘, delay_samples); fprintf(‘有偏估计延迟: %d\n‘, estimated_delay_biased); fprintf(‘无偏估计延迟: %d\n‘, estimated_delay_unbiased); % 绘制对比图 figure(‘Position‘, [100 100 1200 500]); subplot(1,2,1); plot(lags, r_biased, ‘b-‘, ‘LineWidth‘, 1.5); hold on; plot(lags, r_unbiased, ‘r--‘, ‘LineWidth‘, 1.5); xlabel(‘时延(样本数)‘); ylabel(‘互相关系数‘); title(‘互相关函数对比‘); legend(‘有偏估计‘, ‘无偏估计‘, ‘Location‘, ‘best‘); grid on; xlim([-150, 150]); % 聚焦在延迟附近 subplot(1,2,2); zoom_lags = lags(lags>=50 & lags<=150); zoom_bias = r_biased(lags>=50 & lags<=150); zoom_unbias = r_unbiased(lags>=50 & lags<=150); plot(zoom_lags, zoom_bias, ‘b-o‘, ‘MarkerSize‘, 4); hold on; plot(zoom_lags, zoom_unbias, ‘r--s‘, ‘MarkerSize‘, 4); xlabel(‘时延(样本数)‘); ylabel(‘互相关系数‘); title(‘峰值区域放大图‘); legend(‘有偏估计‘, ‘无偏估计‘, ‘Location‘, ‘best‘); grid on;

运行这段代码,你会清晰地看到两种估计的差异:

  1. 整体形状:有偏估计(蓝色实线)呈现明显的三角形包络,两端衰减至零。无偏估计(红色虚线)在远离中心区域的幅值保持得更好,没有这种强制性的衰减。
  2. 峰值区域:在放大图中,两者峰值位置(时延估计)基本一致,都能正确找到100个样本的延迟。但峰值高度不同。无偏估计的峰值更高、更尖锐。这是因为在时延m=100处,重叠样本数为N-100,无偏估计用这个数做归一化,更好地保留了该时延下真实的平均相关性强度。而有偏估计用总长N归一化,相当于把峰值“稀释”了。
  3. 大时延处的波动:注意观察无偏估计曲线在两端(时延绝对值接近N时),波动会变得非常剧烈。这是因为分母 (N-|m|) 变得很小,甚至为1,此时单个噪声样本的波动会被极大地放大,导致估计方差急剧增大。这是无偏估计的一个固有缺点:它以增加方差为代价,换取了估计的无偏性。

4.3 无偏估计的适用场景与权衡

那么,我们什么时候应该用无偏估计呢?

强烈推荐使用无偏估计的场景:

  • 时延估计(TDE):特别是当预期时延较大,不在零附近时。无偏估计能避免三角窗衰减对峰值幅度的压制,让你更容易在噪声中识别出真实的相关峰。在上面的例子中,虽然两者都能找到峰值位置,但在低信噪比条件下,有偏估计的弱峰可能被噪声淹没,而无偏估计的强峰则更鲁棒。
  • 幅度敏感的定量分析:当你需要比较不同时延下的相关强度,或者需要将相关值作为一个绝对量进行阈值判断时,无偏估计提供的数值更接近理论真值。
  • 作为功率谱估计的中间步骤:如果你计划对自相关函数做傅里叶变换来估计功率谱密度(PSD),那么应该使用无偏的自相关估计,或者使用专门的PSD估计函数(如pwelch),以避免频谱失真。

需要谨慎或避免使用无偏估计的场景:

  • 关注零时延附近的自相关:对于分析信号自身的周期性(如通过自相关求周期),零时延附近的信息最重要,有偏和无偏估计差异不大,但有偏估计的方差特性更好。
  • 信号长度很短,且关注大时延:如前所述,无偏估计在大时延处方差极大,结果不可信。此时,有偏估计虽然偏差大,但结果更“稳定”。
  • 后续处理对方差敏感:如果相关序列的后续算法(如某种检测器)对序列的平滑性有要求,有偏估计可能是更好的选择。

实操心得:在我的传感器对齐项目中,我最终选择了无偏估计。因为我的时延可能高达数百个样本,使用有偏估计时,相关峰看起来“矮胖”,与旁瓣区分不明显。切换到无偏估计后,峰值变得“高瘦”,通过简单的峰值检测算法就能稳定锁定,大大提高了对齐的可靠性。记住,没有一种估计在所有情况下都是最优的。理解它们的优缺点,根据你的具体目标(是追求无偏性还是低方差)来做选择,这才是关键。

5. xcorr的其他关键参数与高级用法

除了‘unbiased’xcorr还有其他几个重要参数,共同决定了计算的行为和结果。

5.1 归一化选项:‘coeff’‘normalized’

有时我们不仅关心相关性的形状和峰值位置,还希望相关系数被归一化到[-1, 1]的范围内,表示标准化的线性相关程度。这就要用到‘coeff’参数。

[r_coeff, lags] = xcorr(x, y, ‘coeff‘);

‘coeff’参数计算的是零时延归一化的互相关系数。它首先计算标准的有偏互相关,然后将整个序列除以 ( \sqrt{R_{xx}[0] * R_{yy}[0]} ),即两个信号在零时延的自相关值的几何平均。这样处理之后,在零时延处,自相关系数 (R_{xx}[0]) 会被归一化为1。对于互相关,其最大值不会超过1。

重要提示‘coeff’的归一化是基于零时延能量的,它不能消除有偏估计本身的三角窗衰减。也就是说,xcorr(x, y, ‘coeff’)得到的是归一化的有偏估计。如果你想要归一化的无偏估计,MATLAB并没有直接参数。一个常见的做法是先计算无偏估计,然后手动归一化:

[r_unb, lags] = xcorr(x, y, ‘unbiased‘); % 手动进行零时延能量归一化 r_unb_normalized = r_unb / sqrt(sum(x.^2) * sum(y.^2)); % 近似,对于有限长信号 % 或者更严谨地,用零时延自相关 rxx0 = xcorr(x, x, ‘unbiased‘); ryy0 = xcorr(y, y, ‘unbiased‘); % 注意xcorr输出是对称的,零时延在中间 zero_lag_index = find(lags == 0); norm_factor = sqrt(rxx0(zero_lag_index) * ryy0(zero_lag_index)); r_unb_coeff = r_unb / norm_factor;

5.2 计算模式选项:‘none’,‘biased’,‘unbiased’,‘coeff’

实际上,xcorr的完整语法是xcorr(x, y, maxlags, ‘scaleopt’)

  • maxlags: 指定计算的最大时延,可以减少计算量。例如,xcorr(x, y, 100)只计算从-100到100的时延。
  • ‘scaleopt’: 就是上面讨论的缩放选项。
    • ‘none’(默认):有偏估计,不进行其他归一化。
    • ‘biased’:明确指定有偏估计,与‘none’在实信号上结果相同。
    • ‘unbiased’:无偏估计。
    • ‘coeff’‘normalized’:零时延归一化的有偏估计。

5.3 处理复数信号与共轭对称性

当输入信号xy为复数时(例如,通信中的基带IQ信号),xcorr的行为需要注意。根据定义,公式中涉及复共轭y*[n-m]。MATLAB的xcorr在计算时会自动处理共轭。对于两个复数序列,xcorr(x, y)计算的是 ( \sum x[n] \cdot conj(y[n-m]) )。如果你不希望取共轭,需要预先自己对y进行处理。

此外,对于实信号的自相关(xcorr(x)),结果序列是偶对称的(r[m] = r[-m])。对于互相关,则没有这种对称性。了解这一点有助于验证计算结果。

6. 从相关序列到实际时延:完整的工程实现步骤

理论清晰了,参数也明白了,现在让我们串联起一个完整的时延估计工程流程。假设我们有两个传感器采集的音频信号sig1sig2,我们怀疑sig2相对于sig1有一个时延。

6.1 步骤一:数据预处理

相关分析对数据的预处理非常敏感。

  1. 去直流(去除均值):信号的直流分量(均值)会在零时延处产生一个很大的相关值,可能淹没我们关心的交流分量相关性。务必先去除均值。
    sig1 = sig1 - mean(sig1); sig2 = sig2 - mean(sig2);
  2. 滤波:如果已知感兴趣的信号成分所在的频带,可以进行带通滤波,以抑制带外噪声,提高信噪比,从而使相关峰更突出。
    Fs = 44100; % 示例采样率 f_low = 100; f_high = 3000; % 感兴趣的频带 [b, a] = butter(4, [f_low, f_high]/(Fs/2), ‘bandpass‘); sig1_filt = filtfilt(b, a, sig1); % 使用零相位滤波filtfilt sig2_filt = filtfilt(b, a, sig2);
  3. 截取有效段:如果信号很长,但只有中间一段包含我们关心的事件,可以先截取出来,减少不必要的计算量和对结果的干扰。

6.2 步骤二:计算互相关并选择参数

根据信号长度和预期时延范围,决定是否使用maxlags限制计算范围。根据分析目的选择scaleopt。对于时延估计,我通常首选‘unbiased’

% 假设我们预期时延不超过0.5秒 max_delay_seconds = 0.5; maxlags_samples = round(max_delay_seconds * Fs); [r, lags] = xcorr(sig1_filt, sig2_filt, maxlags_samples, ‘unbiased‘);

6.3 步骤三:峰值检测与时延提取

找到互相关序列r的绝对值的峰值位置。使用findpeaks函数可以更鲁棒,它能避免局部小波动带来的误判。

[peak_values, peak_indices] = findpeaks(abs(r), ‘MinPeakHeight‘, 0.2*max(abs(r)), ‘MinPeakDistance‘, round(Fs/50)); % MinPeakHeight: 设置最小峰值高度阈值,例如最大峰值的20% % MinPeakDistance: 设置峰值间最小距离,例如对应20ms,避免检测到多个紧邻的峰 if ~isempty(peak_indices) [~, main_peak_idx] = max(peak_values); % 找到最高的峰 delay_in_samples = lags(peak_indices(main_peak_idx)); delay_in_seconds = delay_in_samples / Fs; fprintf(‘估计时延: %d 个样本 (%.4f 秒)\n‘, delay_in_samples, delay_in_seconds); else warning(‘未找到显著的相关峰!‘); end

6.4 步骤四:结果可视化与验证

绘图是验证结果可信度的关键。

figure(‘Position‘, [100 100 1000 800]); subplot(3,1,1); t = (0:length(sig1_filt)-1)/Fs; plot(t, sig1_filt, ‘b‘); hold on; plot(t, sig2_filt, ‘r‘); legend(‘信号1‘, ‘信号2‘); xlabel(‘时间 (s)‘); ylabel(‘幅度‘); title(‘预处理后的输入信号‘); grid on; subplot(3,1,2); plot(lags/Fs, r, ‘k-‘, ‘LineWidth‘, 1.5); hold on; plot(delay_in_seconds, r(peak_indices(main_peak_idx)), ‘ro‘, ‘MarkerSize‘, 10, ‘LineWidth‘, 2); xlabel(‘时延 (s)‘); ylabel(‘无偏互相关系数‘); title(‘互相关函数‘); grid on; xlim([-max_delay_seconds, max_delay_seconds]); subplot(3,1,3); % 将信号2根据估计的时延进行对齐后叠加显示 if delay_in_samples > 0 % sig2 落后于 sig1,需要将sig2向左移动(或sig1向右移动) sig2_aligned = [sig2_filt(-delay_in_samples+1:end), zeros(1, -delay_in_samples)]; else % sig2 领先于 sig1,需要将sig2向右移动 sig2_aligned = [zeros(1, delay_in_samples), sig2_filt(1:end-delay_in_samples)]; end % 简单起见,截取到相同长度进行比较 min_len = min(length(sig1_filt), length(sig2_aligned)); plot(t(1:min_len), sig1_filt(1:min_len), ‘b-‘, ‘LineWidth‘, 1.5); hold on; plot(t(1:min_len), sig2_aligned(1:min_len), ‘r--‘, ‘LineWidth‘, 1.5); legend(‘信号1‘, ‘对齐后的信号2‘); xlabel(‘时间 (s)‘); ylabel(‘幅度‘); title(‘时延校正后的信号对比‘); grid on;

通过第三个子图,你可以直观地看到对齐效果。如果两条曲线的主要特征(如波峰、波谷)基本重合,说明时延估计是准确的。

7. 常见陷阱、进阶技巧与性能考量

即使掌握了基本流程,在实际操作中仍会遇到各种问题。这里分享一些踩坑经验和进阶思路。

7.1 当相关峰不唯一或平坦时怎么办?

有时互相关函数会出现多个相近的峰,或者一个很宽的“平台”,这给精确时延估计带来了困难。

  • 原因1:周期性信号。如果信号本身是周期性的(如正弦波、发动机振动信号),那么互相关函数也会是周期性的,在每个周期处都会出现峰值。此时,零时延附近的“主峰”可能不是全局最高峰。解决方案:结合先验知识(例如,时延不可能超过一个周期),或者使用包络检测、插值等方法来精确定位主峰。
  • 原因2:低信噪比或信号带宽太窄。信号带宽越窄,其自相关函数的主瓣就越宽。在极限情况下(单频正弦波),自相关函数是余弦波,没有明显单峰。互相关也会继承这个特性。解决方案:尽量使用宽带信号进行时延估计。如果信号本身带宽窄,可以考虑使用频域的广义互相关(GCC)方法,例如GCC-PHAT(相位变换加权),它对这种场景更鲁棒。MATLAB中可以通过计算互功率谱然后进行加权逆变换来实现。
  • 原因3:多径效应。在声学或通信中,信号可能通过多条路径到达,导致互相关函数出现多个峰值,对应不同的时延。解决方案:这属于信道估计问题,需要更复杂的算法(如解卷积)来分离多径。

7.2 利用频域计算提升长信号处理性能

对于很长的信号序列,直接时域计算互相关(复杂度O(N^2))会非常慢。根据相关定理,时域相关等价于频域共轭相乘。因此,通常使用基于FFT的快速算法来计算,这也是xcorr函数内部对长数据采用的默认方法。

% 手动实现基于FFT的互相关(无偏估计需额外处理) N = length(sig1); M = length(sig2); L = N + M - 1; % 线性卷积长度 P = 2^nextpow2(L); % FFT最佳长度 X = fft(sig1, P); Y = fft(sig2, P); R_freq = X .* conj(Y); % 频域相乘 r_temp = ifft(R_freq, ‘symmetric‘); % 回到时域,取实部(对于实信号) r_fft = r_temp(1:L); % 取有效部分 % 此时 r_fft 是未归一化的循环相关结果,对于线性相关需要截取和移位 % 更重要的是,要将其转换为无偏估计,需要手动除以 (N - abs(lags)) lags_vec = -(M-1):(N-1); for i = 1:length(lags_vec) m = abs(lags_vec(i)); r_fft_unbiased(i) = r_fft(i) / (N - m); % 仅当 m < N 时有效 end % 注意:上述循环方法仅为示意,实际处理大时延(m接近N)时的边界情况需谨慎。

对于绝大多数应用,直接使用优化过的xcorr函数即可,无需手动实现FFT版本。

7.3 自相关:一个特殊的互相关

xcorr(x)计算信号x的自相关。它是互相关在x=y时的特例。自相关函数在零时延处取得最大值,并且对于实信号是偶对称的。自相关常用于:

  • 检测信号周期性:周期信号的自相关函数也是同周期的周期函数。
  • 估计信号功率:零时延的自相关值等于信号的总能量(对于能量信号)或平均功率(对于功率信号)。
  • 白噪声检验:理想白噪声的自相关函数是一个冲激(除零时延外全为零)。

自相关同样面临有偏和无偏估计的选择,其考量与互相关类似。

7.4 处理非平稳信号与窗函数

标准的互相关分析假设信号是平稳的(统计特性不随时间变化)。对于非平稳信号(如语音、变转速机械振动),直接计算整个信号段的相关性可能没有意义。常用的方法是短时互相关:将信号分帧,对每一帧分别计算互相关。这实际上是在时频域进行分析,可以使用spectrogram等函数的互谱模式,或者手动实现分帧循环。

此外,在分帧计算相关或进行FFT时,可能会用到窗函数(如汉明窗)来减少频谱泄漏。需要注意的是,加窗会影响信号的幅度,进而影响相关值的绝对大小。在比较不同帧或不同信号的相关性时,需要确保处理方式一致,或者对结果进行适当的补偿归一化。

回到最初传感器对齐的问题,我最终采用的流程是:去直流、带通滤波、计算无偏互相关、使用findpeaks定位峰值。无偏估计让我在信噪比不高的情况下,依然能稳定地检测到远离零点的时延峰,成功将多个传感器的数据流精确对齐,为后续的融合分析打下了可靠的基础。理解工具背后的原理,永远比记住操作步骤更重要。