FFT卷积与直接卷积

计算科学 傅里叶变换
2021-12-17 03:35:17

最近我尝试比较一维直接卷积和通过 FFT 卷积的结果。我希望得到完全相同的结果,但是我遇到了一个结果不同的问题,尤其是在左边界附近。

在此处输入图像描述

在此处输入图像描述

FFT 卷积应该被归一化,但它不会改变左边界附近的差异。据我了解,出现这种差异是因为 FFT 提供循环卷积,而直接卷积是线性的。我发现它可以通过 Overlap-add 方法修复,但是据我所知,当曲线和内核具有不同的长度时应该使用它,但在我的情况下它们都具有相同的长度。

数学代码:

mat = Table[0, {x, 512}, {y, 512}];
SetAttributes[FillMatrix, HoldAll]
FillMatrix[Kep_, Ktrans_, mat_] := 
  Do[Do[mat[[j, i]] = Exp[-Kep (j - i + 1)], {i, 1, j, 1}], {j, 1, 
    Length[mat], 1}];

FillArray[Kep_, Ktrans_, mat_] := 
 Module[{curve = {}}, 
  Do[curve = Append[curve, Exp[-Kep*i]], {i, 1, Length[mat], 1}]; 
  curve]

AIF = {};
SetAttributes[FillAIF, HoldAll]
FillAIF[AIF_, n_] := 
 Do[AIF = Append[AIF, PDF[GammaDistribution[3, 2], i*0.1]], {i, 1, n, 
   1}]

FillAIF[AIF, Length[mat]]

FillMatrix[0.005, 1, mat]
conv = mat.AIF;

AIFFourier = Fourier[AIF];
kernelCurve = FillArray[0.005, 1, mat];
kernelCurveFourier = Fourier[kernelCurve];

resSource = InverseFourier[AIFFourier*kernelCurveFourier];
ListPlot[resSource, Joined -> True]
ListPlot[conv, Joined -> True]

问题:为什么会出现这种差异,如何解决?

1个回答

一种蛮力方法是用足够的零填充信号和内核,以便在进行循环卷积时不会出现混叠:

AIFFourier = Fourier[PadRight[AIF, 1024]];
kernelCurve = FillArray[0.005, 1, mat];
kernelCurveFourier = Fourier[PadRight[kernelCurve, 1024]];

resSource = InverseFourier[AIFFourier*kernelCurveFourier];
ListPlot[resSource[[1 ;; 512]], Joined -> True]
ListPlot[conv, Joined -> True]
StandardDeviation[resSource[[1 ;; 512]]/conv]

2.37134×1015