C/C++编程-算法学习-数字滤波器

news2025/2/25 12:24:36

数字滤波器

  • 一阶低通滤波器
    • 结论
    • 推导1
      • 1. 基本公式推导
      • 2. 截止频率 和 采样频率 推导
    • 实现
  • 二阶低通滤波器
    • 实现1
    • 实现2
    • 推导1
    • 推导2

一阶低通滤波器

结论

其基本原理基于以下公式:
o u t p u t [ n ] = α ∗ i n p u t [ n ] + ( 1 − α ) ∗ o u t p u t [ n − 1 ] output[n] = α * input[n] + (1 - α) * output[n - 1] output[n]=αinput[n]+(1α)output[n1]

  • output[n] 是当前的输出值
  • input[n] 是当前的输入值
  • α是滤波系数,取值范围在 0 到 1 之间。α值越大,对输入的响应越迅速,但滤波效果相对较弱;α值越小,滤波效果越强,但对输入的响应越慢
  • output[n - 1] 是上一次的输出值
    例如,如果 alpha = 0.1,输入值在短时间内快速变化,由于 (1 - alpha) 的权重较大,上一次的输出值对当前输出值的影响较大,从而起到平滑和抑制高频变化的作用。

推导1

1. 基本公式推导

对应电路模型一阶RC滤波器
Y ( s ) / X ( s ) = H ( s ) = 1 r c s + 1 = 1 r ⋅ j w c + 1 = 1 τ s + 1 Y(s)/X(s)=H(s) = \frac{1}{rcs +1} = \frac{1}{r·jwc + 1} =\frac{1}{\tau s + 1} Y(s)/X(s)=H(s)=rcs+11=rjwc+11=τs+11
在自控中称为一阶惯性环节
转成时域方程
X ( s ) = Y ( s ) / H ( s ) = Y ( s ) ( τ s + 1 ) X(s) = Y(s)/H(s) = Y(s)(\tau s +1) X(s)=Y(s)/H(s)=Y(s)(τs+1)
x ( t ) = τ y ′ ( t ) + y ( t ) x(t) = \tau y'(t) + y(t) x(t)=τy(t)+y(t)
将导数拆开(使用一阶后向差分法,对上面微分方程进行离散化)
x ( t ) = τ ( y ( t ) − y ( t − T ) T ) + y ( t ) x(t) = \tau (\frac {y(t) - y(t-T)}{T}) + y(t) x(t)=τ(Ty(t)y(tT))+y(t)
整理成可递归迭代函数
y ( t ) = ( 1 − T T + τ ) ⋅ y ( t − T ) + T T + τ x ( t ) y(t) = (1-\frac {T}{T+\tau})·y(t-T) + \frac{T}{T+\tau}x(t) y(t)=(1T+τT)y(tT)+T+τTx(t)
a = T T + τ a = \frac{T}{T+\tau} a=T+τT 则可得一般表达式
y ( t ) = ( 1 − a ) y ( t − T ) + a x ( t ) y(t) = (1-a)y(t-T)+ax(t) y(t)=(1a)y(tT)+ax(t)

2. 截止频率 和 采样频率 推导

从模电课本即可知,截止频率处幅值衰减-3db。

f c = 1 2 π R C = 1 2 π τ f_c = \frac{1}{2\pi RC} = \frac{1}{2\pi \tau} fc=2πRC1=2πτ1
τ = 1 2 π f c \tau = \frac{1}{2\pi f_c} τ=2πfc1带入滤波器系数 a a a 可得:
a = T T + τ = 1 1 + f 2 π f c a = \frac{T}{T+ \tau} = \frac{1}{1+\frac{f}{2\pi f_c}} a=T+τT=1+2πfcf1
其中, f = 1 T f = \frac{1}{T} f=T1为采样频率。

实现

#include <stdio.h>
#include <stdlib.h>

// 一阶低通滤波器函数
float lowPassFilter(float input, float prevOutput, float alpha) {
    return alpha * input + (1 - alpha) * prevOutput;
}

int main() {
    float input = 10.0;  // 输入值
    float prevOutput = 5.0;  // 上一次的输出值
    float alpha = 0.2;  // 滤波系数

    for(int i=0; i<20; i++)
    {
        float output = lowPassFilter(input, prevOutput, alpha);

        prevOutput = output;

        printf("filter current result: %f\n", output);
    }

    system("pause");
    return 0;
}

