当波形存在时间偏移时,动态时间规整(Dynamic Time Warping, DTW)是比较合适的方法,因为它能够处理两个序列在时间轴上的不对齐问题。DTW通过找到最优的路径来对齐两个波形,从而计算它们的相似度,即使存在时间偏移或长度差异也能有效比较。

下面是一个完整的JavaScript实现,专门用于处理有时间偏移的波形比较:

// 归一化函数:消除振幅差异影响
function normalize(arr) {
  const min = Math.min(...arr);
  const max = Math.max(...arr);
  const range = max - min;
  
  // 处理所有值相同的情况
  if (range === 0) {
    return arr.map(() => 0);
  }
  
  return arr.map(x => (x - min) / range);
}

// 动态时间规整(DTW)算法实现
function dtwDistance(seriesA, seriesB) {
  const m = seriesA.length;
  const n = seriesB.length;
  
  // 创建DTW矩阵并初始化
  const dtwMatrix = Array.from({ length: m + 1 }, () => 
    Array(n + 1).fill(Infinity)
  );
  dtwMatrix[0][0] = 0;
  
  // 填充DTW矩阵
  for (let i = 1; i <= m; i++) {
    for (let j = 1; j <= n; j++) {
      // 计算当前点的距离(欧氏距离的平方)
      const cost = Math.pow(seriesA[i - 1] - seriesB[j - 1], 2);
      
      // 取三个方向的最小值并加上当前成本
      dtwMatrix[i][j] = cost + Math.min(
        dtwMatrix[i - 1][j],    // 上方
        dtwMatrix[i][j - 1],    // 左方
        dtwMatrix[i - 1][j - 1] // 对角线
      );
    }
  }
  
  // 返回归一化后的距离(除以总长度,使结果不受序列长度影响)
  return dtwMatrix[m][n] / (m + n);
}

// 比较两个波形的整体形状(处理时间偏移)
function compareWaveformsWithOffset(waveA, waveB, threshold = 0.001) {
  // 先归一化,消除振幅差异
  const normA = normalize(waveA);
  const normB = normalize(waveB);
  
  // 计算DTW距离
  const distance = dtwDistance(normA, normB);
  
  // 根据阈值判断形状是否相似
  return {
    distance: distance,
    isSimilar: distance < threshold,
    threshold: threshold
  };
}

// 示例用法
function test() {
  // 创建两个相似但有时间偏移的波形
  const wave1 = [0, 1, 2.2, 3.5, 4.2, 3.7, 2, 1, 0, 1,6, 1, 0];
  const wave2 = [0, 0, 1, 2, 3, 4, 3, 2, 1, 0, 1, 2, 1, 0]; // 比wave1多一个初始0
  
  // 比较波形
  const result = compareWaveformsWithOffset(wave1, wave2);
  
  console.log(`DTW距离: ${result.distance.toFixed(4)}`);
  console.log(`阈值: ${result.threshold}`);
  console.log(`波形形状${result.isSimilar ? '相似' : '不相似'}`);
}

// 运行测试
test();

算法说明

这个实现特别针对有时间偏移的波形比较做了优化:

  1. 归一化处理:首先将波形归一化到[0,1]范围,消除振幅差异对比较结果的影响,只关注形状。
  2. DTW核心算法

    • 创建一个矩阵来存储两个序列之间的距离
    • 每个点的距离计算考虑了上方、左方和对角线三个方向的最小值
    • 这种设计允许波形在时间轴上"弯曲"对齐,有效处理时间偏移
  3. 结果解释

    • DTW距离越小,两个波形的形状越相似
    • 通过设置合适的阈值(threshold)来判断是否"形状一致"
    • 阈值需要根据实际数据特点调整,一般建议在0.01-0.1之间

使用建议

  • 对于存在明显时间偏移的波形,这种方法比简单的欧氏距离或相关系数更可靠
  • 如果波形长度差异很大,可以先进行重采样使长度接近,再应用DTW
  • 对于实时性要求高的场景,可以考虑优化DTW算法(如限制搜索窗口)

你可以根据实际波形数据的特点,调整threshold参数来获得最佳的比较效果。