逐渐filter/smooth一个信号在python(到左边的直线到右边的无滤波)

Progressively filter/smooth a signal in python (to straight line on the left to no filtering on the right)

一图抵千言(拙作见谅):

如果解决方案保留两端的值和斜率,则更好。 如果再加上转场的位置和锐度可以调整就完美了。

但是我还没有找到任何解决办法...

非常感谢您的帮助

这里有一段代码可以开始:

import matplotlib.pyplot as plt
from scipy.signal import savgol_filter
import numpy as np 

def round_up_to_odd(f):
    return np.int(np.ceil(f / 2.) * 2 + 1)

def generateRandomSignal(n=1000, seed=None):
    """
    Parameters
    ----------
    n : integer, optional
        Number of points in the signal. The default is 1000.

    Returns
    -------
    sig : numpy array

    """
    np.random.seed(seed)
    print("Seed was:", seed)
    steps = np.random.choice(a=[-1, 0, 1], size=(n-1))
    roughSig = np.concatenate([np.array([0]), steps]).cumsum(0)
    sig = savgol_filter(roughSig, round_up_to_odd(n/20), 6)
    return sig

n = 1000
t = np.linspace(0,10,n)
seed = np.random.randint(0,high=100000)
#seed = 45136
sig = generateRandomSignal(seed=seed)

###############################
# ????
# sigFilt = adaptiveFilter(sig)
###############################

# Plot
plt.figure()
plt.plot(t, sig, label="Signal")
# plt.plot(t, sigFilt, label="Signal filtered")
plt.legend()

简单的卷积做平滑处理。然而,如下所述,这里我们需要先进行强平滑,最后不进行平滑。我使用了动态大小为 window 的移动平均法。在下面的示例中,window 大小呈线性变化。

def dynamic_smoothing(x, start_window_length=(len(x)//2), end_window_length=1):
    d_sum = np.cumsum(a, dtype=float)
    smoothed = list()
    for i in range(len(x)):
        # compute window length
        a = i / len(x)
        w = int(np.round(a * start_window_length + (1.0-a) * end_window_length))
        # get the window
        w0 = max(0, i - w) # the window must stay inside the array 
        w1 = min(len(x), i + w)
        smoothed.append(sum(x[w0:w1])/(w1+w0))
    return np.array(smoothed)