运行结果
在这里插入图片描述

二阶低通滤波器

实现1

#include <stdio.h>
// #include </lib/gcc/x86_64-linux-gnu/9/math.h>
#include <math.h>

// 二阶低通滤波器参数
#define SAMPLING_FREQ 1000  // 采样频率
#define CUTOFF_FREQ 100  // 截止频率

// 计算滤波器系数
void calculateFilterCoefficients(double *a, double *b) {
    double omega = 2 * M_PI * CUTOFF_FREQ / SAMPLING_FREQ;
    double alpha = sin(omega) / (2 * 0.707);
    double beta = cos(omega);

    double a0 = 1 + alpha;
    double a1 = -2 * beta;
    double a2 = 1 - alpha;

    double b0 = (1 - beta) / 2;
    double b1 = 1 - beta;
    double b2 = (1 - beta) / 2;

    *a = a0;
    *(a + 1) = a1;
    *(a + 2) = a2;

    *b = b0;
    *(b + 1) = b1;
    *(b + 2) = b2;
}

// 二阶低通滤波函数
double lowPassFilter(double input, double *prevInputs, double *prevOutputs, double *a, double *b) {
    double output = *b * input + *b * prevInputs[0] + *b * prevInputs[1] - *a * prevOutputs[0] - *a * prevOutputs[1];

    prevInputs[1] = prevInputs[0];
    prevInputs[0] = input;

    prevOutputs[1] = prevOutputs[0];
    prevOutputs[0] = output;

    return output;
}

int main() {
    double a[3], b[3];
    calculateFilterCoefficients(a, b);

    double prevInputs[2] = {0};
    double prevOutputs[2] = {0};

    double input = 10;  // 输入值,可根据实际情况修改
    double filteredOutput = lowPassFilter(input, prevInputs, prevOutputs, a, b);

    printf("滤波后的输出: %f\n", filteredOutput);

    return 0;
}



/**
如果你在使用gcc编译含数学函数的 C 程序时,出现undefined reference to 'sin'、undefined reference to 'cos'等错误,一般是由于缺少库造成的。因为在 Ubuntu 系统中,gcc的数学函数(如sin、cos等)是定义在libm.so里面的,而数学库不在默认路径下。通过添加-lm选项,就可以告诉编译器到正确的库中查找这些函数。

注意:在使用cmake进行编译时,需要添加命令target_link_libraries(your_target_name m)来链接数学库,其中your_target_name是你的目标名称。
*/

经我实际验证ubuntu20,的math库在如下路径
dpkg -l | grep math
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

实现2

#include <stdio.h>
#include <math.h>

// 二阶低通滤波器系数
typedef struct {
    double a0, a1, a2, b1, b2;
} FilterCoefficients;

// 计算二阶低通滤波器系数
void calculateFilterCoefficients(double cutoffFrequency, double samplingFrequency, FilterCoefficients *coefficients) {
    double omega = 2.0 * 3.14159 * cutoffFrequency / samplingFrequency;
    double cosOmega = cos(omega);
    double sinOmega = sin(omega);
    double alpha = sinOmega / (2.0 * 0.707);

    double a0 =  1 + alpha;
    double a1 = -2 * cosOmega;
    double a2 =  1 - alpha;
    double b1 = -2 * cosOmega;
    double b2 =  1 - alpha;

    coefficients->a0 = 1.0 / a0;
    coefficients->a1 = a1 / a0;
    coefficients->a2 = a2 / a0;
    coefficients->b1 = b1 / a0;
    coefficients->b2 = b2 / a0;
}

// 二阶低通滤波器函数
void secondOrderLowPassFilter(double input[], double output[], int length, FilterCoefficients coefficients) {
    output[0] = input[0];
    output[1] = coefficients.a0 * input[1] + coefficients.a1 * input[0] + coefficients.b1 * output[0];

    for (int i = 2; i < length; i++) {
        output[i] = coefficients.a0 * input[i] + coefficients.a1 * input[i - 1] + coefficients.a2 * input[i - 2]
                    - coefficients.b1 * output[i - 1] - coefficients.b2 * output[i - 2];
    }
}

