高斯滤波器是一种线性滤波器,能够有效的抑制噪声,平滑图像
1. 正态分布
一维高斯函数的表达式(PDF)为:

这里只讲解对应的符号及函数的作用,如果大家有兴趣可以研究一下高斯函数的推导过程,即这个函数是怎么来的:国内文献关于正态分布的推导过程
我们先将公式带入到Desmos图形计算器中:

得到一个标准的正态分布曲线。(u = 0 , simga = 1)
本质上讲正态分布是整个概率论与数理统计的核心
我们观察会发现大部分的数据集中在中间,而越往两边的数据越少,这种连续随机变量概率分布的情况在生活中息息相关:例如班级里同学的身高,学习成绩好坏,以及传感器采集的信号强弱等。
这里我们直观的认为蓝牙信标的信号采集呈正态分布,那么我们接下来就通过一维的高斯函数来解释信号分布的本质:
1.1 关于s(sigma)
概率密度函数可以理解为随机变量x服从于一个数学期望u, 标准方差为pow(s, 2)的高斯分布。
举例班级里的学习平均成绩为80,则80可以理解为数学期望,而从概率学上来说,s即为班级里学习成绩的标准差,它用来形容班级成绩分布的离散程度。
当s越大,则成绩分布越分散,从图形计算器的表达上可以看出,如果s = 2时:

当s越小,则成绩分布越集中,例如s = 0.2时:

1.2 正态分布的sigma原则
sigma原则:
数值分布在(μ-s,μ+s)中的概率为0.6826;

2sigma原则:
数值分布在(μ-2s,μ+2s)中的概率为0.9544;

3sigma原则:
数值分布在(μ-3s,μ+3s)中的概率为0.9974;
从上面三个原则我们可以知道,当x取值超过3sigma基本上是千分之5的概率,在实际实验中是基本不可能发生的。基本上可以把区间(μ-3s,μ+3s)看作是随机变量X实际可能的取值区间,这称之为正态分布的“3sigma”原则。
国外有一个顶尖的对冲基金叫做two-sigma, 这家公司会采用高斯混合模型来进行金融市场动态的预测建模,有兴趣可了解:Two Sigma:通过机器学习识别市场状态
注:这里要推荐一下Desmos在线图形计算工具,省去很多数学模型的绘制工作,太好用了。
2. 高斯滤波
终于进入正题了,我们现在要通过PDF函数对采集的信标信号进行过滤。在前面几篇文章我们提到了一些基础的滤波方法,例如均值滤波等等。。。
使用高斯函数时要注意的是,此函数应用在滤波降噪时,是作为一个建构模型的函数使用,并不是直接带入对应的信号值来计算。
举例来说我们要平滑某次接收到的信号,强度为80. 为了进行高斯滤波,我们需要采样其前后2次信号强度。这样我们就可以得到一个一维数组:
[ 76, 81, 80, 78, 84]
此时,我们带入高斯函数进行计算:
2.1 以80信号作为目标,我们可以设定出一个一一对应下标数组
[-2, -1, 0, 1, 2]
2.2 前面我们知道sigma越大,对应的波形宽度越宽,那么滤波目标受周围信号权重影响越大。这里我们先将此次信号分布作为一个标准的正态分布,则设置s = 1
2.3 因为滤波目标的权重下标为0,带入到PDF函数中 u = 0

计算出对应的模糊权重数组:
[0.054, 0.242, 0.399, 0.242, 0.054]
这时我们就得到了在设置好的高斯模型下的各点概率,然而这些点的权重加在一起等于0.991, 我们要进行加权平均还需要进行归一化处理。
计算后可得:
[ 0.0545, 0.244, 0.4, 0.244, 0.0545]
2.4 数值加权累加
final rssi = 0.0545 76 + 0.244 81 + 0.399 80 + 0.244 78 + 0.0545 *84 = 79.664
3. 代码实现
基于flutter代码实现高斯滤波demo
/// 计算高斯filter模板List<double> getOneGuassionArray(int size, int kerR, double sigma) {if (size % 2 == 0) {size -= 1;}if (size == 0) {return [];}if (kerR > size - 1) {return [];}double sum = 0;List<double> arr = List(size);for (int i = 0; i < size; i++) {arr[i] = exp(-((i - kerR) * (i - kerR)) / (2 * sigma * sigma)) / (sqrt(2 * PI) * sigma);sum += arr[i];}return arr.map((e) => e / sum).toList();}/// 计算sigmadouble computedSigma(list) {double average = getAverage(list);double sigmaSum = 0;list.forEach((e) {sigmaSum += (e - average).abs();});double sigma = sigmaSum / list.length;return sigma;}/// 求序列平均值double getAverage(List list) {double sum = 0.0;int n = list.length;list.forEach((e) {sum += e;});double average = sum / n;return average;}/// 高斯滤波double sigma = computedSigma(curBeacon['store']);int size = curBeacon['store'].length;int tmpSize = (size / 2).toInt();/// 进行高斯模糊过滤/// 计算高斯权重模型int r = (tmpSize / 2).floor();List models = getOneGuassionArray(tmpSize, r, sigma);dynamic ret = 0.0;int index = 0;List<num> gaussTmp = [];curBeacon['store'].forEach((element) {if (index >= r && index <= size - r) {for (int rIndex = -r; rIndex <= r; rIndex++) {ret += element * models[rIndex + r];}} else {ret = element;}index += 1;gaussTmp.add(ret);ret = 0.0;});
到这里,我们基本上了解了高斯函数与滤波,如有兴趣可以阅读下面几篇文章进行拓展:
