自相关和互相关、卷积计算流程演示
我们有两个信号,假设为x和y。
x = [1,3,4,6,7,2,3,1,6,8,10,1,2,1,1,1,1,1,1,3,3,4,5,6,1,2,12]
y = [1,3,4,8,7,2,5,1,6,8,10,1,2,1,1,1,1,2,1,3,3,4,5,6,1,2,14]
自相关 (Autocorrelation)
以信号x为例,计算时延为0, 1, 2时的自相关:
时延=0(信号完全对齐):
x: [1,3,4,6,7,2,3,1,6,8,10,1,2,1,1,1,1,1,1,3,3,4,5,6,1,2,12] x: [1,3,4,6,7,2,3,1,6,8,10,1,2,1,1,1,1,1,1,3,3,4,5,6,1,2,12] 对应相乘求和:1×1 + 3×3 + 4×4 + ... = 很高的值
时延=1:
x: [1,3,4,6,7,2,3,1,6,8,10,1,2,1,1,1,1,1,1,3,3,4,5,6,1,2,12] x: [1,3,4,6,7,2,3,1,6,8,10,1,2,1,1,1,1,1,1,3,3,4,5,6,1,2,12] 对应相乘求和:3×1 + 4×3 + 6×4 + ... = 较低的值
时延=2:
x: [1,3,4,6,7,2,3,1,6,8,10,1,2,1,1,1,1,1,1,3,3,4,5,6,1,2,12] x: [1,3,4,6,7,2,3,1,6,8,10,1,2,1,1,1,1,1,1,3,3,4,5,6,1,2,12]
互相关 (Cross-correlation)
互相关是两个不同信号在不同时间偏移下的相似性度量。
计算示例:
时延=0:
x: [1,3,4,6,7,2,3,1,6,8,10,1,2,1,1,1,1,1,1,3,3,4,5,6,1,2,12] y: [1,3,4,8,7,2,5,1,6,8,10,1,2,1,1,1,1,2,1,3,3,4,5,6,1,2,14] 对应相乘求和:1×1 + 3×3 + 4×4 + 6×8 + ...
时延=1:
x: [1,3,4,6,7,2,3,1,6,8,10,1,2,1,1,1,1,1,1,3,3,4,5,6,1,2,12] y: [1,3,4,8,7,2,5,1,6,8,10,1,2,1,1,1,1,2,1,3,3,4,5,6,1,2,14] 对应相乘求和:3×1 + 4×3 + 6×4 + 7×8 + ...
Python代码实现
import numpy as np
import matplotlib.pyplot as pltx = np.array([1,3,4,6,7,2,3,1,6,8,10,1,2,1,1,1,1,1,1,3,3,4,5,6,1,2,12])
y = np.array([1,3,4,8,7,2,5,1,6,8,10,1,2,1,1,1,1,2,1,3,3,4,5,6,1,2,14])# 自相关
autocorr_x = np.correlate(x, x, mode='full')
autocorr_y = np.correlate(y, y, mode='full')# 互相关
crosscorr = np.correlate(x, y, mode='full')# 绘制结果
lags = np.arange(-len(x)+1, len(x))plt.figure(figsize=(15, 5))
plt.subplot(1, 3, 1)
plt.plot(lags, autocorr_x)
plt.title('x的自相关')
plt.xlabel('时延')
plt.ylabel('相关性')plt.subplot(1, 3, 2)
plt.plot(lags, autocorr_y)
plt.title('y的自相关')
plt.xlabel('时延')
plt.ylabel('相关性')plt.subplot(1, 3, 3)
plt.plot(lags, crosscorr)
plt.title('x和y的互相关')
plt.xlabel('时延')
plt.ylabel('相关性')plt.tight_layout()
plt.show()# 打印最大值位置
print(f"x自相关最大值位置: {np.argmax(autocorr_x) - len(x) + 1}")
print(f"y自相关最大值位置: {np.argmax(autocorr_y) - len(y) + 1}")
print(f"互相关最大值位置: {np.argmax(crosscorr) - len(x) + 1}")
实际应用意义
自相关应用:
检测信号的周期性
在时延=0处总是最大值(完全自相似)
用于信号处理和模式识别
互相关应用:
确定两个信号之间的时间延迟
模板匹配(在信号y中寻找与x相似的片段)
雷达和声纳系统中的目标检测
卷积的过程:
假设存在俩个信号: x = [1, 3, 4, 6] y = [1, 3, 4, 8]
步骤1:翻转第二个信号 y
y_flipped = [8, 4, 3, 1]
步骤2:逐位置滑动计算
位置 0:
x: [1, 3, 4, 6] y翻转: [1] 重叠部分:只有1和1重叠 乘积 = 1×1 = 1 卷积结果[0] = 1
位置 1:
x: [1, 3, 4, 6] y翻转: [3, 1] 重叠部分: [1,3] 和 [3,1] 1×3 + 3×1 = 3 + 3 = 6 卷积结果[1] = 6
位置 2:
x: [1, 3, 4, 6] y翻转: [4, 3, 1] 重叠部分: [1,3,4] 和 [4,3,1] 1×4 + 3×3 + 4×1 = 4 + 9 + 4 = 17 卷积结果[2] = 17
位置 3:
x: [1, 3, 4, 6] y翻转: [8, 4, 3, 1] 重叠部分: [1,3,4,6] 和 [8,4,3,1] 1×8 + 3×4 + 4×3 + 6×1 = 8 + 12 + 12 + 6 = 38 卷积结果[3] = 38
位置 4:
x: [1, 3, 4, 6] y翻转: [8, 4, 3] 重叠部分: [3,4,6] 和 [8,4,3] 3×8 + 4×4 + 6×3 = 24 + 16 + 18 = 58 卷积结果[4] = 58
位置 5:
x: [1, 3, 4, 6] y翻转: [8, 4] 重叠部分: [4,6] 和 [8,4] 4×8 + 6×4 = 32 + 24 = 56 卷积结果[5] = 56
位置 6:
x: [1, 3, 4, 6] y翻转: [8] 重叠部分: [6] 和 [8] 6×8 = 48 卷积结果[6] = 48
最终卷积结果:[1, 6, 17, 38, 58, 56, 48]
python代码实现俩个卷积:
假设信号为:
x = [1,3,4,6,7,2,3,1,6,8,10,1,2,1,1,1,1,1,1,3,3,4,5,6,1,2,12] y = [1,3,4,8,7,2,5,1,6,8,10,1,2,1,1,1,1,2,1,3,3,4,5,6,1,2,14]
import numpy as np
import matplotlib.pyplot as pltx = np.array([1,3,4,6,7,2,3,1,6,8,10,1,2,1,1,1,1,1,1,3,3,4,5,6,1,2,12])
y = np.array([1,3,4,8,7,2,5,1,6,8,10,1,2,1,1,1,1,2,1,3,3,4,5,6,1,2,14])# 方法1:使用numpy的convolve函数
conv_result = np.convolve(x, y, mode='full')
print("卷积结果长度:", len(conv_result))
print("前10个卷积值:", conv_result[:10])# 方法2:手动实现卷积
def manual_convolution(a, b):len_a, len_b = len(a), len(b)result = np.zeros(len_a + len_b - 1)# 翻转第二个信号b_flipped = b[::-1]# 对于每个输出位置for n in range(len_a + len_b - 1):# 计算重叠范围start_a = max(0, n - len_b + 1)end_a = min(n + 1, len_a)start_b = max(0, len_b - 1 - n)end_b = min(len_b, len_a + len_b - 1 - n)# 计算乘积和for i in range(end_a - start_a):result[n] += a[start_a + i] * b_flipped[start_b + i]return result# 验证手动实现
manual_conv = manual_convolution(x, y)
print("手动实现前10个值:", manual_conv[:10])
print("两种方法是否一致:", np.allclose(conv_result, manual_conv))# 可视化结果
plt.figure(figsize=(12, 8))plt.subplot(3, 1, 1)
plt.stem(x, basefmt=" ")
plt.title('信号 x')
plt.grid(True)plt.subplot(3, 1, 2)
plt.stem(y, basefmt=" ")
plt.title('信号 y')
plt.grid(True)plt.subplot(3, 1, 3)
plt.stem(conv_result, basefmt=" ")
plt.title('卷积结果 x * y')
plt.grid(True)plt.tight_layout()
plt.show()# 不同模式的卷积
print("\n不同卷积模式:")
print("Full模式长度:", len(np.convolve(x, y, mode='full')))
print("Same模式长度:", len(np.convolve(x, y, mode='same')))
print("Valid模式长度:", len(np.convolve(x, y, mode='valid')))卷积 vs 互相关
卷积:需要翻转其中一个信号
互相关:不需要翻转信号
