信号处理学习笔记4:动态调整系数的一阶低通滤波

动态调整 K,就是为了打破固定系数 "平稳与灵敏度不可兼得" 的矛盾
动态K的运用 不存在于 高通滤波中(目标相反,不能混用!

动态 K 要 "稳变化、跟平稳" 高通要 "留变化、去平稳"
动态 K 是为了 "稳",高通是为了 "抓变";

一个要静,一个要动,天生不能一起用。

目录

为何要动态调整系数K:

动态K滤波原理:

[1. 趋势计数(dir_cnt)](#1. 趋势计数(dir_cnt))

[2. 变化幅度(diff)](#2. 变化幅度(diff))

[3.这两参数,直接影响 K 的变化率](#3.这两参数,直接影响 K 的变化率)

C代码:

python绘图结果:


为何要动态调整系数K:

因为固定 K 永远做不到:既不抖动、又不滞后、又能跟趋势!

  • K 太大 → 反应快,但毛刺、抖动压不住
  • K 太小 → 很平稳,但严重滞后、跟不上真实变化
  • 无论怎么调,只能二选一,无法兼顾

动态 K = 让滤波自己变聪明,该稳就稳、该快就快。

动态 K 做了一件固定 K 做不到的事:

  1. 数据稳定 / 抖动时

K 自动变小 → 输出纹丝不动,抗干扰极强

  1. 数据持续上涨 / 下跌(真实趋势)

K 自动变大 → 输出立刻跟上,不滞后、不拖尾

  1. 数据快速跳变

K 加速变大

动态K滤波原理:

动态 K 滤波对比固定(静态)K 一阶滤波 ,核心是增加了对滤波系数 K 的动态调整逻辑模块
动态 K 滤波 对比 静态 K 滤波,核心就多了两个东西:

1. 趋势计数(dir_cnt)

判断是不是连续涨 / 连续跌 → 决定 K 要不要开始变大

2. 变化幅度(diff)

判断变化大不大 → 决定 K 变大的速度有多快

3.这两参数,直接影响 K 的变化率

① 改 趋势计数

dir_cnt > 1K 启动更快

dir_cnt > 3K 启动更慢

② 改 变化幅度判断

diff > 0.2 → 稍微一动就加速 K

diff > 1.0 → 必须很大变化才加速 K

③ 改 K 增加的步长

K += 0.25K 涨得飞快

K += 0.05K 涨得很慢

cpp 复制代码
    float diff = now_val - last_out;    // 当前值与滤波输出差值
    int is_same_dir;

    // 判断:本次变化 和 上一次变化 是否【同向】
    is_same_dir = ((now_val > last_out) && (last_val > last_out)) ||
                  ((now_val < last_out) && (last_val < last_out));

    // ==================== 动态调整 K ====================
    if (is_same_dir)
    {
        dir_cnt++;  // 同向 = 真实趋势,加速响应
        if (dir_cnt > 1)// 判断数据变化幅度:变化大则K多涨,变化小则K少涨
        {
            K += (diff > 0.5f || diff < -0.5f) ? 0.15f : 0.05f;
        }
    }
    else
    {
        dir_cnt = 0;    // 抖动/反向 = 防抖
        K = 0.1f;       // 系数重置变小
    }

    // K 限制范围(防止太灵敏/太迟钝)
    if (K > 0.8f)  K = 0.8f;
    if (K < 0.05f) K = 0.05f;

C代码:

cpp 复制代码
#include <stdio.h>

// ==================== 动态滤波核心参数 ====================
float last_out  = 0.0f;   // 上一次滤波输出
float last_val  = 0.0f;   // 上一次原始值
float K         = 0.1f;   // 初始系数(会自动变)
int   dir_cnt   = 0;      // 同向趋势计数

// 初始化
void dynamic_filter_init(float val)
{
    last_out = val;
    last_val = val;
    K = 0.1f;
    dir_cnt = 0;
}

// ==================== 动态K一阶滤波(核心函数) ====================
float dynamic_filter(float now_val)
{
    float diff = now_val - last_out;    // 当前值与滤波输出差值
    int is_same_dir;

    // 判断:本次变化 和 上一次变化 是否【同向】
    is_same_dir = ((now_val > last_out) && (last_val > last_out)) ||
                  ((now_val < last_out) && (last_val < last_out));

    // ==================== 动态调整 K ====================
    if (is_same_dir)
    {
        dir_cnt++;  // 同向 = 真实趋势,加速响应
        if (dir_cnt > 1)// 判断数据变化幅度:变化大则K多涨,变化小则K少涨
        {
            K += (diff > 0.5f || diff < -0.5f) ? 0.15f : 0.05f;
        }
        /*  
            K += (diff > 0.5f || diff < -0.5f) ? 0.15f : 0.05f;
            等效的if else 语句如下:
            if (diff > 0.5f || diff < -0.5f)
            {
                K = K + 0.15f;  // 变化幅度大(快速趋势/跳变),K猛加,提升灵敏度
            }
            else
            {
                K = K + 0.05f;  // 变化幅度小(平稳慢变),K少加,保持平稳性
            }
        */
    }
    else
    {
        dir_cnt = 0;    // 抖动/反向 = 防抖
        K = 0.1f;       // 系数重置变小
    }

    // K 限制范围(防止太灵敏/太迟钝)
    if (K > 0.8f)  K = 0.8f;
    if (K < 0.05f) K = 0.05f;

    // ==================== 一阶滤波公式 ====================
    float out = K * now_val + (1.0f - K) * last_out;

    // 更新历史值
    last_val = now_val;
    last_out = out;

    return out;
}

// ==================== 测试(用50个趋势+毛刺数据) ====================
int main(void)
{
    // 你的50个带趋势+毛刺数据
    float data[50] = {
    10.00,10.05,99.90,10.10,10.15,
    10.20,10.25,88.80,10.30,10.35,
    10.40,10.45,77.70,10.50,10.55,
    10.60,10.65,66.60,10.70,10.75,
    10.80,10.85,55.50,10.90,10.95,
    11.00,11.10,44.40,11.15,11.20,
    11.25,11.30,33.30,11.35,11.40,
    11.50,11.60,22.20,11.70,11.80,
    11.90,12.00,12.05,12.10,12.15,
    12.20,12.30,12.35,12.40,12.50
    };

    dynamic_filter_init(data[0]);

    printf("序号\t原始数据\t动态滤波输出\n");
    printf("-----------------------------------------\n");

    for(int i=0; i<50; i++)
    {
        float res = dynamic_filter(data[i]);
        printf("%2d\t%.2f\t\t%.2f\n", i+1, data[i], res);
    }

    return 0;
}

python绘图结果:

相关推荐
中屹指纹浏览器2 小时前
2026多账号运维中的指纹标准化治理与平台风控适配研究
经验分享·笔记
繁星星繁2 小时前
Python基础语法(一)
c++·笔记·python
前端飞行手册2 小时前
electron应用开发模板,集成多种解决方案
前端·javascript·学习·electron·前端框架·vue
NULL指向我2 小时前
信号处理学习笔记3:限幅 + 中值 + 一阶 RC 三合一
学习·信号处理
NULL指向我2 小时前
信号处理学习笔记1:软件RC一阶高通\低通滤波
学习
NPUQS3 小时前
【Unity 3D学习】Unity 与 Python 互通入门:点击按钮调用 Python(超简单示例)
学习·3d·unity
电子云与长程纠缠10 小时前
Godot学习05 - 播放与分离FBX动画
学习·游戏引擎·godot
蒸蒸yyyyzwd10 小时前
day3学习笔记
笔记·学习
red_redemption12 小时前
自由学习记录(143)
学习