硬汉嵌入式论坛

 找回密码
 立即注册
查看: 2213|回复: 13
收起左侧

[信号与系统] 五点二次线性平滑的函数分享

  [复制链接]

332

主题

2031

回帖

3032

积分

版主

Rank: 7Rank: 7Rank: 7

积分
3032
发表于 2022-3-11 15:12:41 | 显示全部楼层 |阅读模式
本帖最后由 caicaptain2 于 2022-3-11 16:33 编辑

研究了一下线性多次平滑的滤波算法。 公式是这个:
Savitzky–Golay-5点2次平滑公式.png


函数如下:
  1. /**
  2. *@function: - 5点2次线性平滑
  3. *@data:输入数据,输出数据
  4. *@size;data数据的个数
  5. *返回滤波后的值 */
  6. int8_t  LinearSmooth5p2(float* data, uint16_t size)
  7. {
  8.   float output[5]; //5点缓存
  9.   uint16_t j=0;
  10.   int8_t  Para[5][5]={ //每一行的数字之和为35
  11.     {31, 9,-3,-5, 3},  
  12.     { 9,13,12, 6,-5},
  13.     {-3,12,17,12,-3},
  14.     {-5, 6,12,13, 9},
  15.     { 3,-5,-3, 9,31},        
  16.   };
  17.   
  18.   if(size<5) return -1; //数据太少。不处理。
  19.   else
  20.   {
  21.     output[0]=(Para[0][0]*data[0]+ Para[0][1]*data[1]+Para[0][2]*data[2]+Para[0][3]*data[3]+ Para[0][4]*data[4])/35;
  22.     output[1]=(Para[1][0]*data[0]+ Para[1][1]*data[1]+Para[1][2]*data[2]+Para[1][3]*data[3]+ Para[1][4]*data[4])/35;

  23.     output[3]=(Para[3][0]*data[size-5]+ Para[3][1]*data[size-4]+Para[3][2]*data[size-3]+Para[3][3]*data[size-2]+ Para[3][4]*data[size-1])/35;
  24.     output[4]=(Para[4][0]*data[size-5]+ Para[4][1]*data[size-4]+Para[4][2]*data[size-3]+Para[4][3]*data[size-2]+ Para[4][4]*data[size-1])/35;
  25.    
  26.     for(j=2;j<=size-3;j++)
  27.       {
  28.         output[2]=(Para[2][0]*data[j-2]+ Para[2][1]*data[j-1]+Para[2][2]*data[j]+Para[2][3]*data[j+1]+ Para[2][4]*data[j+2])/35;
  29.         data[j]=output[2];
  30.       }
  31.       data[0]=output[0];
  32.       data[1]=output[1];
  33.       data[size-2]=output[3];
  34.       data[size-1]=output[4];
  35.       return 1; //成功转换。
  36.   }
  37. }   
复制代码




回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106437
QQ
发表于 2022-3-12 11:19:37 | 显示全部楼层
谢谢分享。
回复

使用道具 举报

95

主题

297

回帖

582

积分

金牌会员

123

积分
582
发表于 2022-3-21 14:33:20 | 显示全部楼层
比如我来一个点执行一次这个函数,那么第一个参数就是一个数组buffdata,buffdata[0](最新的数据);buffdata[0](前一个数据);buffdata[1](更前一个数据);buffdata[2](更更前一个数据);buffdata[3](更更更前一个数据);buffdata[4](更更更更前一个数据);第二个参数就是5,数据的个数;?是否对呢?返回的值就是当前加权后的算出的值,然后把点打到屏幕?
回复

使用道具 举报

332

主题

2031

回帖

3032

积分

版主

Rank: 7Rank: 7Rank: 7

积分
3032
 楼主| 发表于 2022-3-21 17:08:15 | 显示全部楼层
ssssssss 发表于 2022-3-21 14:33
比如我来一个点执行一次这个函数,那么第一个参数就是一个数组buffdata,buffdata[0](最新的数据);buffdat ...

我的数学也不好,只是照葫芦画瓢。。。。
似乎是就是把前后的数据进行加权平均,得到当前数据。 为什么是这个权重? 因为数学家经过计算了,这样子的方差最小。
回复

使用道具 举报

95

主题

297

回帖

582

积分

金牌会员

123

积分
582
发表于 2022-3-21 22:52:16 | 显示全部楼层
本帖最后由 ssssssss 于 2022-3-22 08:11 编辑
caicaptain2 发表于 2022-3-21 17:08
我的数学也不好,只是照葫芦画瓢。。。。
似乎是就是把前后的数据进行加权平均,得到当前数据。 为什么 ...

函数的入口参数我理解的对吗?

网络摘抄
1、五点线性拟合去差值原理是利用五点数据拟合出一条曲线来计算每一未知点的函数值。选择周围五个点,去掉最大值和最小值求剩余三个点的平均,使其相邻点变得平滑。

2、五点线性平滑算法原理是利用最小二乘法拟合一条直线来计算未知点的函数值,属于一种均值滤波。




