burgessmaggie 发表于 2024-11-20 10:04

中值滤波实战

遇到一个强的干扰信号,平均之后数据是无法反应出正确的信号的,这个时候,中值滤波的优势就体现出来了。中值滤波在数据处理中的角色就是一个和事佬,把数据中的“刺头”剔除出去。如下图所示:https://i0.hdslb.com/bfs/article/9b5ca6e5dc883dcdd335edeaec8e3ded3c17d6c3.png@1192w.webp//阶数怎么确定后面会解释 一般来说可以试出来#defineORDER10            //阶数#define    N    ((ORDER) / 2) //判断中值位置的值    //这里需要判断值得有效性    //assert(pSrc);    //assert(pDst);    //assert(blockSize);/* 数据幅值给临时缓冲 这里要先填充ORDER个数据才能滤波 也可以用for*/    //for(i = 0; i < blockSize; i++)   //{   //DataBuffer = pSrc;   //}    memcpy(DataBuffer,pSrc,sizeof(DataBuffer));/* 求每个数据点的中值为什么blocksize要减去阶数呢?因为采集够10个数据才能开始滤波,滤出来的第一个数据其实要放在10/2=5的位置才能对的上相位,同理可得数据只能过滤到倒数5个的位置,所以数据过滤后比过滤前数据其实会少阶乘个,因为前后5个都是没有足够的数据进行滤波的,实际采样可以多采集ORDER个数据就能得到想要长度的滤波数据*/for(i =0; i < blockSize-ORDER; i++){    /* 排序 排序算法可以自己选择 这里就不放排序代码了 排序里面做的就是把DataBuffer数据copy一份后排序到SortData*/    sort(DataBuffer, SortData, ORDER);    //下面这个判断应该很好理解 就是判断ORDER阶数的中值位置,排序后直接取到中值    /* 奇数 */    if(N)    {      pDst = SortData;    }    /* 偶数 */    else    {      pDst = (SortData + SortData)/2;    }//第二种 边采集数据边处理数据/***********************************************************************************************************函 数 名: MidFilterRT*功能说明: 逐个数据实时滤波的中值滤波器。*形    参: pSrc 源数据地址。*             pDst 滤波后数据地址。*             ucFlag 1表示首次滤波,后面继续滤波,需将其设置为0。*             ORDER 至少3阶。*   注    意:阶数不给设置2是因为我认为2的话就是平均值了,两个值取中值就只能是平均了 *             类型可以根据自己需要进行修改*返 回 值: 无**********************************************************************************************************/void MidFilterRT(uint16_t *pSrc, uint16_t *pDst, uint8_t ucFlag){    uint16_t i;    static uint32_t Count = 0;//这里要注意溢出的时候 可能会出问题   static uint16_t DataBuffer;//数据缓冲 设置成阶数大小就行了,不需要设置成数据量大小,会造成浪费    uint16_t SortData;//排序后的数据    /* 排序 排序算法可以自己选择 这里就不放排序代码了 排序里面做的就是把DataBuffer数据copy一份后排序到SortData*/    sort(DataBuffer, SortData, ORDER);    //下面这个判断应该很好理解 就是判断ORDER阶数的中值位置,排序后直接取到中值    /* 奇数 */    if(N)    {      pDst = SortData;    }    /* 偶数 */    else    {          pDst = (SortData + SortData)/2;    }}uint16_t testdata = {104,104,101,103,102,104,103,102,102,104,102,104,101,103,102,101,102,102,103,104,101,103,102,104,130,132,102,105,104,103,103,102,103,101,104,103,105,104,102,102,103,101,104,104,104,101,104,101,103,105,103,105,104,104,102,102,103,104,104,104,102,104,104,103,101,101,102,103,103,102,104,101,103,80,80,102,101,104,105,102,104,104,103,103,104,104,102,103,104,102,105,104,104,103,103,105,105,102,103,105};/*******************************************************************************************函 数 名: MidFilterBlockTest*功能说明: 整块数据的中值滤波测试*形    参: 无*返 回 值: 无******************************************************************************************/void MidFilterBlockTest(void){for(int i = 0; i < TEST_LENGTH_SAMPLES; i++){   printf("%d %d\r\n", testdata, DstDate);}}至此,中值滤波的应用代码就完成了,下面再解释一下编写过程存在的可能让人疑惑的点:1、上面填充数据部分是什么意思?怎么实现DataBuffer = pSrc;DataBuffer = pSrc;这两个呢就是队列的思想:先进先出,把新的数据放进来,把最老的数据踢出去,因为我们不需要保留原来的数据缓冲中的数据之间的相对位置,只是需要把他们维持在一个数组内就行,所以一直填充新的数据,一直把最老的数据踢掉,(取余操作在ORDER是2的n次方的时候可以换成&,以后会出一期解释)如图所示:https://i0.hdslb.com/bfs/article/e8d7a2011213f4c3f137bb8ed0418305a074a24a.png@1192w.webp
2、阶数应该怎么确定一般来说,中值滤波主要是过滤掉脉冲噪声,主要是看你需要处理的这个脉冲噪声,理想点考虑的话:
https://i0.hdslb.com/bfs/article/4aa6904b4fca449ab0538fdefbaa6336619f20fc.png@948w.webp连续两个点的话就是5个一般来说阶数可以直接试出来,就先把原始数据采集好放进excel表中,用MEDIAN()公式求中值,多少阶就扫多少个数据(以3阶为例),试出一个满意的效果:https://i0.hdslb.com/bfs/article/5521380a9fa9f928967567384b6409a64d16b55a.png@402w_658h.webp
3、阶数的大小会影响什么?前面有讲过,要采完滤波阶数大小的点才算开始真正的滤波,所以阶数越大,信号处理的结果延迟就越大,信号就越迟缓,同时增大排序的处理数据量,造成单个数据点的计算就越久。

页: [1]
查看完整版本: 中值滤波实战