import numpy as np
import matplotlib.pyplot as plt
from scipy import signal
# 生成示例信号
t = np.linspace(0, 1, 1000)
x = np.sin(2 * np.pi * 5 * t) + np.sin(2 * np.pi * 20 * t) + np.random.randn(len(t)) * 0.2
# 设计低通滤波器
order = 3 # 滤波器阶数
cutoff_freq = 0.9 # 截止频率(Hz)
b, a = signal.butter(order, cutoff_freq, fs=2, btype='low', analog=False, output='ba')
# 应用滤波器
filtered_x = signal.lfilter(b, a, x)
# 绘制原始信号和滤波后的信号
plt.figure(figsize=(8, 6))
plt.plot(t, x, label='原始信号')
plt.plot(t, filtered_x, label='滤波后的信号')
plt.xlabel('时间')
plt.ylabel('振幅')
plt.legend()
plt.show()
动画效果展示,实时进行平滑:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from scipy import signal
# 创建图形对象和子图
fig, ax = plt.subplots()
# 设置空白的线对象
line_raw, = ax.plot([], [], 'b-', label='原始数据')
line_filtered, = ax.plot([], [], 'r-', label='平滑数据')
# 设计低通滤波器
order = 4
b, a = signal.butter(3, 0.8, btype='low', analog=False, output='ba')
# 初始化数据和滤波结果
x = np.zeros(1000)
filtered_x = np.zeros_like(x)
time = np.arange(len(x))
# 更新函数,用于每一帧的绘制
def update(frame):
global x, filtered_x, time
# 生成新数据
new_data = np.random.randn() # 这里示例使用随机数作为新数据
# 更新数据
x = np.append(x[1:], new_data)
time = np.append(time[1:], time[-1] + 1)
# 应用滤波器
filtered_x = signal.lfilter(b, a, x)
# 更新绘图数据
line_raw.set_data(time, x)
line_filtered.set_data(time, filtered_x)
# 设置轴的范围
ax.set_xlim(time[0], time[-1])
ax.set_ylim(min(x.min(), filtered_x.min()) - 1, max(x.max(), filtered_x.max()) + 1)
# 创建动画
ani = FuncAnimation(fig, update, frames=range(1000), interval=10)
# 设置图形界面
plt.xlabel('时间')
plt.ylabel('数值')
plt.legend()
# 显示动画
plt.show()
一欧元滤波
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from scipy import signal
class ExtendOneEuroFilter:
def __init__(self, x0, dx0=0.0, min_cutoff=1, beta=0.0, d_cutoff=1.0):
"""Initialize the one euro filter."""
# The parameters.
self.min_cutoff = float(min_cutoff)
self.beta = float(beta)
self.d_cutoff = float(d_cutoff)
# Previous values.
self.x_prev = float(x0)
self.dx_prev = float(dx0)
def __call__(self, x, t_e=1):
"""Compute the filtered signal."""
# The filtered derivative of the signal.
a_d = self.smoothing_factor(t_e, self.d_cutoff)
dx = (x - self.x_prev) / t_e
dx_hat = self.exponential_smoothing(a_d, dx, self.dx_prev)
# The filtered signal.
cutoff = self.min_cutoff + self.beta * abs(dx_hat)
a = self.smoothing_factor(t_e, cutoff)
x_hat = self.exponential_smoothing(a, x, self.x_prev)
# Memorize the previous values.
self.x_prev = x_hat
self.dx_prev = dx_hat
return x_hat
def exponential_smoothing(self, a, x, x_prev):
return a * x + (1 - a) * x_prev
def smoothing_factor(self, t_e, cutoff):
r = 2 * np.pi * cutoff * t_e
return r / (r + 1)
def update_prev(self,x_prev):
self.x_prev = x_prev
def get_prev(self):
return self.x_prev
def get_min_cutoff(self):
return self.min_cutoff
def update_min_cutoff(self, min_cutoff):
self.min_cutoff = min_cutoff
# 创建图形对象和子图
fig, ax = plt.subplots()
# 设置空白的线对象
line_raw, = ax.plot([], [], 'b-', label='原始数据')
line_filtered, = ax.plot([], [], 'r-', label='平滑数据')
# 初始化数据和滤波结果
x = np.zeros(30)
# ss = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1] * 100
filtered_x = np.zeros_like(x)
t = np.arange(len(x))
# 创建ExtendOneEuroFilter对象
one_euro_filter = ExtendOneEuroFilter(x0=0, dx0=0)
# 初始化点序号注释
point_num_text = ax.text(0, 0, '', fontsize=12, ha='center', va='center')
# 更新函数,用于每一帧的绘制
def update(frame):
global x, filtered_x, t, counter
# 生成新数据
if counter > 1000:
new_data = 1.0 # 设置为固定值
else:
new_data = np.random.randn()
# print(one_euro_filter.get_min_cutoff())
if counter > 100:
one_euro_filter.update_min_cutoff(0.5)
if counter > 200:
one_euro_filter.update_min_cutoff(0.25)
if counter > 300:
one_euro_filter.update_min_cutoff(0.1)
if counter > 400:
one_euro_filter.update_min_cutoff(0.08)
if counter > 500:
one_euro_filter.update_min_cutoff(0.05)
if counter > 600:
one_euro_filter.update_min_cutoff(0.03)
if counter > 700:
one_euro_filter.update_min_cutoff(0.02)
# 更新数据
x = np.append(x[1:], new_data)
# x = np.append(x[1:], ss[counter])
t = np.append(t[1:], t[-1] + 1)
# 应用滤波器
filtered_x = one_euro_filter(x, t_e=1)
print(filtered_x[-1])
# 更新绘图数据
line_raw.set_data(t, x)
line_filtered.set_data(t, filtered_x)
# 设置轴的范围
ax.set_xlim(t[0], t[-1])
ax.set_ylim(min(x.min(), filtered_x.min()) - 1, max(x.max(), filtered_x.max()) + 1)
# 更新点序号注释
point_num_text.set_position((t[-1], x[-1]))
point_num_text.set_text(str(counter))
# 更新计数器
counter += 1
# 创建动画
ani = FuncAnimation(fig, update, frames=range(1000), interval=10)
# 设置图形界面
plt.xlabel('时间')
plt.ylabel('数值')
plt.legend()
# 暂停状态的标志
paused = False
# 键盘事件处理函数
def on_key(event):
global paused
# 按下空格键暂停/恢复动画
if event.key == ' ':
paused = not paused
if paused:
ani.event_source.stop()
else:
ani.event_source.start()
# 绑定键盘事件处理函数
fig.canvas.mpl_connect('key_press_event', on_key)
# 初始化计数器
counter = 0
# 显示动画
plt.show()