五点三次平滑法(cubical smoothing algorithm with five-point approximation)
Y=a0+a1x+a2x^2+a3x^3 三次多项式拟合:
yo(-2)=(69*yi(-2)+4*yi(-1)-6*yi(0)+4*yi(1)-yi(2))/70
yo(-1)=(2*yi(-2)+27*yi(-1)+12*yi(0)-8*yi(1)+2*yi(2))/35
yo(0) =(-3*yi(-2)+12*yi(-1)+17*yi(0)+12*yi(1)-3*yi(2))/35 (除了前两项和后两项外,都可用此式)
yo(1) =(2*yi(-2)-8*yi(-1)+12*yi(0)+27*yi(1)+2*yi(2))/35
yo(2) =(-yi(-2)+4*yi(-1)-6*yi(0)+4*yi(1)+69*yi(2))/70

七点三次平滑法:yo(0) =(-2*yi(-3)+3*yi(-2)+6*yi(-1)+7*yi(0)+6*yi(1)+3*yi(2)-2*yi(3))/21




回复

使用道具 举报

332

主题

2031

回帖

3032

积分

版主

Rank: 7Rank: 7Rank: 7

积分
3032
 楼主| 发表于 2022-3-22 12:28:16 | 显示全部楼层
ssssssss 发表于 2022-3-21 22:52
函数的入口参数我理解的对吗?

网络摘抄

是的。
5点好理解,二次,三次的区别不懂区别。
回复

使用道具 举报

95

主题

297

回帖

582

积分

金牌会员

123

积分
582
发表于 2022-3-22 19:58:14 | 显示全部楼层
caicaptain2 发表于 2022-3-22 12:28
是的。
5点好理解,二次,三次的区别不懂区别。

你试的效果如何,你多长时间采集一个值?
回复

使用道具 举报

95

主题

297

回帖

582

积分

金牌会员

123

积分
582
发表于 2022-3-24 17:44:26 | 显示全部楼层
caicaptain2 发表于 2022-3-22 12:28
是的。
5点好理解,二次,三次的区别不懂区别。

double KalmanFilter(double inData)
{
    static double prevData = 0;                              //上一个数据
    static double p = 10, q = 0.00005, r = 0.005, kGain = 0; //q值控制误差,r控制响应速度
    p = p + q;
    kGain = p / (p + r);                                       //计算增益
    inData = prevData + (kGain * ((double)inData - prevData)); //计算本次滤波估计值
    p = (1 - kGain) * p;                                       //更新测量方差
    prevData = inData;
    return inData;
}



看看这个函数行不行?
回复

使用道具 举报

332

主题

2031

回帖

3032

积分

版主

Rank: 7Rank: 7Rank: 7

积分
3032
 楼主| 发表于 2022-3-25 09:30:01 | 显示全部楼层
ssssssss 发表于 2022-3-24 17:44
double KalmanFilter(double inData)
{
    static double prevData = 0;                             ...

粗看,p的初始值有点问题吧。
第一轮,p等于10,那么kgain约等于1,第二轮,p值就几乎归零了。
可以用excel拉一个表格,观察kgain的变化,评估是否合理。
回复

使用道具 举报

95

主题

297

回帖

582

积分

金牌会员

123

积分
582
发表于 2022-3-25 16:08:13 | 显示全部楼层
caicaptain2 发表于 2022-3-25 09:30
粗看,p的初始值有点问题吧。
第一轮,p等于10,那么kgain约等于1,第二轮,p值就几乎归零了。
可以用e ...

我的一个朋友说,可以用excel表格,用一串数据试试就知道了,这个函数是可以用的
回复

使用道具 举报

0

主题

2

回帖

2

积分

新手上路

积分
2
发表于 2022-3-29 09:50:26 | 显示全部楼层
ssssssss 发表于 2022-3-24 17:44
double KalmanFilter(double inData)
{
    static double prevData = 0;                             ...

测试过,可用,效果不错。感谢分享!
回复

使用道具 举报

0

主题

3

回帖

3

积分

新手上路

积分
3
发表于 2022-3-29 21:05:08 | 显示全部楼层
核信号处理中这个函数用的很多,还有7点法,9点法和11点。以前在一本核信号处理书上看到过,具体系数都忘记了。一般用在谱数据预处理上,适合滤除随机干扰噪声,对特征峰影响较小。
回复

使用道具 举报

95

主题

297

回帖

582

积分

金牌会员

123

积分
582
发表于 2022-4-21 09:38:06 | 显示全部楼层
larry.wong 发表于 2022-3-29 09:50
测试过,可用,效果不错。感谢分享!

你的测试场景是啥,具体是啥功能?能大概说一下嘛?
回复

使用道具 举报

0

主题

2

回帖

2

积分

新手上路

积分
2
发表于 2022-5-18 11:57:06 | 显示全部楼层
ssssssss 发表于 2022-4-21 09:38
你的测试场景是啥,具体是啥功能?能大概说一下嘛?

测度的的一个称重的应变数据,稳定挺快的,对外部振动反映会慢些。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-4-20 13:52 , Processed in 0.246579 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表