常见滤波算法(Python&C版本)

简介

受限于MCU自身的ADC外设缺陷,精度和稳定性通常较差,很多场景下需要用滤波算法进行补偿。滤波的主要目的是减少噪声与干扰对数据的影响,让数据更加接近真实值。

一阶低通滤波

一阶低通滤波是一种信号处理技术,用于去除信号中高频部分,保留低频部分。在滤波过程中,一阶低通滤波器会使得高于某个截止频率的信号被衰减,而低于截止频率的信号则会被保留。这有助于减少噪音或者不需要的信号成分,从而提高信号的质量。

**典型案例:**蓝牙耳机、音响

Python实现

python 复制代码
import numpy as np
import matplotlib.pyplot as plt
# 生成示例数据
sensor_data = np.random.randn(200) # 正态分布随机数据
# 定义低通滤波函数
def low_pass_filter(data,cutoff_freq):
    filtered_data = np.copy(data)
    for i in range(1,len(data)):
        filtered_data[i] = (1-cutoff_freq)*filtered_data[i-1]+cutoff_freq*data[i]
    return filtered_data
# 设置截止频率
cutoff_freq = 0.2
# 应用低通滤波
filter_sensor_data = low_pass_filter(sensor_data,cutoff_freq)
# 绘制原始数据和滤波后数据
plt.figure(figsize=(10,6))
plt.plot(sensor_data)
plt.plot(filter_sensor_data)
plt.show()

C实现

均值滤波

**说明:**连续取N个采样值进行算术平均运算达到降噪目的;

N值较大时:信号平滑度较高,但灵敏度较低

N值较小时:信号平滑度较低,但灵敏度较高

**优点:**试用于对一般具有随机干扰的信号进行滤波。这种信号的特点是有一个平均值,信号在某一数值范围附近上下波动。

**缺点:**测量速度较慢或要求数据计算较快的实时控制不适用。

**典型案例:**电子秤...

Python实现

python 复制代码
import numpy as np
import matplotlib.pyplot as plt 
# 生成模拟示例数据
sensor_data = np.random.randn(200) # 正态分布随机数据
m = 0 # 起始角标
n = 11 # 在多少个数中取中间值,必须为奇数
def average_filter(data):
    global m,n
    data = sensor_data[m:m+n]
    m +=n
    value = np.average(data)
    return value

filter_sensor_data = np.zeros_like(sensor_data)

for i in range(0, len(sensor_data),n):
    filter_sensor_data[i] = average_filter(sensor_data)
    
# 绘制原始数据和滤波后数据
plt.figure(figsize=(10,6))
plt.plot(sensor_data,c="green")
plt.plot(filter_sensor_data,c="red")
plt.show()

C实现

滑动平均滤波

**说明:**把连续取N个采样值看成一个队列,队列的长度固定为N。每次采样到一个新数据放入队尾,并扔掉原来队首的一次数据(先进先出原则)。把队列中的N个数据进行算术平均运算,就可获得新的滤波结果。

**N值的选取:**流量,N=12;压力:N=4;液面,N=4~12;温度,N=1~4

**优点:**对周期性干扰有良好的抑制作用,平滑度高;试用于高频振荡的系统

**缺点:**灵敏度低;对偶然出现的脉冲性干扰的抑制作用较差,不适于脉冲干扰较严重的场合比较浪费RAM(改进方法,减去的不是队首的值,而是上一次得到的平均值)

**典型应用:**汽车上剩余可行驶里程预估

Python实现

python 复制代码
import numpy as np
import matplotlib.pyplot as plt

sensor_data = np.random.randn(200)
n = 11
filter_sensor_data = np.zeros_like(sensor_data)
for i in range(1,len(sensor_data)):
    if i<n:
        temp_data = sensor_data[0:i]
        value = np.average(temp_data)
        filter_sensor_data[i] = value
    else:
        temp_data = sensor_data[i-n:i]
        value = np.average(temp_data)
        filter_sensor_data[i] = value
plt.figure(figsize=(10,6))
plt.plot(sensor_data,c="green")
plt.plot(filter_sensor_data,c="red")
plt.show()

C实现

中值滤波

**说明:**连续采样N次(N取奇数)把N次采样值按大小排列取中间值为本次有效值

**优点:**能有效克服因偶然因素引起的波动干扰;对温度、液位等变化缓慢的被测参数有良好的滤波效果