int main() {
    double cutoffFrequency = 10.0;  // 截止频率
    double samplingFrequency = 50.0;  // 采样频率
    FilterCoefficients coefficients;

    calculateFilterCoefficients(cutoffFrequency, samplingFrequency, &coefficients);

    double input[] = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0};
    double output[10];
    int length = 10;

    secondOrderLowPassFilter(input, output, length, coefficients);

    for (int i = 0; i < length; i++) {
        printf("Output[%d] = %f\n", i, output[i]);
    }

    return 0;
}

实验结果:

在这里插入图片描述

推导1

二阶数字低通滤波器的时域上的开环传递函数为:
G ( s ) = w c 2 s 2 + 2 ξ w c s + w c 2 G(s) = \frac{w_c^2}{s^2+2\xi w_c s + w_c^2} G(s)=s2+2ξwcs+wc2wc2
其中 w c w_c wc是低通滤波器的截止频率, ξ \xi ξ为阻尼比。
采用双线性变换法 将 线性非时变系统 在 连续时域系统的传递函数 转换 成线性且平移不变滤波器 在 离散时域的传递函数。
双线性变换法: S = 2 T Z − 1 Z + 1 S = \frac{2}{T}\frac{Z-1}{Z+1} S=T2Z+1Z1
可得
G ( s ) = w c 2 T s w 2 ( z 2 + 2 z + 1 ) z 2 ( w c 2 T s w 2 + 4 ξ w c T s w + 4 ) + z ( 2 w c 2 T s w 2 − 8 ) + ( w c 2 T s w 2 − 4 ξ w c T s w + 4 ) G(s) = \frac{w_c^2T_{sw}^2(z^2+2z+1)}{z^2(w_c^2T_{sw}^2 + 4\xi w_cT_{sw}+4)+z(2w_c^2T_{sw}^2-8)+(w_c^2T_{sw}^2-4\xi w_c T_{sw} + 4)} G(s)=z2(wc2Tsw2+4ξwcTsw+4)+z(2wc2Tsw28)+(wc2Tsw24ξwcTsw+4)wc2Tsw2(z2+2z+1)

令系数为:
b 0 = w c 2 b_0 = w_c^2 b0=wc2
a 0 = 4 T 2 + 4 T ξ w c + w c 2 a_0 = \frac{4}{T^2 }+\frac{4}{T}\xi w_c +w_c^2 a0=T24+T4ξwc+wc2
a 1 = 2 w c 2 − 8 T 2 a_1 = 2w_c^2-\frac{8}{T^2} a1=2wc2T28
a 2 = w 2 − 2 ξ w c 2 T + 4 T 2 a_2 = w_2-2\xi w_c \frac{2}{T}+\frac{4}{T^2} a2=w22ξwcT2+T24
等效为:
b 0 = w c 2 T b_0 = w_c^2T b0=wc2T
a 0 = w c 2 T 2 + 4 ξ w c T + 4 a_0 = w_c^2T^2 + 4\xi w_c T + 4 a0=wc2T2+4ξwcT+4
a 1 = 2 w c 2 T 2 − 8 a_1 = 2w_c^2T^2 - 8 a1=2wc2T28
a 2 = w 2 T 2 − 4 ξ w c T + 4 a_2 = w_2T^2-4\xi w_c T+ 4 a2=w2T24ξwcT+4

根据Z变换的时移性质
分母: Y ( n − 1 ) Y ( n ) = z − 1 \frac {Y(n-1)}{Y(n)} = z^{-1} Y(n)Y(n1)=z1, Y ( n − 2 ) Y ( n ) = z − 2 \frac{Y(n-2)}{Y(n)} = z^{-2} Y(n)Y(n2)=z2;
分子: X ( n − 1 ) X ( n ) = z − 1 \frac{X(n-1)}{X(n)} = z^{-1} X(n)X(n1)=z1 X ( n − 2 ) X ( n ) = z − 2 \frac{X(n-2)}{X(n)} = z^{-2} X(n)X(n2)=z2;
进一步可得:
Y ( n ) = b 0 X ( n ) + b 1 X ( n − 1 ) + b 2 X ( n − 2 ) − a 1 Y ( n − 1 ) − a 2 Y ( n − 2 ) a 0 Y(n) = \frac {b_0X(n) + b_1X(n-1) + b_2X(n-2)-a_1Y(n-1)-a_2Y(n-2)}{a_0} Y(n)=a0b0X(n)+b1X(n1)+b2X(n2)a1Y(n1)a2Y(n2)

