我制作了一个 python 代码来使用 Weierstrass 变换来平滑给定的信号,这基本上是归一化高斯与信号的卷积。
代码如下:
#Importing relevant libraries
from __future__ import division
from scipy.signal import fftconvolve
import numpy as np
def smooth_func(sig, x, t= 0.002):
N = len(x)
x1 = x[-1]
x0 = x[0]
# defining a new array y which is symmetric around zero, to make the gaussian symmetric.
y = np.linspace(-(x1-x0)/2, (x1-x0)/2, N)
#gaussian centered around zero.
gaus = np.exp(-y**(2)/t)
#using fftconvolve to speed up the convolution; gaus.sum() is the normalization constant.
return fftconvolve(sig, gaus/gaus.sum(), mode='same')
如果我为一个阶跃函数运行此代码,它会平滑拐角,但在边界处它会解释另一个拐角并使其平滑,因此会在边界处产生不必要的行为。我用下面链接中显示的图来解释这一点。
边界效应
如果我们直接积分求卷积就不会出现这个问题。因此问题不在于 Weierstras 变换,因此问题在于 scipy 的 fftconvolve 函数。
要理解为什么会出现这个问题,我们首先需要了解 fftconvolve 在 scipy 中的工作原理。
fftconvolve 函数基本上使用卷积定理来加速计算。
简而言之:
卷积(int1,int2)=ifft(fft(int1)*fft(int2))
如果我们直接应用这个定理,我们不会得到想要的结果。为了得到想要的结果,我们需要对一个大小为 max(int1,int2) 的数组进行 fft。但这会导致不希望的边界效应。这是因为在 fft 代码中,如果 size(int) 大于大小(在其上采用 fft),它会将输入填充为零,然后采用 fft。这种零填充正是造成不希望的边界效应的原因。
你能建议一种消除这种边界效应的方法吗?
我试图通过一个简单的技巧将其删除。平滑函数后,我将平滑信号的值与边界附近的原始信号进行比较,如果它们不匹配,我将平滑函数的值替换为该点的输入信号。
如下:
i = 0
eps=1e-3
while abs(smooth[i]-sig[i])> eps: #compairing the signals on the left boundary
smooth[i] = sig[i]
i = i + 1
j = -1
while abs(smooth[j]-sig[j])> eps: # compairing on the right boundary.
smooth[j] = sig[j]
j = j - 1
这个方法有个问题,因为使用了epsilon,smoothened函数有小的跳转,如下图:
上面的方法可以做些改变来解决这个边界问题吗?