滑动窗口滤波器原理分析及详细代码讲解实现

目录

前言

一、图解滑动窗口滤波器的原理

二、滑动窗口滤波器的特点

三、滑动窗口滤波器的C++代码实现

1、基本思路

2、头文件filter.h

3、源文件filter.cpp

四、滑动窗口滤波器的C代码实现

1、基本思路

2、头文件filter.h

3、源文件filter.c


前言

        在嵌入式开发程序中涉及数据采样如传感器采样,AD采样等如果直接读取信号后,将信号值直接参与后续逻辑处理,若程序无软件滤波,会导致静态或者动态采样时:

        1、信号曲线相对没有那么平滑。

        2、同时可能存在脉冲干扰导致逻辑判断错误。

        在信号处理系统中,输入信号通常含有各种噪声和干扰。为对信号进行准确的测量和控制,必须削弱或滤除被测信号中的噪声和干扰。因此在工程应用需要使用软件滤波,软件滤波也称数字滤波,是通过一定的算法削弱噪声的影响。在实际的开发过程中使用了滑动窗口滤波算法来对传感器的数据采样进行滤波处理。


一、图解滑动窗口滤波器的原理

        1、建立采样窗口滤波窗口,自定义各窗口长度大小。

        2、当数据样本点数未填满采样窗口,对采样窗口内的数据累加做平均值计算。

        例如此时采样窗口内数据采样点只有4个,小于定义的采样窗口长度,则将4个值累加后再做平均值计算。

         3、当数据样本点数已填满采样窗口,进行冒泡排序后,去除n个最大值及最小值后,对滤波窗口内的数据累加做平均值运算。

        例如此时采样窗口内数据采样点有7个,已填满定义长度大小的采样窗口,则分别去除自定义的1个最大值和1个最小值后,对剩余滤波窗口内的数据累加后再做平均值计算。

        4、新的数据样本到来,移除采样窗口中时间最早的点(FIFO),重复上述3操作。


二、滑动窗口滤波器的特点

        1、经过滤波处理后,滤除了噪声干扰,数据波动稳定平滑。

        2、每采样一个新数据,就将最早采集的那个数据丢掉,因此每进行一次采样,就可计算出一个新的平均值,从而加快了数据处理的速度。

        3、可以根据实时性的要求和需要滤波后数据的平滑度来设置采样窗口和滤波窗口的大小。

        4、当采样的数据量非常大时,这时的采样窗口会设置很大,那么窗口需要消耗一定的内存空间。

        5、当采样数据越多,数据实时性越差,当数据突然发生较大变化时,不能被立刻检测到,无法及时处理突发事件。


三、滑动窗口滤波器的C++代码实现

1、基本思路

        1、在工程根目录下新建filter文件夹,将源文件filter.cpp和头filter.h放在文件夹中供修改调用。 

        2、头文件:

        (1)定义滤波算法函数中的可修改宏值;

        (2)声明定义的滤波函数模板;

        (3)使用extern的方式声明实例化后的模板函数。    

        3、源文件:

        (1)定义需要使用滤波算法的函数模板;

        (2)在定义的函数模板后进行函数实例化操作,通过这样的方法实现具体的模板函数。       

2、头文件filter.h

#ifndef _FILTER_H_
#define _FILTER_H_

#define MAX_SENSOR_NUM 9   //使用滤波时的传感器数量
#define MAX_DATA_NUM 9     //最大采样点数量,即采样窗口长度
#define WINDOW_DATA_NUM 5  //滤波窗口长度
//去除采样窗口内最大最小值的数量,这里去除两个最大和两个最小 
#define REMOVE_MAXMIN_NUM ((MAX_DATA_NUM - WINDOW_DATA_NUM)/2)  

//extern double m_dataList[MAX_SENSOR_NUM][MAX_DATA_NUM];

//声明定义的函数模板
template<typename InType> InType Filter_SlidingWindowAvg(int index, InType data);
//使用extern的方式声明实例化后的模板函数,根据实际需要自定义数据类型
extern template short Filter_SlidingWindowAvg(int index, short data);
extern template unsigned int Filter_SlidingWindowAvg(int index, unsigned int data);

