python实现滤波器的简单案例
python实现滤波器的简单案例
- python实现滤波器的简单案例
- 四阶贝塞尔滤波器过滤
- 效果
- 代码
- butter
- 效果
- 代码
python实现滤波器的简单案例
这。。。
天天都在用deepseek写代码,自己是完全不会了。这里记录下来python实现滤波器的简单案例。
四阶贝塞尔滤波器过滤
效果
代码
import sys
import numpy as np
from scipy import signal
from scipy.fft import fft, fftfreq
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QSlider, QLabel, QGroupBox, QPushButton,QSpinBox, QDoubleSpinBox, QFormLayout, QSplitter)
from PyQt5.QtCore import Qt, QTimerapp = QApplication(sys.argv)
import pyqtgraph as pgclass NoiseGenerator:def __init__(self, fs=1000.0, duration=1.0):self.fs = fsself.duration = durationself.N = int(fs * duration)self.t = np.linspace(0, duration, self.N, endpoint=False)self.noise = Noneself.filtered_noise = Nonedef read_sensor_data(self, filename):data_values = []with open(filename, 'r') as file:for line in file:line = line.strip()value = int(line )data_values.append(value)return np.array(data_values)def generate_noise(self, mean=0, std_dev=1):"""生成高斯白噪声"""self.noise = self.read_sensor_data("your_file.txt")print(len(self.noise))return self.noisedef apply_filter(self, cutoff_freq, filter_order=4):"""应用四阶贝塞尔低通滤波器"""if self.noise is None:self.generate_noise()# 使用贝塞尔滤波器(Bessel filter)b, a = signal.bessel(filter_order, cutoff_freq / (self.fs / 2), 'low', norm='phase')# 使用零相移滤波self.filtered_noise = signal.filtfilt(b, a, self.noise)return self.filtered_noisedef compute_spectrum(self, signal_data):"""计算信号的频谱"""n = len(signal_data)fft_vals = fft(signal_data)freqs = fftfreq(n, 1/self.fs)magnitude = np.abs(fft_vals) / n * 2return freqs[:n//2], magnitude[:n//2]class MainWindow(QMainWindow):def __init__(self):super().__init__()self.setWindowTitle("四阶贝塞尔低通滤波器")self.setGeometry(100, 100, 1200, 800)# 初始化噪声生成器self.generator = NoiseGenerator(fs=1000000, duration=1.042432)# 初始化参数self.cutoff_freq = 50000.0self.filter_order = 4 # 固定为4阶贝塞尔滤波器self.std_dev = 1.0self.init_ui()self.update_plots()def init_ui(self):"""初始化用户界面"""# 左侧控制面板control_panel = QGroupBox("控制面板")control_layout = QFormLayout()# 截止频率控制self.cutoff_slider = QSlider(Qt.Horizontal)self.cutoff_slider.setRange(1000, 200000) # 调整范围以适应您的采样频率self.cutoff_slider.setValue(int(self.cutoff_freq))self.cutoff_slider.valueChanged.connect(self.on_cutoff_changed)self.cutoff_spinbox = QDoubleSpinBox()self.cutoff_spinbox.setRange(1000.0, 200000.0) # 调整范围self.cutoff_spinbox.setValue(self.cutoff_freq)self.cutoff_spinbox.setSuffix(" Hz")self.cutoff_spinbox.valueChanged.connect(self.on_cutoff_spinbox_changed)cutoff_layout = QHBoxLayout()cutoff_layout.addWidget(self.cutoff_slider)cutoff_layout.addWidget(self.cutoff_spinbox)control_layout.addRow("截止频率:", cutoff_layout)# 滤波器阶数显示(固定为4阶贝塞尔)self.order_label = QLabel("4 (贝塞尔滤波器)")control_layout.addRow("滤波器阶数:", self.order_label)# 噪声标准差控制self.std_spinbox = QDoubleSpinBox()self.std_spinbox.setRange(0.1, 5.0)self.std_spinbox.setValue(self.std_dev)self.std_spinbox.setSingleStep(0.1)self.std_spinbox.valueChanged.connect(self.on_std_changed)control_layout.addRow("噪声标准差:", self.std_spinbox)# 滤波器类型信息filter_info = QLabel("使用四阶贝塞尔滤波器\n特点:线性相位响应,保持波形形状")filter_info.setWordWrap(True)control_layout.addRow("滤波器类型:", filter_info)# 控制按钮self.generate_btn = QPushButton("重新生成噪声")self.generate_btn.clicked.connect(self.on_generate_clicked)control_layout.addRow(self.generate_btn)self.auto_update_cb = QPushButton("暂停自动更新")self.auto_update_cb.setCheckable(True)self.auto_update_cb.clicked.connect(self.on_auto_update_toggled)control_layout.addRow(self.auto_update_cb)control_panel.setLayout(control_layout)control_panel.setMaximumWidth(350)# 右侧图表区域plot_widget = QWidget()plot_layout = QVBoxLayout(plot_widget)# 时域图self.time_plot = pg.PlotWidget(title="时域波形 - 四阶贝塞尔滤波器")self.time_plot.setLabel('left', '幅度')self.time_plot.setLabel('bottom', '时间', 's')self.time_plot.addLegend()self.time_curve_original = self.time_plot.plot(pen='b', name='原始信号')self.time_curve_filtered = self.time_plot.plot(pen='r', name='贝塞尔滤波后')# 频域图self.freq_plot = pg.PlotWidget(title="频谱 - 四阶贝塞尔滤波器")self.freq_plot.setLabel('left', '幅度')self.freq_plot.setLabel('bottom', '频率', 'Hz')self.freq_plot.setLogMode(False, True) # Y轴对数坐标self.freq_plot.addLegend()self.freq_curve_original = self.freq_plot.plot(pen='b', name='原始频谱')self.freq_curve_filtered = self.freq_plot.plot(pen='r', name='滤波后频谱')self.cutoff_line = pg.InfiniteLine(angle=90, movable=False, pen='g')self.freq_plot.addItem(self.cutoff_line)plot_layout.addWidget(self.time_plot, 1)plot_layout.addWidget(self.freq_plot, 1)central_widget = QWidget()self.setCentralWidget(central_widget)main_layout = QHBoxLayout(central_widget)main_layout.addWidget(control_panel)main_layout.addWidget(plot_widget, 1) # 垂直分割# 设置定时器用于自动更新self.timer = QTimer()self.timer.timeout.connect(self.update_plots)self.timer.start(100) # 每100ms更新一次def on_cutoff_changed(self, value):"""滑块值改变时的处理"""self.cutoff_freq = valueself.cutoff_spinbox.setValue(value)self.update_plots()def on_cutoff_spinbox_changed(self, value):"""微调框值改变时的处理"""self.cutoff_freq = valueself.cutoff_slider.setValue(int(value))self.update_plots()def on_order_changed(self, value):"""滤波器阶数改变时的处理"""# 贝塞尔滤波器固定为4阶self.filter_order = 4self.update_plots()def on_std_changed(self, value):"""标准差改变时的处理"""self.std_dev = valueself.update_plots()def on_generate_clicked(self):"""重新生成噪声按钮点击处理"""self.generator.generate_noise(std_dev=self.std_dev)self.update_plots()def on_auto_update_toggled(self, checked):"""自动更新切换处理"""if checked:self.timer.stop()self.auto_update_cb.setText("开始自动更新")else:self.timer.start(100)self.auto_update_cb.setText("暂停自动更新")def update_plots(self):"""更新图表显示"""# 生成新噪声(如果还没有)if self.generator.noise is None:self.generator.generate_noise(std_dev=self.std_dev)# 应用四阶贝塞尔滤波器filtered = self.generator.apply_filter(self.cutoff_freq, self.filter_order)# 计算频谱freqs_orig, spec_orig = self.generator.compute_spectrum(self.generator.noise)freqs_filt, spec_filt = self.generator.compute_spectrum(filtered)# 更新时域图self.time_curve_original.setData(self.generator.t, self.generator.noise)self.time_curve_filtered.setData(self.generator.t, filtered)# 更新频域图self.freq_curve_original.setData(freqs_orig, spec_orig)self.freq_curve_filtered.setData(freqs_filt, spec_filt)self.cutoff_line.setValue(self.cutoff_freq)# 设置频域图显示范围self.freq_plot.setXRange(0, 500000)# 更新窗口标题显示统计信息orig_std = np.std(self.generator.noise)filt_std = np.std(filtered)power_ratio = (filt_std / orig_std) ** 2self.setWindowTitle(f"四阶贝塞尔低通滤波器 | "f"截止频率: {self.cutoff_freq}Hz | "f"输入功率: {orig_std**2:.3f} | "f"输出功率: {filt_std**2:.3f} | "f"功率比: {power_ratio:.3f}")def main():# 设置pyqtgraph样式pg.setConfigOption('background', 'w')pg.setConfigOption('foreground', 'k')window = MainWindow()window.show()sys.exit(app.exec_())if __name__ == "__main__":main()
butter
效果
代码
import sys
import numpy as np
from scipy import signal
from scipy.fft import fft, fftfreqfrom PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QSlider, QLabel, QGroupBox, QPushButton,QSpinBox, QDoubleSpinBox, QFormLayout)
from PyQt5.QtCore import Qt, QTimerapp = QApplication(sys.argv)
import pyqtgraph as pg
class NoiseGenerator:def __init__(self, fs=1000.0, duration=1.0):self.fs = fsself.duration = durationself.N = int(fs * duration)self.t = np.linspace(0, duration, self.N, endpoint=False)self.noise = Noneself.filtered_noise = Nonedef read_sensor_data(self, filename):# """# 读取传感器数据文件,提取数值第一列(除去HEAD和GPSTim开头的行)# """data_values = []with open(filename, 'r') as file:for line in file:line = line.strip()value = int(parts[0])data_values.append(value)return np.array(data_values)def generate_noise(self, mean=0, std_dev=1):"""生成高斯白噪声"""self.noise = np.random.normal(mean, std_dev, self.N)# self.noise = self.read_sensor_data("your_file.txt")print(len(self.noise))return self.noisedef apply_filter(self, cutoff_freq, filter_order=4):"""应用低通滤波器"""if self.noise is None:self.generate_noise()b, a = signal.butter(filter_order, cutoff_freq / (self.fs / 2), 'low')# 使用零相移滤波self.filtered_noise = signal.filtfilt(b, a, self.noise)return self.filtered_noisedef compute_spectrum(self, signal_data):"""计算信号的频谱"""n = len(signal_data)fft_vals = fft(signal_data)freqs = fftfreq(n, 1/self.fs)magnitude = np.abs(fft_vals) / n * 2return freqs[:n//2], magnitude[:n//2]class MainWindow(QMainWindow):def __init__(self):super().__init__()self.setWindowTitle("高斯白噪声低通滤波器")self.setGeometry(100, 100, 1200, 800)# 初始化噪声生成器self.generator = NoiseGenerator(fs=1000000, duration=1.042432)# 初始化参数self.cutoff_freq = 50000.0self.filter_order = 4self.std_dev = 1.0self.init_ui()self.update_plots()def init_ui(self):"""初始化用户界面"""central_widget = QWidget()self.setCentralWidget(central_widget)main_layout = QHBoxLayout(central_widget)# 左侧控制面板control_panel = QGroupBox("控制面板")control_layout = QFormLayout()# 截止频率控制self.cutoff_slider = QSlider(Qt.Horizontal)self.cutoff_slider.setRange(1, 200)self.cutoff_slider.setValue(int(self.cutoff_freq))self.cutoff_slider.valueChanged.connect(self.on_cutoff_changed)self.cutoff_spinbox = QDoubleSpinBox()self.cutoff_spinbox.setRange(1.0, 200.0)self.cutoff_spinbox.setValue(self.cutoff_freq)self.cutoff_spinbox.setSuffix(" Hz")self.cutoff_spinbox.valueChanged.connect(self.on_cutoff_spinbox_changed)cutoff_layout = QHBoxLayout()cutoff_layout.addWidget(self.cutoff_slider)cutoff_layout.addWidget(self.cutoff_spinbox)control_layout.addRow("截止频率:", cutoff_layout)# 滤波器阶数控制self.order_spinbox = QSpinBox()self.order_spinbox.setRange(1, 8)self.order_spinbox.setValue(self.filter_order)self.order_spinbox.valueChanged.connect(self.on_order_changed)control_layout.addRow("滤波器阶数:", self.order_spinbox)# 噪声标准差控制self.std_spinbox = QDoubleSpinBox()self.std_spinbox.setRange(0.1, 5.0)self.std_spinbox.setValue(self.std_dev)self.std_spinbox.setSingleStep(0.1)self.std_spinbox.valueChanged.connect(self.on_std_changed)control_layout.addRow("噪声标准差:", self.std_spinbox)# 控制按钮self.generate_btn = QPushButton("重新生成噪声")self.generate_btn.clicked.connect(self.on_generate_clicked)control_layout.addRow(self.generate_btn)self.auto_update_cb = QPushButton("暂停自动更新")self.auto_update_cb.setCheckable(True)self.auto_update_cb.clicked.connect(self.on_auto_update_toggled)control_layout.addRow(self.auto_update_cb)control_panel.setLayout(control_layout)control_panel.setMaximumWidth(300)# 右侧图表区域plot_widget = QWidget()plot_layout = QVBoxLayout(plot_widget)# 时域图self.time_plot = pg.PlotWidget(title="时域波形")self.time_plot.setLabel('left', '幅度')self.time_plot.setLabel('bottom', '时间', 's')self.time_plot.addLegend()self.time_curve_original = self.time_plot.plot(pen='b', name='原始噪声')self.time_curve_filtered = self.time_plot.plot(pen='r', name='滤波后噪声')# 频域图self.freq_plot = pg.PlotWidget(title="频谱")self.freq_plot.setLabel('left', '幅度')self.freq_plot.setLabel('bottom', '频率', 'Hz')self.freq_plot.setLogMode(False, True) # Y轴对数坐标self.freq_plot.addLegend()self.freq_curve_original = self.freq_plot.plot(pen='b', name='原始频谱')self.freq_curve_filtered = self.freq_plot.plot(pen='r', name='滤波后频谱')self.cutoff_line = pg.InfiniteLine(angle=90, movable=False, pen='g')self.freq_plot.addItem(self.cutoff_line)plot_layout.addWidget(self.time_plot, 1)plot_layout.addWidget(self.freq_plot, 1)main_layout.addWidget(control_panel)main_layout.addWidget(plot_widget, 1)# 设置定时器用于自动更新self.timer = QTimer()self.timer.timeout.connect(self.update_plots)self.timer.start(100) # 每100ms更新一次def on_cutoff_changed(self, value):"""滑块值改变时的处理"""self.cutoff_freq = valueself.cutoff_spinbox.setValue(value)self.update_plots()def on_cutoff_spinbox_changed(self, value):"""微调框值改变时的处理"""self.cutoff_freq = valueself.cutoff_slider.setValue(int(value))self.update_plots()def on_order_changed(self, value):"""滤波器阶数改变时的处理"""self.filter_order = valueself.update_plots()def on_std_changed(self, value):"""标准差改变时的处理"""self.std_dev = valueself.update_plots()def on_generate_clicked(self):"""重新生成噪声按钮点击处理"""self.generator.generate_noise(std_dev=self.std_dev)self.update_plots()def on_auto_update_toggled(self, checked):"""自动更新切换处理"""if checked:self.timer.stop()self.auto_update_cb.setText("开始自动更新")else:self.timer.start(100)self.auto_update_cb.setText("暂停自动更新")def update_plots(self):"""更新图表显示"""# 生成新噪声(如果还没有)if self.generator.noise is None:self.generator.generate_noise(std_dev=self.std_dev)# 应用滤波器filtered = self.generator.apply_filter(self.cutoff_freq, self.filter_order)# 计算频谱freqs_orig, spec_orig = self.generator.compute_spectrum(self.generator.noise)freqs_filt, spec_filt = self.generator.compute_spectrum(filtered)# 更新时域图self.time_curve_original.setData(self.generator.t, self.generator.noise)self.time_curve_filtered.setData(self.generator.t, filtered)# 更新频域图self.freq_curve_original.setData(freqs_orig, spec_orig)self.freq_curve_filtered.setData(freqs_filt, spec_filt)self.cutoff_line.setValue(self.cutoff_freq)# 设置频域图显示范围self.freq_plot.setXRange(0, 500000)# 更新窗口标题显示统计信息orig_std = np.std(self.generator.noise)filt_std = np.std(filtered)power_ratio = (filt_std / orig_std) ** 2self.setWindowTitle(f"高斯白噪声低通滤波器 | "f"截止频率: {self.cutoff_freq}Hz | "f"输入功率: {orig_std**2:.3f} | "f"输出功率: {filt_std**2:.3f} | "f"功率比: {power_ratio:.3f}")def main():# 设置pyqtgraph样式pg.setConfigOption('background', 'w')pg.setConfigOption('foreground', 'k')window = MainWindow()window.show()sys.exit(app.exec_())if __name__ == "__main__":main()