数据平滑处理 数据滤波

从传感器读回来的数据,波动比较大。除了用一个队列,比如设置队列大小为128 , 当队列满时候求得一个平均值,再不停的出队一个元素,进队一个元素,再求队列中128个元素的平均值。再出队,进队, 求平均 ... 还有别的方法来平滑这段数据,或者滤波把高频的给滤掉,只保留10HZ以下频率。
数据在百度网盘 ,

链接:https://pan.baidu.com/s/15MBlVGYABF6DSj6Dwct8ZQ?pwd=7gvh
提取码:7gvh

图一

img

图二

运行结果

img

以下答案由GPT-3.5大模型与博主波罗歌共同编写:
对于数据的平滑处理,还有其他的方法可以使用,比如:

  1. 中值滤波(Median Filter):将数据按照大小排列,然后取中间值作为滤波器输出。相对于均值滤波,中值滤波对于离群值的影响较小,但会丢失部分信息。

  2. 加权平均滤波:不同的数据赋予不同的权重,加权平均后得到平滑后的数据。可以使用指数加权平均或移动平均来平滑数据。

  3. 卡尔曼滤波(Kalman Filter):利用系统的动力学模型和观测模型来预测并校正状态变量,能够对非线性系统进行滤波。

对于滤波去除高频信号的方法,可以使用低通滤波器。常用的低通滤波器包括:

  1. 一阶低通滤波器:使用一阶差分方程,可以实现对信号的平滑处理。

  2. 二阶低通滤波器:使用二阶差分方程,可以实现对信号的二次平滑处理。比一阶低通滤波器更加平滑。

  3. 巴特沃斯低通滤波器:可以实现对信号的平滑处理,并且在通频带内的衰减最小。

以下是使用Python实现队列平滑滤波的示例代码:

from collections import deque

# 读取数据文件
with open('data.txt') as f:
    lines = f.readlines()
    data = [float(line.strip()) for line in lines]

# 定义滤波窗口大小和队列
window_size = 128
queue = deque(maxlen=window_size)

# 定义输出数据和滤波结果列表
output = []
result = []

# 遍历数据进行平滑处理
for i in range(len(data)):
    # 将数据放入队列
    queue.append(data[i])
    # 如果队列满,计算平均值并添加到输出列表
    if len(queue) == window_size:
        avg = sum(queue) / window_size
        output.append(avg)
    # 如果队列未满,将当前值添加到输出列表
    else:
        output.append(data[i])
    # 在输出列表末尾添加原始数据和滤波结果
    result.append([data[i], output[-1]])

# 将滤波结果列表写入文件
with open('result.txt', 'w') as f:
    for r in result:
        f.write(str(r[0]) + '\t' + str(r[1]) + '\n')

另外,对于滤波去除高频信号的方法,可以使用Python中提供的信号处理库scipy.signal中的低通滤波函数lfilter进行实现。以下是示例代码:

import numpy as np
from scipy import signal

# 读取数据文件
with open('data.txt') as f:
    lines = f.readlines()
    data = [float(line.strip()) for line in lines]

# 定义滤波器参数
order = 5
cutoff_freq = 10 # 单位为Hz
sampling_freq = 1000 # 单位为Hz

# 计算数字滤波器的系数
nyq_freq = 0.5 * sampling_freq
normal_cutoff = cutoff_freq / nyq_freq
b, a = signal.butter(order, normal_cutoff, btype='low', analog=False)

# 使用数字滤波器进行滤波
filtered_data = signal.lfilter(b, a, data)

# 将滤波结果列表写入文件
with open('result.txt', 'w') as f:
    for i in range(len(data)):
        f.write(str(data[i]) + '\t' + str(filtered_data[i]) + '\n')

以上两个示例代码分别演示了使用队列平滑滤波和使用低通滤波器进行滤波的方法。需要根据实际情况选择适合的方法。
如果我的回答解决了您的问题,请采纳!

可以借鉴下
https://blog.csdn.net/weixin_29002191/article/details/112581694

为了平滑处理传感器数据并滤除高频噪声,可以使用滑动窗口平均滤波方法。该方法基于队列的思想,通过计算窗口内数据的平均值来平滑数据,并保留低于10Hz的频率成分。

以下是使用Python实现滑动窗口平均滤波的示例代码:

python

import pandas as pd
import numpy as np

# 读取CSV文件
data = pd.read_csv('your_data.csv')
sensor_data = data['data'].values

# 定义滑动窗口大小和阈值
window_size = 128
threshold = 10

# 初始化队列和平滑后的数据列表
data_queue = []
smoothed_data = []

# 定义滑动窗口平均滤波函数
def sliding_average_filter(data, window_size):
    data_queue.append(data)
    if len(data_queue) > window_size:
        data_queue.pop(0)
    if len(data_queue) == window_size:
        average = sum(data_queue) / window_size
        return average
    return None

# 进行滑动窗口平均滤波
for value in sensor_data:
    smoothed_value = sliding_average_filter(value, window_size)
    if smoothed_value is not None:
        smoothed_data.append(smoothed_value)