其中, T s w T_{sw} Tsw为数据采样频率周期, ξ \xi ξ为阻尼比,取值0.707, w c = 2 π f c w_c = 2\pi f_c wc=2πfc (截止频率)

推导2

【推导方法1】
【推导方法2】

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1960304.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

(Arxiv-2023)MobileDiffusion:移动设备上即时文本到图像生成

MobileDiffusion&#xff1a;移动设备上即时文本到图像生成 Paper Title&#xff1a;MobileDiffusion: Instant Text-to-Image Generation on Mobile Devices Paper是谷歌出品 Paper地址 图 1&#xff1a;MobileDiffusion 用于 (a) 文本到图像的生成。(b) Canny 边缘到图像、风…

认证授权概述和SpringSecurity安全框架快速入门

1. 认证授权的概述 1.1 什么是认证 进入移动互联网时代&#xff0c;大家每天都在刷手机&#xff0c;常用的软件有微信、支付宝、头条、抖音等 以微信为例说明认证的相关基本概念。在初次使用微信前需要注册成为微信用户&#xff0c;然后输入账号和密码即可登录微信&#xff0c…

完成stable将图片转换为二维码

1.创建虚拟环境 conda create -n stable python=3.10.6 2.克隆项目 git clone https://github.com/AUTOMATIC1111/stable-diffusion-webui 或者 git clone https://kgithub.com/AUTOMATIC1111/stable-diffusion-webui 3.安装依赖(-i https://pypi.tuna.tsinghua.edu.cn/s…

C++基础编程100题-028 OpenJudge-1.4-08 判断一个数能否同时被3和5整除

更多资源请关注纽扣编程微信公众号 http://noi.openjudge.cn/ch0104/08/ 描述 判断一个数n 能否同时被3和5整除 输入 输入一行&#xff0c;包含一个整数n。&#xff08; -1,000,000 < n < 1,000,000&#xff09; 输出 输出一行&#xff0c;如果能同时被3和5整除输…

八股文-基础知识-int和Integer有什么区别?

引言 在Java编程实践中&#xff0c;基本数据类型int与包装类Integer扮演着不可或缺的角色&#xff0c;它们间的转换与使用策略深刻影响着程序的性能与内存效率。本文旨在深入探究int与Integer的区别&#xff0c;涵盖其在内存占用、线程安全、自动装箱与拆箱机制等方面的表现。…

3条非常实用的处世“潜规则”,受益终生

01 尽量不要让别人在你身上免费得到&#xff0c;哪怕是你不需要或者根本不在意的东西。 让别人免费得到&#xff0c;其实就是一种暗示&#xff0c;暗示别人可以继续免费索取&#xff0c;为什么&#xff1f;因为人性总是趋利的&#xff0c;如果可以免费得到&#xff0c;那为什…

高校是需要AIGC 实验室还是大数据人工智能实验室呢

AIGC&#xff08;人工智能与图形计算&#xff09;实验室和大数据人工智能实验室虽然都隶属于人工智能的范畴&#xff0c;但它们的关注点、研究方向和具体应用领域有所不同。 我们分别从研发方向、技术侧重、应用领域、研究工具和方法等方面去分析两者的区别&#xff0c;希…

MySQL的跳跃式索引

Skip Index Scan&#xff08;跳跃式索引&#xff09; 例如初中有个学生表&#xff0c;年级、班级、学号 符合索引。 -- 问题是下面这个查询为什么也可以用到索引。 select * from 初中学生表 where 班级 1 and 学号 001-- 思考一下这个查询比全表扫描快吗&#xff1f; sele…

“微软蓝屏”事件:网络安全与稳定性的深刻反思

&#x1f308;所属专栏&#xff1a;【其它】✨作者主页&#xff1a; Mr.Zwq✔️个人简介&#xff1a;一个正在努力学技术的Python领域创作者&#xff0c;擅长爬虫&#xff0c;逆向&#xff0c;全栈方向&#xff0c;专注基础和实战分享&#xff0c;欢迎咨询&#xff01; 您的点…

软件-vscode-plantUML-IDEA

