• 【数据去噪】SG-多项式平滑算法


    一、简介

    在处理工业数据的时候,工业数据有数据颗粒细,噪声大,量大,随着测量点的增加,数据维度高,复杂性高,而且关联性强,不过这个关联性是相对的,因为有时候数据噪声较大,显示不出来这种关联性。

    最近了解的五点三次平滑,因为工作中遇到了用 五点三次平滑算法 平滑 车道线模型检测出的 车道线的点集,去除噪声点,方便后处理里拟合车道线方程。

    引用文献的解释:

    “一般来说,在数据采集系统中采集到的数据往往叠加有噪声。
    噪声分为两种,一类为周期性的,一类为不规则的。前者代表为50 Hz 的工频干扰,后者代表为随机信号。”
    “由于随机干扰的存在,使得随机信号绘成的曲线多呈折线状,这就表明采样数据中高频成分比较丰富。为了消除或减弱干扰的影响,提高曲线光滑度,需对采样数据进行平滑处理。
    常用的平滑处理方法有: 平均法样条函数法五点三次平滑法

    • 平均法相对简单,滤波效果也差;
    • 样条函数法利用样条插值逼近采样点的方法来实现平滑,算法多样,效果较好,但是,使用该方法计算相对复杂,平滑幅度控制较差;
    • 五点三次平滑法利用多项式最小二乘逼近来对采样点实行平滑滤波,算法简单,效果较好。”

    二、原理

    在这里插入图片描述
    把光谱一段区间的等波长间隔的5个点记为X集合,多项式平滑就是利用在波长点为Xm-2,Xm-1,Xm,Xm+1,Xm+2的数据的多项式拟合值来取代Xm,,然后依次移动,直到把光谱遍历完。

    在这里插入图片描述

    5点3次多项式平滑

    设已知n个等距点,上的观测(或实验)数据为
    x0<x1<…<xn-1,
    则可以在每个数据点的前后各取两个相邻的点,用三次多项式

    Y=a0 + a1x + a2x^2 + a3x^3

    进行逼近。

    根据最小二乘原理确定出系数a0,a1,a2,a3,最后可得到五点三次平滑公式如下:
    在这里插入图片描述
    该公式要求数据点数n≥5,当数据点数多于5时,为对称考虑,除在两端分别用公式(4-1),(4-2)和(4-4),(4-5)外,其余都用公式(4-3)进行平滑,这就相当在每个子区间上用不同的三次最小二乘多项式进行平滑。

    三、代码

    1. 3点线性平滑

    //3点线性平滑
    int LinearSmooth3(double* input, long size) {
    	double *output = new double[size];
    	long i(0);
     
    	if (size < 3)
    	{
    		for (i = 0; i <= size - 1; i++)
    		{
    			output[i] = input[i];
    		}
    	}
    	else
    	{
    		output[0] = (5.0 * input[0] + 2.0 * input[1] - input[2]) / 6.0;
    		for (i = 1; i <= size - 2; i++)
    		{
    			output[i] = (input[i - 1] + input[i] + input[i + 1]) / 3.0;
    		}
    		output[size - 1] = (5.0 * input[size - 1] + 2.0 * input[size - 2] - input[size - 3]) / 6.0;
    	}
     
    	for (i = 0; i < size; i++)
    	{
    		input[i] = output[i];
    	}
     
    	delete[] output;
     
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    2. 5点线性平滑

    //5点线性平滑
    int LinearSmooth5(double* input, long size) {
    	double *output = new double[size];
    	long i(0);
     
    	if (size < 5)
    	{
    		for (i = 0; i <= size - 1; i++)
    		{
    			output[i] = input[i];
    		}
    	}
    	else
    	{
    		output[0] = (3.0 * input[0] + 2.0 * input[1] + input[2] - input[4]) / 5.0;
    		output[1] = (4.0 * input[0] + 3.0 * input[1] + 2 * input[2] + input[3]) / 10.0;
    		for (i = 2; i <= size - 3; i++)
    		{
    			output[i] = (input[i - 2] + input[i - 1] + input[i] + input[i + 1] + input[i + 2]) / 5.0;
    		}
    		output[size - 2] = (4.0 * input[size - 1] + 3.0 * input[size - 2] + 2 * input[size - 3] + input[size - 4]) / 10.0;
    		output[size - 1] = (3.0 * input[size - 1] + 2.0 * input[size - 2] + input[size - 3] - input[size - 5]) / 5.0;
    	}
     
    	for (i = 0; i < size; i++)
    	{
    		input[i] = output[i];
    	}
     
    	delete[] output;
     
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    3. 5点2次线性平滑

    //5点二次线性平滑
    int LinearSmooth52(double* input, long size) {
    	double *output = new double[size];
    	long i(0);
     
    	if (size < 5)
    	{
    		for (i = 0; i <= size - 1; i++)
    		{
    			output[i] = input[i];
    		}
    	}
    	else
    	{
    		output[0] = (31.0 * input[0] + 9.0 * input[1] - 3.0 * input[2] - 5.0 * input[3] + 3.0 * input[4]) / 35.0;
    		output[1] = (9.0 * input[0] + 13.0 * input[1] + 12 * input[2] + 6.0 * input[3] - 5.0 *input[4]) / 35.0;
    		for (i = 2; i <= size - 3; i++)
    		{
    			output[i] = (-3.0 * (input[i - 2] + input[i + 2]) +
    				12.0 * (input[i - 1] + input[i + 1]) + 17 * input[i]) / 35.0;
    		}
    		output[size - 2] = (9.0 * input[size - 1] + 13.0 * input[size - 2] + 12.0 * input[size - 3] + 6.0 * input[size - 4] - 5.0 * input[size - 5]) / 35.0;
    		output[size - 1] = (31.0 * input[size - 1] + 9.0 * input[size - 2] - 3.0 * input[size - 3] - 5.0 * input[size - 4] + 3.0 * input[size - 5]) / 35.0;
    	}
     
    	for (i = 0; i < size; i++)
    	{
    		input[i] = output[i];
    	}
     
    	delete[] output;
     
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    4. 5点3次线性平滑

    //5点三次线性平滑
    int LinearSmooth53(double* input, long size) {
    	double *output = new double[size];
    	long i(0);
     
    	if (size < 5)
    	{
    		for (i = 0; i <= size - 1; i++)
    			output[i] = input[i];
    	}
    	else
    	{
    		output[0] = (69.0 * input[0] + 4.0 * input[1] - 6.0 * input[2] + 4.0 * input[3] - input[4]) / 70.0;
    		output[1] = (2.0 * input[0] + 27.0 * input[1] + 12.0 * input[2] - 8.0 * input[3] + 2.0 * input[4]) / 35.0;
    		for (i = 2; i <= size - 3; i++)
    		{
    			output[i] = (-3.0 * (input[i - 2] + input[i + 2]) + 12.0 * (input[i - 1] + input[i + 1]) + 17.0 * input[i]) / 35.0;
    		}
    		output[size - 2] = (2.0 * input[size - 5] - 8.0 * input[size - 4] + 12.0 * input[size - 3] + 27.0 * input[size - 2] + 2.0 * input[size - 1]) / 35.0;
    		output[size - 1] = (-input[size - 5] + 4.0 * input[size - 4] - 6.0 * input[size - 3] + 4.0 * input[size - 2] + 69.0 * input[size - 1]) / 70.0;
    	}
     
    	for (i = 0; i < size; i++)
    	{
    		input[i] = output[i];
    	}
     
    	delete[] output;
     
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    5. 7点线性平滑

    //7点线性平滑
    int LinearSmooth7(double* input, long size) {
    	double *output = new double[size];
    	long i(0);
     
    	if (size < 7)
    	{
    		for (i = 0; i <= size - 1; i++)
    		{
    			output[i] = input[i];
    		}
    	}
    	else
    	{
    		output[0] = (13.0 * input[0] + 10.0 * input[1] + 7.0 * input[2] + 4.0 * input[3] +
    			input[4] - 2.0 * input[5] - 5.0 * input[6]) / 28.0;
    		output[1] = (5.0 * input[0] + 4.0 * input[1] + 3 * input[2] + 2 * input[3] +
    			input[4] - input[6]) / 14.0;
    		output[2] = (7.0 * input[0] + 6.0 * input[1] + 5.0 * input[2] + 4.0 * input[3] +
    			3.0 * input[4] + 2.0 * input[5] + input[6]) / 28.0;
    		for (i = 3; i <= size - 4; i++)
    		{
    			output[i] = (input[i - 3] + input[i - 2] + input[i - 1] + input[i] + input[i + 1] + input[i + 2] + input[i + 3]) / 7.0;
    		}
    		output[size - 3] = (7.0 * input[size - 1] + 6.0 * input[size - 2] + 5.0 * input[size - 3] +
    			4.0 * input[size - 4] + 3.0 * input[size - 5] + 2.0 * input[size - 6] + input[size - 7]) / 28.0;
    		output[size - 2] = (5.0 * input[size - 1] + 4.0 * input[size - 2] + 3.0 * input[size - 3] +
    			2.0 * input[size - 4] + input[size - 5] - input[size - 7]) / 14.0;
    		output[size - 1] = (13.0 * input[size - 1] + 10.0 * input[size - 2] + 7.0 * input[size - 3] +
    			4 * input[size - 4] + input[size - 5] - 2 * input[size - 6] - 5 * input[size - 7]) / 28.0;
    	}
     
    	for (i = 0; i < size; i++)
    	{
    		input[i] = output[i];
    	}
     
    	delete[] output;
     
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    6. 7点2次线性平滑

    //7点二次线性平滑
    int LinearSmooth72(double* input, long size) {
    	double *output = new double[size];
    	long i(0);
     
    	if (size < 7)
    	{
    		for (i = 0; i <= size - 1; i++)
    		{
    			output[i] = input[i];
    		}
    	}
    	else
    	{
    		output[0] = (32.0 * input[0] + 15.0 * input[1] + 3.0 * input[2] - 4.0 * input[3] -
    			6.0 * input[4] - 3.0 * input[5] + 5.0 * input[6]) / 42.0;
    		output[1] = (5.0 * input[0] + 4.0 * input[1] + 3.0 * input[2] + 2.0 * input[3] +
    			input[4] - input[6]) / 14.0;
    		output[2] = (1.0 * input[0] + 3.0 * input[1] + 4.0 * input[2] + 4.0 * input[3] +
    			3.0 * input[4] + 1.0 * input[5] - 2.0 * input[6]) / 14.0;
    		for (i = 3; i <= size - 4; i++)
    		{
    			output[i] = (-2.0 * (input[i - 3] + input[i + 3]) +
    				3.0 * (input[i - 2] + input[i + 2]) +
    				6.0 * (input[i - 1] + input[i + 1]) + 7.0 * input[i]) / 21.0;
    		}
    		output[size - 3] = (1.0 * input[size - 1] + 3.0 * input[size - 2] + 4.0 * input[size - 3] +
    			4.0 * input[size - 4] + 3.0 * input[size - 5] + 1.0 * input[size - 6] - 2.0 * input[size - 7]) / 14.0;
    		output[size - 2] = (5.0 * input[size - 1] + 4.0 * input[size - 2] + 3.0 * input[size - 3] +
    			2.0 * input[size - 4] + input[size - 5] - input[size - 7]) / 14.0;
    		output[size - 1] = (32.0 * input[size - 1] + 15.0 * input[size - 2] + 3.0 * input[size - 3] -
    			4.0 * input[size - 4] - 6.0 * input[size - 5] - 3.0 * input[size - 6] + 5.0 * input[size - 7]) / 42.0;
    	}
     
    	for (i = 0; i < size; i++)
    	{
    		input[i] = output[i];
    	}
     
    	delete[] output;
     
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
  • 相关阅读:
    『吴秋霖赠书活动 | 第三期』《Python asyncio并发编程》
    vue3.2的vuex升级pinia
    载电荷/离子修饰/稀土杂化表面/空心玻璃微球表面接枝聚苯乙烯微球
    Linux之history使用技巧
    FPGA工程师面试——RTL知识
    代码整洁之道:程序员的职业素养(十六)
    【Matytype】在CSDN博客中插入Mathtype行间与行内公式
    sqqyw(淡然点图标系统)漏洞复现和74cms漏洞复现
    储存卡数据怎么恢复?教你几招解决
    超自动化的未来
  • 原文地址:https://blog.csdn.net/All_In_gzx_cc/article/details/128079606