假設兩個平穩信號 $\textbf{x}$ 和 $\textbf{y}$ ,如果 $x\left(t+\tau\right)= y\left(t\right)$ ,則可通過互相關求 $\tau$ 。由於信號處理相關知識都蘸醬吃了,理論相關的部分咱們來日方長(我一定可能會補充的)。
XCORR 實現
首先,通過實現 xcorr 函數介紹互相關計算流程:
clc clear close % 實現 xcorr 函數 % 基本設置 T = 1; % [s] 總時間長度 fs = 5000; % [Hz] 采樣頻率 t = 0:1/fs:T; % [s] 時間坐標 N = length(t); % 信號個數 % 信號生成 tm = [ t(1:N) - T , t(2:N) ]; % 相關結果的時間延遲坐標軸 td1 = 0.2*T; % x 信號時間延遲 td2 = 0.3*T; % y 信號時間延遲 noise = rand(1,2*N); % 生成了兩倍時間 T 長度的噪聲 [0,1]噪聲 x = noise(1+round(td1*fs):N+round(td1*fs))-0.5*ones(1,N); y = noise(1+round(td2*fs):N+round(td2*fs))-0.5*ones(1,N); % 求取互相關 z1 = xcorr(x,y); % Matlab 自帶函數 [~,I1] = max(abs(z1)); % 模仿 Matlab doc 給出延遲坐標 z2 = zeros(1,N); % 自編函數 for n = 1:length(tm) z2(n) = sum( x( max(1,n-N+1):min(n,N) ).*y( max(1,N-n+1):min(2*N-n,N) ) ); end [~,I2] = max(abs(z2)); % 模仿 Matlab doc 給出延遲坐標 %---------------------計算說明--------------------% % case1: | case2: % % .N | .2*N-n % % y: .......... | y: .......... % % .N-n+1 | .1 % % .n | .N % % x: .......... | x: .......... % % .1 | .n-N+1 % %------------------------------------------------% err = z1-z2; % 兩種算法的差 % 繪圖 subplot(1,3,1) plot(tm,z1) title('Matlab function') xlabel('time delay') ylabel('Amp') a1 = gca; a1.XTick = sort([-1:0.5:1 tm(I1)]); subplot(1,3,2) plot(tm,z2) title('My function') xlabel('time delay') ylabel('Amp') a2 = gca; a2.XTick = sort([-1:0.5:1 tm(I2)]); subplot(1,3,3) plot(tm,err,'.-') title('error') xlabel('time delay') ylabel('Amp') suptitle('xcorr realization')
以上 Matlab 代碼可以得到下面的結果。從左到右依次是 Matlab 自帶函數、我編的互相關函數、兩個函數的差值。不難發現:兩個函數十分接近,但是差值不為零。個人猜測是因為 xcorr 的求和和 sum 求和的截斷誤差不同所致。這個誤差的來源我懶得去編程序驗證了——畢竟10-16量級的差別,沒多大深究的意義。但是可以注意到這個差值有四個特點:
- 小幅值時有固定幾個數值
- 每跑一次程序,rand 產生的噪聲數據不同,error 值不同
- 呈“紡錘型”,中間高,兩邊低
- 實際值大的數據點,error 值大
最后要談一下 xcorr 的噪聲問題。我們通常使用的噪聲是白噪聲,或者高斯白,有一個很重要的特點就是均值為零,也就是說沒有直流分量。但是當我們的噪聲存在直流分量的時候(比如上面的噪聲信號直接使用rand(1,2*N)時),互相關就是一個類似等腰三角形的東西了(想想門函數卷積)。回憶一下,對於存在穩定周期分量的兩組信號 $\textbf{x}$ 、 $\textbf{y}$ 而言,互相關結果將會是一個幅度為“紡錘形”的周期震盪的信號。由此可觀:互相關一方面可以得到非周期信號延遲結果,同時也能反映極端情況下,相同頻率成分的存在,這一點可以用來觀察工頻干擾程度。
XCORR 與 CONV
互相關 xcorr 與 conv 的差別在於兩點:
- xcorr 在兩段信號較短者后補零,使兩段信號長度一致
- xcorr 直接用兩個信號的各種延遲做相乘求和,conv 使用翻褶后的信號做相乘求和
這導致了:
1、xcorr(x,y) 中 (x,y) 順序有影響,而conv(x,y) 沒有
2、兩者在大部分情況下得到的結果是不一樣的,但是對於一些有趣的對稱信號是存在等價關系的。有興趣的讀者可以搞一搞,找找規律。因為本人並不搞對稱相關的研究,這點就不展開了。下面的例子是有等價關系的。
clc clear close % 比較 conv xcorr % 例子 A = ones(1,12); % -3:3 B = 0:4; % 3:-1:-3 C = xcorr(A,B); D = conv(A,B); %繪圖 subplot(2,2,1) plot(A,'.-') ylim([ -0.1 5.1 ]) xlim([ 0.9 12.1]) title('A = ones(1,12)') xlabel('n') ylabel('Amp') subplot(2,2,2) plot(B,'.-') ylim([ -0.1 5.1 ]) xlim([ 0.9 12.1]) title('B = 0:4') xlabel('n') ylabel('Amp') subplot(2,2,3) plot(C,'.-') ylim([ -0.1 15.1 ]) xlim([ 0.9 25.1]) title('xcorr 結果') xlabel('n') ylabel('Amp') subplot(2,2,4) plot(D,'.-') ylim([ -0.1 15.1 ]) xlim([ 0.9 25.1]) title('cone 結果') xlabel('n') ylabel('Amp') suptitle('conv與xcorr對比')
有興趣的讀者可以試着用給定函數實現目標函數:
- xcorr --> fliplr
- xcorr --> conv
- conv --> fliplr
- conv --> xcorr
END