在 python 中逐步过滤/平滑信号(到左边的直线到右边没有过滤)
Posted
技术标签:
【中文标题】在 python 中逐步过滤/平滑信号(到左边的直线到右边没有过滤)【英文标题】:Progressively filter/smooth a signal in python (to straight line on the left to no filtering on the right) 【发布时间】:2021-02-04 22:52:26 【问题描述】:一张图抵得上一千个字(为粗制滥造见谅):
如果解决方案保留两端的值和斜率,那就更好了。 此外,如果可以调整过渡的位置和清晰度,那就完美了。
但是我还没有找到任何解决方案...
非常感谢您的帮助
下面是一段代码开始:
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()
【问题讨论】:
我只是想知道我下面的回答是否有帮助。 【参考方案1】:简单卷积进行平滑处理。但是,如下所述,这里我们首先需要强平滑,最后不需要平滑。我将移动平均方法与窗口的动态大小一起使用。在下面的示例中,窗口大小呈线性变化。
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)
【讨论】:
感谢您的回复。我刚刚测试了你的解决方案。它确实平滑了信号,但不是我想要的方式:逐渐(左侧更平滑,右侧没有平滑,如图所示)。也许我错过了什么?我假设 w 是 window_length 但也许你有别的想法。 感谢您的更新。这是一个工作版本: def dynamic_smoothing(x, start_window_length=None, end_window_length=1): if not start_window_length: start_window_length = len(x)//2 smoothed = [] for i in range(len(x)): # 计算窗口长度 a = float(i) / len(x) w = int(np.round(a * start_window_length+(1.0-a) * end_window_length)) # 得到窗口 w0 = max(0, i - w) # 窗口必须留在数组内 w1 = min(len(x), i + w) smoothed.append(sum(x[w0:w1])/(w1-w0)) return np.array(smoothed) 这个想法很棒,它回答了我的问题。您可以继续,删除 UPD 上方的答案部分,然后复制粘贴我将修改的代码,我会接受答案。非常感谢!注意:窗口长度的线性减小虽然不是最好的,但我会自己修改!唯一的缺点是很难强制执行第一个点值和斜率。 注意,接受的答案有一些错误:start_window_length=(len(x)//2) 必须放在函数内部,d_sum 没有使用,a = float(i) / len (x),smoothed.append(sum(x[w0:w1])/(w1-w0)),最后一行没用,start_window_length和end_window_length必须切换……我把这个评论放在这里给以后的用户。跨度>以上是关于在 python 中逐步过滤/平滑信号(到左边的直线到右边没有过滤)的主要内容,如果未能解决你的问题,请参考以下文章