#endif

3、源文件filter.cpp

#include <algorithm>
#include "Filter.h"

using namespace std;
//定义各个传感器的数据采样点列表
double m_dataList[MAX_SENSOR_NUM][MAX_DATA_NUM] = {0};
//滑窗均值滤波,使用函数模板可用于适配不同数据类型的采样点
template<typename InType>
InType Filter_SlidingWindowAvg(int index, InType data)   
{
    static int dataNum[MAX_SENSOR_NUM] = {0}; //定义记录传感器的采样点个数
    int i;
    double sum = 0;
    double out = 0;
    double array[MAX_DATA_NUM] = {0};
    
    //数据采样点在采样窗口内移动,FIFO操作
    for(i = MAX_DATA_NUM - 2; i >= 0; i--)
        m_dataList[index][i+1] = m_dataList[index][i];
    
    m_dataList[index][0] = data;
    //数据采样点数量小于采样窗口长度,对采样窗口数据累加后进行平均值运算                                     
    if(dataNum[index] < MAX_DATA_NUM) 
    {
        dataNum[index]++;
        for(i = 0; i < dataNum[index]; i++)
        {
            sum += m_dataList[index][i];
        }
        out = sum / dataNum[index];
    }
    //数据采样点已填满采样窗口,进行排序后,去除n个最大值及最小值后,对滤波窗口内的数据累加后进 
    //行平均值运算   
    else        
    {  
        for(i = 0; i < MAX_DATA_NUM; i++)
        {
            array[i] = m_dataList[index][i];
        }
        //利用C++标准库的sort函数进行排序,这里使用默认的升序
        sort(array, array + MAX_DATA_NUM);
        
        int start = (MAX_DATA_NUM - WINDOW_DATA_NUM) / 2; //start = REMOVE_MAXMIN_NUM
        
        for(i = start; i < start + WINDOW_DATA_NUM; i++)
        {
            sum += array[i];
        }
        out = sum / WINDOW_DATA_NUM;
    }
    return out;
}

//对函数模板进行函数实例化操作,根据实际需要自定义数据类型
template short Filter_SlidingWindowAvg(int index, short data);
template unsigned int Filter_SlidingWindowAvg(int index, unsigned int data);

四、滑动窗口滤波器的C代码实现

1、基本思路

        1、在工程根目录下新建filter文件夹,将头filter.h和源文件filter.c放在文件夹中供修改调用。

        2、头文件:

        (1)定义滤波算法函数中的可修改宏值;

        (2)声明定义的滤波算法函数;

        3、源文件:

        (1)定义冒泡排序功能函数;           

        (2)定义滤波算法功能函数。        

2、头文件filter.h

#ifndef _FILTER_H_
#define _FILTER_H_

#define MAX_SENSOR_NUM 9   //使用滤波时的传感器数量
#define MAX_DATA_NUM 9     //最大采样点数量,即采样窗口长度
#define WINDOW_DATA_NUM 5  //滤波窗口长度
//去除采样窗口内最大最小值的数量,这里去除两个最大和两个最小 
#define REMOVE_MAXMIN_NUM ((MAX_DATA_NUM - WINDOW_DATA_NUM)/2)  

//extern double m_dataList[MAX_SENSOR_NUM][MAX_DATA_NUM];

//声明定义的函数
double Filter_SlidingWindowAvg(int index, double data);

#endif

3、源文件filter.c

#include "Filter.h"

//定义各个传感器的数据采样点列表
double m_dataList[MAX_SENSOR_NUM][MAX_DATA_NUM] = {0};

//冒泡排序
void BubbleSort(double array[], int len)
{
    int temp;
    //外层循环控制排序的趟数,n个元素排序需要循环n-1次
    for(int i=0; i<len-1; i++) 
    {
        //内层循环控制比较的次数,n个元素第i趟比较n-i次 
        for(int j=0; j<len-1-i; j++) 
        {
            //比较相邻的元素大小 目的:将最大的元素选出到移动到最后 
            if(array[j] > array[j+1])
            {
                temp = array[j];
                array[j] = array[j+1];
                array[j+1] = temp;
            }
        }
    }
}