**缺点:**对流量,速度等快速变化的参数不宜。

**典型应用:**电子秤....

Python实现

python 复制代码
import numpy as np
import matplotlib.pyplot as plt
# 生成模拟数据
sensor_data = np.random.randn(200) # 正态分布随机数据

# 起始角标
m = 0
n = 11 # 在多少个数中取中间值,必须为奇数

# 定义中值滤波算法
def middle_filter(data):
    global m,n
    data = sensor_data[m:m+n]
    m += n
    data2 = sorted(data)
    # 取中间值
    middle_index = int(len(data2)/2)
    value = data2[middle_index]
    return value
filter_sensor_data = np.ones_like(sensor_data)
# 绘制原始数据和滤波后数据
for i in range(0,len(sensor_data),n):
    filter_sensor_data[i] = middle_filter(sensor_data)
plt.figure(figsize=(10,6))
plt.plot(sensor_data,c="blue")
plt.plot(filter_sensor_data,c="red")
plt.show()

C实现

卡尔曼滤波

**说明:**根据当前的仪器"测量值" 和上一刻的 "预测量" 和 "误差",计算得到当前的最优量,再预测下一刻的量。里面比较突出的是观点是:把误差纳入计算,而且分为预测误差和测量误差两种,通称为噪声。还有一个非常大的特点是:误差独立存在,始终不受测量数据的影响。

**优点:**巧妙的融合了观测数据与估计数据,对误差进行闭环管理,将误差限定在一定范围。适用性范围很广,时效性和效果都很优秀。

**缺点:**需要调参,参数的大小对滤波的效果影响较大。

**典型应用:**卫星轨迹预测、火箭发射、无人机与机器人运动控制....

Python实现

python 复制代码
class KalmanFilter:
    def __init__(self,q=0.001,r=0.001) -> None:
        self.q = q # 过程噪声协方差
        self.r = r # 测量噪声协方差
        self.p = 5 # 估计误差协方差
        self.k_gain = 0 #卡尔曼增益
        self.prev_data = 0 # 先前数据值
    def updata(self,measurement):
        # 预测
        self.p +=self.q
        # 计算卡尔曼增益
        self.k_gain = self.p/(self.p+self.r)
        # 更新估计值
        estimation = self.prev_data + self.k_gain*(measurement-self.prev_data)
        # 更新估计误差协方差
        self.p = (1-self.k_gain)* self.p
        # 更新先前数据值
        self.prev_data = estimation
        return estimation

# 测试
kf = KalmanFilter()
input_data = 5
filter_data = kf.updata(input_data)
print(f"滤波后:filter_data")

import numpy as np
import matplotlib.pyplot as plt
sensor_data = np.random.randn(200)
n = 11
filter_sensor_data = np.zeros_like(sensor_data)
for i in range(1,len(sensor_data)):
    src_data = sensor_data[i]
    filter_sensor_data[i] = kf.updata(src_data)
    
plt.figure(figsize=(10,6))
plt.plot(sensor_data,c="green")
plt.plot(filter_sensor_data,c="red")
plt.show()

C实现

相关推荐
m0_747124536 分钟前
基于 RK3568 / IMX6ULL / STM32MP157 的智能车载系统
嵌入式硬件·qt·车载系统
君秋水11 分钟前
FastAPI教程:20个核心概念从入门到 happy使用
后端·python·程序员
lizz3124 分钟前
机器学习中的线性代数:奇异值分解 SVD
线性代数·算法·机器学习
试着生存25 分钟前
java根据List<Object>中的某个属性排序(数据极少,顺序固定)
java·python·list
MSTcheng.29 分钟前
【C语言】动态内存管理
c语言·开发语言·算法
热心市民小汪30 分钟前
管理conda下python虚拟环境
开发语言·python·conda
不去幼儿园33 分钟前
【启发式算法】Dijkstra算法详细介绍(Python)
人工智能·python·算法·机器学习·启发式算法·图搜索算法
McQueen_LT39 分钟前
聊天室Python脚本——ChatGPT,好用
开发语言·python·chatgpt
serve the people42 分钟前
神经网络中梯度计算求和公式求导问题
神经网络·算法·机器学习
闻缺陷则喜何志丹1 小时前
【二分查找、滑动窗口】P10389 [蓝桥杯 2024 省 A] 成绩统计|普及+
c++·算法·蓝桥杯·二分查找·滑动窗口·洛谷·成绩