高斯加权移动平均滤波(Gaussian weighted moving average)是将高斯函数与滑动窗口平均结合的一种滤波技术。它的目的是通过平滑数据,减少噪声,从而得到更加平稳的信号。

基本概念

高斯滤波(Gaussian Filtering)是一种对数据进行平滑的方法,它的目的是去除数据中的噪声或快速变化,使信号更加平滑和连续。它基于高斯函数(数学上的钟形曲线)来分配权重,使得距离中心越远的值影响越小。
滑动窗口平均(Moving Average)是一种通过对一段时间内的数据计算平均值来平滑数据的技术。在滑动窗口平均中,我们使用一个大小固定的窗口(即一段连续的数值),并且每次计算平均值时,这个窗口会按顺序“滑动”到下一个数据点。

  1. 高斯函数 (Gaussian Function)

高斯函数定义了滤波器的权重分布,其数学公式为:

G(x)=12πσex22σ2G(x) = \dfrac{1}{\sqrt{2\pi\sigma}}e^{-\tfrac{x^{2}}{2\sigma^{2}}}

其中:

  • xx: 与中心点的距离(例如第几个数据点)。
  • σ\sigma (标准差): 决定曲线的宽度。
    • σ\sigma 大:滤波器分布更宽,平滑程度高(去除更多噪声)。
    • σ\sigma 小:滤波器集中在中心,平滑程度低(保留更多细节)。
  1. 高斯核 (Gaussian Kernel)

高斯核是根据高斯函数生成的一组数字,这些数字用来加权你的数据。例如,一个5个点的高斯核(标准差为1):

[0.061,0.242,0.383,0.242,0.061][0.061, 0.242, 0.383, 0.242, 0.061]

中间的值最大,离中心越远权重越小。

  1. 卷积 (Convolution)

卷积是高斯滤波的核心操作,高斯核会像一个窗口一样滑过整个数据,每次计算加权平均值,生成新的平滑数据

  1. 窗口大小

滑动窗口中包含的连续数据点的数量。比如,如果窗口大小是 3,意味着每次平均的是三个相邻的数据点。

整体思路

假定我们现在有一个输入信号(如温度数据):

X=[x1,x2,x3,x4,...]X = [x_1, x_2, x_3, x_4, ...]

我们要对这些数据进行高斯加权移动平均滤波。具体步骤如下:

构建高斯权重

我们选择一个窗口大小,比如 NN,然后构建一个高斯权重数组。假设我们选择窗口大小为 5,表示我们要处理每 5 个连续的数据点。然后,计算每个位置的权重。

例如,使用标准差 σ=1\sigma = 1 来生成一个窗口大小为 5 的高斯权重数组:

Weights=[0.054,0.242,0.398,0.242,0.054]Weights = [0.054, 0.242, 0.398, 0.242, 0.054]

这个数组是基于高斯函数计算出来的,表示距离中心点越近,权重越大。

应用高斯加权移动平均

接下来,我们将这些权重应用到原始数据上,计算加权平均。对于输入信号的每一组 5 个数据,我们按照以下公式计算加权平均:

y(t)=1Wi=22x(t+i)W(i)y(t) = \dfrac{1}{\sum W}\sum\limits^{2}_{i=-2}x(t+i)W(i)

其中:

  • y(t)y(t) 是时间点 tt 上的滤波结果。

  • x(t+i)x(t+i) 是信号 XX 在时间 tt 位置周围的值。

  • W(i)W(i) 是高斯权重。

例如,假设原始信号为:

X=[10,11,12,13,14,15,16,17,18]X = [10, 11, 12, 13, 14, 15, 16, 17, 18]

对第一个窗口 [10,11,12,13,14][10, 11, 12, 13, 14] 应用高斯加权平均:

y1=10.054+0.242+0.398+0.242+0.054×(10×0.054+11×0.242+12×0.398+13×0.242+14×0.054)y_1 = \dfrac{1}{0.054+0.242+0.398+0.242+0.054} \times (10 \times 0.054 + 11 \times 0.242 + 12 \times 0.398 + 13 \times 0.242 + 14 \times 0.054 )

这样得到一个新的平滑值,以此类推,直到对整个信号应用滤波。

更新信号

每次应用完滤波,得到的新信号就是去噪之后的平滑结果。