//滑窗均值滤波,这里采样点data数据类型和滤波后返回值数据类型都是double,实际使用可根据需要定义
//其他数据类型
double Filter_SlidingWindowAvg(int index, double data)   
{
    static int dataNum[MAX_SENSOR_NUM] = {0}; //定义记录传感器的采样点个数
    int i;
    double sum = 0;
    double out = 0;
    double array[MAX_DATA_NUM] = {0};
    
    //数据采样点在采样窗口内移动,FIFO操作
    for(i = MAX_DATA_NUM - 2; i >= 0; i--)
        m_dataList[index][i+1] = m_dataList[index][i];
    
    m_dataList[index][0] = data;
    //数据采样点数量小于采样窗口长度,对采样窗口数据累加后进行平均值运算                                     
    if(dataNum[index] < MAX_DATA_NUM) 
    {
        dataNum[index]++;
        for(i = 0; i < dataNum[index]; i++)
        {
            sum += m_dataList[index][i];
        }
        out = sum / dataNum[index];
    }
    //数据采样点已填满采样窗口,进行排序后,去除n个最大值及最小值后,对滤波窗口内的数据累加后进 
    //行平均值运算   
    else        
    {  
        for(i = 0; i < MAX_DATA_NUM; i++)
        {
            array[i] = m_dataList[index][i];
        }
        //调用冒泡排序函数
        BubbleSort(array, MAX_DATA_NUM);

        int start = (MAX_DATA_NUM - WINDOW_DATA_NUM) / 2; //start = REMOVE_MAXMIN_NUM
        
        for(i = start; i < start + WINDOW_DATA_NUM; i++)
        {
            sum += array[i];
        }
        out = sum / WINDOW_DATA_NUM;
    }
    return out;
}

↓↓↓更多技术内容和书籍资料获取,入群技术交流敬请关注“明解嵌入式”↓↓↓

   

以下是GEE基于滑动窗口法主成分分析合成遥感图像的JavaScript代码实现的一个示例: ```javascript // 设置滑动窗口的大小,这里设为3x3的口 var windowSize = 3; // 加载需要进行主成分分析的遥感图像 var image = ee.Image('LANDSAT/LC08/C01/T1_TOA/LC08_123032_20140515'); // 获取图像的波段数 var numBands = image.bandNames().size(); // 定义一个滑动窗口的核心函数 var slidingWindow = function(img) { // 将图像转换为一个数组 var arr = img.toArray(); // 获取图像的行和列数 var rows = img.size()[0]; var cols = img.size()[1]; // 定义一个空的结果数组 var out = ee.List([]); // 循环遍历每一个像素点 for (var i = windowSize; i <= rows - windowSize; i++) { for (var j = windowSize; j <= cols - windowSize; j++) { // 定义一个滑动窗口 var window = arr.slice(i - windowSize, j - windowSize, i + windowSize + 1, j + windowSize + 1); // 将滑动窗口转换为一个矩阵 var windowMatrix = ee.Array(window); // 对矩阵进行主成分分析 var pca = windowMatrix.reduceRegion({ reducer: ee.Reducer.pca(numBands), geometry: ee.Geometry.Rectangle(i - windowSize, j - windowSize, i + windowSize, j + windowSize), scale: 30 }); // 将主成分分析的结果添加到结果数组中 out = out.add(ee.Feature(null, pca)); } } // 将结果数组转换为一个特征集合 return ee.FeatureCollection(out); }; // 对图像进行滑动窗口主成分分析 var pcaImage = slidingWindow(image); // 将主成分分析的结果可视化 Map.addLayer(pcaImage, {}, 'PCA Image'); ``` 需要注意的是,这只是一个简单的示例,实际应用中可能需要对代码进行调整以满足不同的需求。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sharemaker

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值