自适应滤波C语言实现

这里写目录标题

原理

自适应滤波是近年以来发展起来的一种最佳滤波方法。它是在维纳滤波,Kalman滤波等线性滤波基础上发展起来的一种最佳滤波方法。由于它具有更强的适应性和更优的滤波性能。从而在工程实际中,尤其在信息处理技术中得到了广泛的应用。自适应滤波存在于信号处理、控制、图像处理等许多不同领域,它是一种智能更有针对性的滤波方法,通常用于去噪。
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210311120044984.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQyMjA5OTc3,size_16,color_FFFFFF,t_70在这里插入图片描述
在这里插入图片描述
本人理解的自适应滤波是输入X(N)变量值和自适应滤波滤波器系数W(n)进行矩阵相乘得到系统输出的Y(j),Y(j)和期望信号D(n)相减得到差值E(n).通过不断的迭代得到合适的滤波器系数W(N+1)。

代码

参考:https://blog.csdn.net/xdzhujy/article/details/105638797?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522161543561316780255269410%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=161543561316780255269410&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allbaidu_landing_v2~default-6-105638797.pc_search_result_cache&utm_term=%E8%87%AA%E9%80%82%E5%BA%94%E7%AE%97%E6%B3%95

上诉博主理论和MATLAB代码说得很详细,在他MATLAB代码的基础,理解了一下,写出C语言代码,运行环境Microsft Visual Studio.
下面展示一些 内联代码片

#include<stdio.h>
#define F_COUNT 1024
#define M 15
/* xn--------输入的信号序列(列向量)
 * itr-------迭代次数,标量,默认为xn的长度,M<itr<sizeof(xn)
 * en--------误差序列(itr*1)列向量
 * dn--------所期望的响应序列(列向量)
 * M---------滤波器的阶数(标量)
 * mu--------收敛因子(步长)标量
 * W---------滤波器权值矩阵,大小为M*itr
 * yn--------实际输出序列(列向量)*/

float xn[250] = { 10,10.2,9.8,10,10.1,9.9,10.1,10.2,9.78,9.9,10, 10,10.1,9.8,10,10.1,9.9,10.1,10.2,9.78,9.9,10, 10,9.8,9.8,10,10.1,9.9,10.1,10.2,9.78,9.9,10, 10,10.2,9.8,10,10.1,9.9,10.1,10.2,9.78,9.9,10, 10,10,9.8,10,10.1,9.9,10.10,10.2,9.78,9.9,10, 10,9,9.8,10,10.1,9.9,10.1,10.2,9.78,9.9,10, 10,9,9.8,10,10.1,9.9,10.1,10.2,9.78,9.9,10, 10,9.8,9.8,10,10.1,9.9,10.1,10.2,9.78,9.9,10, 10,9.8,9.8,10,10.1,9.9,10.1,10.2,9.78,9.9,10,10,9.8,9.8,10,10.1,9.9,10.1,10.2,9.78,9.9,10, 10,9.8,9.8,10,10.1,9.9,10.1,10.2,9.78,9.9,10, 10,9.8,9.8,10,10.1,9.9,10.1,10.2,9.78,9.9,10, 10,9.8,9.8,10,10.1,9.9,10.1,10.2,9.78,9.9,10, 10,9.8,9.8,10,10.1,9.9,10.1,10.2,9.78,9.9,10, 10,9.8,9.8,10,10.1,9.9,10.1,10.2,9.78,9.9,10, 10,9.8,9.8,10,10.1,9.9,10.1,10.2,9.78,9.9,10, 10,9.8,9.8,10,10.1,9.9,10.1,10.2,9.78,9.9,10, 10,9.8,9.8,10,10.1,9.9,10.1,10.2,9.78,9.9,10,20.0,20.1,20.2,20.3,20.4,20.5,20.6,20.7,20.8,20.9,21,21.1,21.2,21.3,21.4,21.5,21.6,21.7,21.8,21.9,22,22.1,22.2,22.3,22.4,22.51,22.62,22.72,22.78,22.89,23.02,23.12,23.18,23.31,23.42,23.53,23.62,23.67,23.78,23.89,24.02,24.08,24.18,24.32,24.38,24.52,24.61,24.74,24.81,24.92,25,25.1 };
float dn[251] = {10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10 ,10,10,10,10,10,10,10,10,10,10 ,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10 ,10,10,10,10,10,10,10,10,10,10 ,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10 ,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10 ,10,10,10,10,10,10,10,10,10,10 ,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10 ,10,10,10,10,10,10,10,10,10,10 ,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10 ,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,20.0,20.1,20.2,20.3,20.4,20.5,20.6,20.7,20.8,20.9,21,21.1,21.2,21.3,21.4,21.5,21.6,21.7,21.8,21.9,22,22.1,22.2,22.3,22.4,22.5,22.6,22.7,22.8,22.9,23.0,23.1,23.2,23.3,23.4,23.5,23.6,23.7,23.8,23.9,24.0,24.1,24.2,24.3,24.4,24.5,24.6,24.7,24.8,24.9,25 };

float* LMS_Filter(int itr, const float* xn, const float* dn, double mu, int length)
{
	static int i = 0;
	static int k = 0;
	static float y = 0.0;
	static float en[F_COUNT];
	static float W[M];//static float W[M][F_COUNT];
	static float x[M];
	static float yn[F_COUNT];

	
		//下面两行代码打印出xn原始数据,需要可以取消注释
	//for (i = 0; i < 250; i++)
	//	printf("y=%f   k=%d\n", xn[i], i);


	for(i=0;i<M;i++)
		printf("y=%f   k=%d\n", xn[i], i);
	/*创建一个en全零矩阵,en(k)表示第k次迭代时预期输出与实际输入的误差*/
	for (i = 0; i < itr; i++)
	{
		en[i] = 0;
	}

	/*创建一个W全零矩阵,每一行代表一个加权参量,每一列代表一次迭代*/
	for (i = 0; i < M; i++)
			W[i] = 0;

	/*创建一个x全零矩阵*/
	for (i = 0; i < M; i++)
		x[i] = 0;

	/*迭代计算*/
	for (k = M; k <= itr; k++)
	{
		/* 滤波器M个抽头的输入:从xn第k-1个值倒序取出M个样点的值放入x
		 * y为滤波器输出:W的第K-2列与x的积的和*/
		for (i = 0; i < M; i++)
		{
			x[i] = xn[k-i-1];
		}
		for (i = 0; i < M; i++)
			y += W[i] * x[i];   //卷积乘法
		en[k] = dn[k] - y;  //第k次迭代的误差

		/*滤波器权值计算的迭代式*/
		for (i = 0; i < M; i++)
		{
			W[i] = W[i]+  mu * en[k] * x[i];
		}

		printf("y=%f   k=%d\n", y,k);
		y = 0.0;
	}

	return yn;
}
int main()
{
	LMS_Filter(250, xn, dn, 0.0008, 250);
	printf("hellow");
}

结果

在这里插入图片描述


在这里插入图片描述
经过自适应滤波后,确实起到滤波效果,而且在前后段数据波动较大时,系统也可以很快的拟合数据。效果比固定拟合系数的卡尔曼滤波好。代码中xn是原始数据,DN是期望数据,代码中可以更改步长,和滤波器阶数。有啥问题评论区留言,一起探讨,博主也是半懂不懂。

  • 3
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值