C 语言代码示例

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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
/**
******************************************************************************
* @file : GWMA.c
* @brief : Gaussian weighted moving average algorithm,
* this is a modified code, which is used for filtering
* temperature data after collecting from sensors, window
* size is 5 and only calculate the center data of sliding
* window array, and the data to the left of the center
* data is the mirror fill value.
* @author : Charles
* @date : 2024-11-20
******************************************************************************
* @attention
*
* @copyright 2024 by Charles/https://www.charlesyu1997.com
*
******************************************************************************
*/

#include "GWMA.h"
#include "main.h"

/**
* @name initGaussianKernelForGWMA
* @brief Initialize the Gaussian kernel data array.
* @param kernel[] Kernel data array.
* @param size Size of kernel data array.
* @param sigma Standard deviation of Gaussian.
* @return NONE
*
*/
void initGaussianKernelForGWMA(float kernel[], int size, float sigma)
{
float sum = 0.0;
int center = size / 2;
int i_gwma;
for ( i_gwma = 0; i_gwma < size; i_gwma++) {
int x = i_gwma - center;
kernel[i_gwma] = exp(-(x * x) / (2 * sigma * sigma));
sum += kernel[i_gwma];
}
// Normalization
for (int i_gwma = 0; i_gwma < size; i_gwma++) {
kernel[i_gwma] /= sum;
}
}
/**
* @name updateSlidingWindowForGWMA
* @brief Update the sliding window data array and remove the oldest data.
* @param window[] Sliding window data array.
* @param size Size of sliding window data array.
* @param newValue A new value which will be inserted to the end of sliding window.
* @return NONE
*
*/
void updateSlidingWindowForGWMA(float window[], int size, float newValue)
{
int i_gwma;
for ( i_gwma = 1; i_gwma < ((size+1) / 2) ; i_gwma++) {
window[i_gwma - 1] = window[i_gwma];
}
// Mirror Padding
for (i_gwma = (size / 2) ; i_gwma < size; i_gwma++ ) {
window[i_gwma] = newValue; // Insert the new value.
}
}
/**
* @name calculateConvolutionForGWMA
* @brief Calculate convolution and get the result of GWMA.
* @param window[] Sliding window data array.
* @param size Size of sliding window data array.
* @param newValue A new value which will be inserted to the end of sliding window.
* @return NONE
*
*/
float calculateConvolutionForGWMA(float window[], float kernel[], int size)
{
float result = 0.0;
int i_gwma = 0;
for (i_gwma = 0; i_gwma < size; i_gwma++) {
result += window[i_gwma] * kernel[i_gwma];
}
return result;
}

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
/**
******************************************************************************
* @file : GWMA.h
* @brief : Gaussian weighted moving average algorithm.
* @author : Charles
* @date : 2024-11-20
******************************************************************************
* @attention
*
* @copyright 2024 by Charles/https://www.charlesyu1997.com
*
******************************************************************************
*/

#ifndef __GWMA_H__
#define __GWMA_H__

#define GWMA_WINDOW_SIZE 5
#define GWMA_KERNEL_SIZE GWMA_WINDOW_SIZE

void initGaussianKernelForGWMA(float kernel[], int size, float sigma);
void updateSlidingWindowForGWMA(float window[], int size, float newValue);
float calculateConvolutionForGWMA(float window[], float kernel[], int size);

#endif

优点

  • 平滑效果好: 相比简单的平均值滤波,高斯加权滤波更加精确,因为它考虑了数据的相对重要性。
  • 去噪效果明显: 它特别适用于平滑带有高频噪声的信号。
  • 保留边缘信息: 由于高斯函数的特点,它能更好地保留信号的边缘信息,避免过度平滑。

缺点

  • 计算量大: 尤其在数据量较大时,每次计算都需要进行加权操作,可能会导致计算开销较大。
  • 窗口大小的选择问题: 窗口大小 NN 和标准差 σ\sigma 的选择会影响滤波效果。如果选择不当,可能导致信号丢失或者噪声去除不充分。

简单总结

高斯加权移动平均滤波 是一种高效的信号去噪方法,它通过为数据赋予不同的权重,平滑信号并减少噪声。高斯函数 的特点使得距离中心点越远的值对最终结果的影响越小,从而保持信号的真实性。通过构建合适的 加权窗口标准差,你可以控制滤波的强度和精度。

为什么使用高斯加权?

我们常常想通过滤波来平滑数据,减少噪声,但简单的均值滤波可能会忽略数据的空间结构,导致信息丢失。而高斯加权滤波通过给数据赋予不同的权重,使得远离中心点的值对最终结果的影响较小,从而更加精确地平滑信号,保留有效信息。


此间车厢已使用  次 |   人乘坐过此趟开往世界尽头的列车