文章目录 vscode基础命令 实操1. vscode实现springboot项目搭建 &#xff08;包括spring data jpa和sqlLite连接&#xff09; PlantUMLIDEA下载及安装Eval Reset插件配置修改IDEA创建项目的默认目录IDEA配置gitIDEA翻译插件translationIDEA断点调试IDEA全局搜索快捷键不能使用代…

UE5.4内容示例(3)FBX_Import_Options - 学习笔记

https://www.unrealengine.com/marketplace/zh-CN/product/content-examples 《内容示例》是学习UE5的基础示例&#xff0c;可以用此熟悉一遍UE5的功能 FBX_Import_Options案例 导入案例需要和模型制作工具结合理解&#xff0c;这里就大致了解下都可以导入些什么内容 1.1 Stati…

基于web3区块链的名酒资产数字化、个人闲置资产收藏系统,实现联盟链、NFT数据上链、智能合约开发

系统背景&#xff1a; 国内有众多历史悠久却极具收藏价值的名酒品类&#xff0c;但是传统名酒投资存在着保真、流通和收藏三大痛点&#xff0c;极大影响了名酒产业的发展。基于区块链的分布式、不可篡改、可追溯、透明性、多方维护、交叉验证等特性&#xff0c;数据权属可以被有…

录歌用什么软件好?关于录音软件的操作介绍(内含7款)

录歌用什么软件好&#xff1f;借助录音软件&#xff0c;我们可以在电脑上录制音频文件&#xff0c;包括游戏原声、电台、视频会议、音乐平台等。 一、什么是录音软件 简单来说&#xff0c;录音软件就是一个录制声音的用户界面。这些应用程序允许用户录制任何声音、处理和混合音…

成就巴西休闲游戏如何借助Google谷歌广告投放优势

在探讨巴西休闲游戏如何借助谷歌广告投放优势实现市场扩张的过程中&#xff0c;我们不得不深入分析巴西市场的独特属性、休闲游戏的兴起背景&#xff0c;以及谷歌广告平台在全球范围内的强大影响力。近年来&#xff0c;随着移动游戏市场的快速发展&#xff0c;特别是中轻度休闲…

使用免费代理有什么危险?

一、引言 随着互联网的普及&#xff0c;越来越多的人开始意识到代理服务的重要性&#xff0c;尤其是在保护隐私和突破地域限制方面。然而&#xff0c;在众多的代理服务中&#xff0c;免费的代理服务已经成为许多人的首选。本文将深入探讨使用免费代理的危险&#xff0c;并帮助…

LeetCode Hot100 删除链表的倒数第 N 个结点

给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], n 2 输出&#xff1a;[1,2,3,5]示例 2&#xff1a; 输入&#xff1a;head [1], n 1 输出&#xff1a;[]示例 3&#xff1a;…

【Unity渲染】烘培

光照探针 光照探针就是在烘焙的时候会布局多个探测点&#xff0c;记录那个地方的光照信息&#xff0c;后面实时渲染动态物体会影响其渲染&#xff0c;动态物体会选择自己周围最近的探针进行影响 反射探针 反射探针就是记录周围环境&#xff0c;计算一个类似天空盒的图片&am…

免费!OpenAI发布最新模型GPT-4o mini,取代GPT-3.5,GPT-3.5退出历史舞台?

有个小伙伴问我&#xff0c;GPT-4O mini是什么&#xff0c;当时我还一脸懵逼&#xff0c;便做了一波猜测&#xff1a; 我猜测哈&#xff0c;这个可能是ChatGPT4o的前提下&#xff0c;只支持文本功能的版本&#xff0c;速度更快 结果&#xff0c;大错特错。 让我们一起看看Open…

【QT】无法打开QT的ui文件,出现闪退情况

打开qt的ui文件出现闪退的情况&#xff1a; 解决办法&#xff1a;点击扩展-Qt VS Tools-Options 找到Qt General中的Qt Designer 的Run in detached window改为True。

如何用3个月零基础入门网络安全?_网络安全零基础怎么学习

前 言 写这篇教程的初衷是很多朋友都想了解如何入门/转行网络安全&#xff0c;实现自己的“黑客梦”。文章的宗旨是&#xff1a; 1.指出一些自学的误区 2.提供客观可行的学习表 3.推荐我认为适合小白学习的资源.大佬绕道哈&#xff01; →点击获取网络安全资料攻略← 一、自学…