# 输出滤波后的数据
print(smoothed_data)

在上述代码中,首先读取CSV文件中的传感器数据,并将其存储在sensor_data数组中。然后,定义了滑动窗口的大小和频率阈值。

接下来,定义了一个sliding_average_filter函数,用于实现滑动窗口平均滤波。该函数将数据依次加入队列,当队列长度超过窗口大小时,将队列中最早的数据移除。当队列长度等于窗口大小时,计算队列中数据的平均值,并返回该平均值作为平滑后的数据。如果队列长度小于窗口大小,则返回None。

然后,通过遍历传感器数据数组,依次将数据输入滑动窗口平均滤波函数,并将返回的平滑数据存储在smoothed_data列表中。

最后,输出滤波后的数据。

我可以提供一些建议来平滑处理或滤波处理从传感器读取的数据,以降低数据波动:

  1. 移动平均滤波器:最简单的办法是使用移动平均滤波器,该方法可以有效消除高频变化,让我们看到数据更大的一个趋势。在matlab中,可以使用movmean函数实现。

  2. 巴特沃斯滤波器:巴特沃斯滤波器是一种常用的数字滤波器,可以通过选择合适的参数来实现去除高频的目的。在matlab中,可以使用butter函数设计巴特沃斯滤波器,使用filtfilt函数将设计好的滤波器应用于原始数据上。

  3. 中值滤波器:如果需要去除尖峰点,可以使用中值滤波,这种方法是非线性的,能很好地滤除信号中的剧烈波动。在matlab中,可以使用medfilt1函数实现。

综合上述方法,可以将巴特沃斯滤波器和移动平均滤波器结合使用,实现将高频率数据滤除,只保留10Hz以下频率的数据。具体操作可以按照段落0中提到的“巴特沃斯-滑动平均混合滤波”处理过程进行,也可以根据实际需求进行调整。

除了您提到的队列方法外,还有其他常用的滤波器用于平滑数据和去除噪声。这里推荐两种常用的滤波方法:滑动平均滤波器(Moving Average Filter)和低通滤波器(Low-pass Filter)。

  1. 滑动平均滤波器(Moving Average Filter):

滑动平均滤波器是一种简单的滤波方法,它通过计算数据窗口内的平均值来平滑数据。您提到的队列方法实际上就是一种滑动平均滤波器。除了计算固定窗口大小的平均值外,还可以使用加权滑动平均方法,使窗口内的数据按照权重进行平均。加权滑动平均可以更好地适应数据的波动。

例如,假设数据窗口大小为 N,权重矩阵为 W,则加权滑动平均值为:

filtered_value = (data[i-N+1] * W[1] + data[i-N+2] * W[2] + ... + data[i] * W[N]) / sum(W)

  1. 低通滤波器(Low-pass Filter):

低通滤波器用于去除高频噪声,保留低频成分。常见的低通滤波器有无限冲激响应(IIR)滤波器和有限冲激响应(FIR)滤波器。这里以一阶 IIR 低通滤波器为例:

filtered_value = alpha * previous_filtered_value + (1 - alpha) * current_value

其中,alpha 是滤波器系数,它决定了滤波器的截止频率。alpha 越小,滤波器的截止频率越低,平滑程度越高。previous_filtered_value 是上一个滤波后的值,current_value 是当前数据值。

以下是一个简单的一阶 IIR 低通滤波器的 Python 代码实现:

def low_pass_filter(data, alpha=0.1):
    filtered_data = [data[0]]
    for i in range(1, len(data)):
        filtered_value = alpha * filtered_data[-1] + (1 - alpha) * data[i]
        filtered_data.append(filtered_value)
    return filtered_data

您可以根据数据特点和需求选择合适的滤波方法。

根据您提供的数据和您的描述,猜测您选择的采样频率是128Hz。
您所说的方法实际上就是滑动平均滤波方法。
那么我使用一阶惯性环节作为低通滤波器对您的数据进行滤波,仅作参考。
令输入为x(k),输出为y(k)
传递函数为 G = wc/(s+wc)
使用双线性变换,s= 2(z-1)/(T(z+1))。整理得到
y(k) = (2-Twc)/(2+Twc)y(k-1) + Twc/(2+Twc)(x(k) + x(k-1))
可以根据上式编写代码进行滤波。
取截至频率为20Hz,则wc = 40pi,采样频率为fs = 128Hz,T = 1/fs。
matlab的实现代码如下(已省去数据过程)

fs = 128
T = 1/fs;
x = data.data;
wc = 20*2*pi;
y = zeros(size(x));
for k = 2:length(x)
    y(k) = (2-T*wc)/(2+T*wc)*y(k-1) + T*wc/(2+T*wc)*(x(k) + x(k-1));
end
plot(data.t,y)

滤波结果如下

img

单一阶惯性环节的相移比较严重。您可以选择其他类型的滤波器进行滤波。
希望我的回答能对您有所帮助。
如果您希望了解更多的滤波器设计只是,可以私聊我或者另行查阅资料。