1. 程式人生 > >濾波演算法集合(中位數、中位數平均、平均、加權平均、一階加權、正太分佈)

濾波演算法集合(中位數、中位數平均、平均、加權平均、一階加權、正太分佈)

/********************************************************************************/
/********************************************************************************/
/*本檔案支援濾波函式:                                                           */   
/*                 0、取中位數                                                  */                         
/*                 1、取中位數平均                                              */
/*                 2、取平均                                                    */
/*                 3、取加權平均                                                */
/*                 4、一階加權                                                  */
/*                 5、正太分佈                                                  */
/******************請根據具體的應用需求進行濾波選擇********************************/
/********************************************************************************/
/********************************************************************************/
/********************************************************************************/
#define WAVEFILTERINGBUFMAXLENG  100   //濾波快取最大的資料長度,根據個人應用以及程式空間進行修改,最大不超過255
#define u8     unsigned char 
#define u16     unsigned int 


u8 WaveFilteringMode = 0;                       //濾波模式 0-4 選擇
u8 WaveFilteringLength = 0;                     //濾波長度
u8 WaveFilteringEnable= 0;                     //濾波開關

u16 WaveFilteringBuf[WAVEFILTERINGBUFMAXLENG];  //資料計算快取buf,資料快取最大255 將遞迴的資料賦值給快取進行排布計算,避免計算排序導致原始資料順序錯誤
u16 CCDEdgeLeftWaveFilteringBuf[WAVEFILTERINGBUFMAXLENG];   //CCD左邊緣資料濾波快取區域
u16 CCDEdgeRightWaveFilteringBuf[WAVEFILTERINGBUFMAXLENG];  //CCD右邊緣資料濾波快取區域



/*******************************************************

  //函式名稱:u16 Wave_Filter(char type,u8 time,u16 data,u16* ptr)
  //功能描述:濾波函式
  //修改日誌:2018.04.10
  //函式介面:type 濾波型別參看下面註釋    time 濾波係數  data 最新接收資料  ptr 儲存資料地址
*******************************************************
  ////濾波演算法說明   濾波係數設定最大為255 
                    

0  //// Median                   中位數濾波               排序後提取中位資料,如果設定係數為偶數去中間較小的那個 例如係數為4 2對應的資料。
1  //// Median average           中位值平均濾波           對取樣資料去除最大值與最小值進行平均運算。 
2  //// Recursive mean           遞推平均濾波             遞推平均濾波又稱為滾動平均濾波 採用佇列形式每次接收新的後拋棄最早的那個資料後求平均值。                
3  //// Weighted recursive mean  加權遞推平均濾波法       對取樣資料進行加權,然後在取平均值。越新的資料加權值越大。
4  ////                          一階滯後濾波法           本次濾波結果=新取樣值×濾波係數÷256+上次濾波結果×(256-濾波係數)÷256 
*******************************************************
  //函式返回值: 補償完成後的資料。
  
  //首版建立2018.04.10    版本:V1.00      修改人:szp

*******************************************************/

u16 Wave_Filter(u8 type,u8 bufleng,u16 data,u16* ptr)
{
	u8 i = 0,j = 0;
	u16 num = 0;
    
    if(bufleng > WAVEFILTERINGBUFMAXLENG)
    {
        return 0;
    }
    
	for(i = 0; i < bufleng-1; i++) 
	{
		*(ptr+i) = *(ptr+i+1);                          //緩 存佇列 
		 WaveFilteringBuf[i] = *(ptr+i);                //將遞迴的資料賦值給快取進行排布計算,避免計算排序導致原始資料順序錯誤
	}
	*(ptr + bufleng - 1) = data;                               //更新最新的資料
     WaveFilteringBuf[i] = data;                        //最後一個數也賦值
	
	if(type < 2)
	{	
		for(i = 0; i < bufleng-1; i++)                      //此處使用冒泡法進行排序,排序為升序。
		{ 
			for(j = 0; j < (bufleng - i-1);j++)
			{
				if(*(WaveFilteringBuf+j) > *(WaveFilteringBuf+j+1))
				{
					*(WaveFilteringBuf+j) = (*(WaveFilteringBuf+j) + *(WaveFilteringBuf+j+1));
					
					*(WaveFilteringBuf+j+1) = (*(WaveFilteringBuf+j) - *(WaveFilteringBuf+j+1));
					
					*(WaveFilteringBuf+j) = (*(WaveFilteringBuf+j) - *(WaveFilteringBuf+j+1));					
				}
			}	
		}		
	}

	switch(type)
	{
		case 0x00:
			i = bufleng/2;                                        //獲取佇列長度的中位
		    num = *(WaveFilteringBuf+i);                       //獲取佇列長度的中位值。        
			break;
		case 0x01:
			num = Sum_Count(bufleng-2,WaveFilteringBuf+1);       //計算中位平均值,拋棄開頭和結尾最大與最小值,頭部拋棄資料需要自己自行設定
			break;
		case 0x02:
			num = Sum_Count(bufleng,WaveFilteringBuf);           //直接計算平均值
			break;
		case 0x03:
			num = Sum_Weighted(bufleng, WaveFilteringBuf);       //計算加權平均值,
			break;
		case 0x04:
			num = First_Filter(256 - bufleng ,data);              //使用這種濾波方式,濾波係數越小濾波效果越好。
			break;
		default:
			num = data;
			break;
	}
	
	return num;
	
}







/**********************************************************************************************
 *【函 數 名】: u16 bubble_sort(s16 buf, u16 num)
 *【功    能】:氣泡排序,從小到大排序,返回中位數
 *【介面變數】: 
 *【內部變數】:無 
 *【返 回 值】:中位數
 *【撰 寫 人】:szp  撰寫日期:2018年4月12日
 *【修 改 人】:         修改日期:                修改原因:
 ***********************************************************************************************/
u16 bubble_sort(u16 *buf,u8 bufleng)
{
    u8 i = 0;
    u8 j = 0;
    u16 temp = 0;
    if(bufleng > WAVEFILTERINGBUFMAXLENG)
    {
        return 0;
    }
    for( i=0; i<bufleng; i++)
    {
		WaveFilteringBuf[i] = buf[i];//將buf值進行儲存在進行計算,避免修改原buf的數值
	}
    for( i=0; i<bufleng-1; i++)
    {
        //每一輪比較前n-1-i個,即已排序好的最後i個不用比較
        for(j=0; j<bufleng-1-i; j++)
        {
            if(WaveFilteringBuf[j] > WaveFilteringBuf[j+1])
            {
                temp = WaveFilteringBuf[j];
                WaveFilteringBuf[j]   = WaveFilteringBuf[j+1];
                WaveFilteringBuf[j+1] = temp;
            }
        }
    }
    bufleng =  bufleng /2;
    return WaveFilteringBuf[bufleng];
}
/**********************************************************************************************
 *【函 數 名】:void Recursion_buf(u16 *buf, u8 num, u8 bufleng)
 *【功    能】:遞迴函式,  最新進來的資料把最早進來的資料推出
 *【介面變數】: 
 *【內部變數】:無
 *【返 回 值】:無
 *【撰 寫 人】:邵志鵬   撰寫日期:2018年4月12日
 *【修 改 人】:         修改日期:                修改原因:
 ***********************************************************************************************/
void Recursion_buf(u16 *buf, u8 Newdata, u8 bufleng)
{
	u8 i = 0;
    if(bufleng > WAVEFILTERINGBUFMAXLENG)
    {
        return ;
    }
    
	for(i = 0; i < bufleng ; i ++)
	{
		buf[i] = buf[i+1];
	}
	buf[bufleng - 1] = Newdata; 
}
/**********************************************************************************************
 *【函 數 名】:u16 Sum_Count(u8 time, u16* ptr)
 *【功    能】:求和函式
 *【介面變數】: 
 *【內部變數】:無
 *【返 回 值】:無
 *【撰 寫 人】:szp   撰寫日期:2018年4月12日
 *【修 改 人】:         修改日期:                修改原因:
 ***********************************************************************************************/
u16 Sum_Count(u8 bufleng, u16* ptr)
{
	u8 i = 0;
	u32 num = 0;
    
	if(bufleng > WAVEFILTERINGBUFMAXLENG)
    {
        return 0;
    }
	for(i = 0; i < bufleng; i++)
	{
		num += *(ptr+i);
	}
	return num/bufleng;
}
/**********************************************************************************************
 *【函 數 名】:u16 Sum_Weighted(u8 time, u16* ptr)
 *【功    能】:計算加權平均
 *【介面變數】: 根據進來資料的先後順序給資料乘以對應係數,全部資料去和之後再去平均值。最新進來的資料權重最大
 *【內部變數】:無
 *【返 回 值】:無
 *【撰 寫 人】:szp   撰寫日期:2018年4月12日
 *【修 改 人】:         修改日期:                修改原因:
 ***********************************************************************************************/
u16 Sum_Weighted(u8 bufleng, u16* ptr)
{
	u8 i = 0;
	u16 data = 0;
	u32 num = 0;
	if(bufleng > WAVEFILTERINGBUFMAXLENG)
    {
        return 0;
    }
	for(i = 0; i < bufleng; i++)
	{
		num += (*(ptr+i)*i);      //計算加權和
		
		data += i;                //計算權值。
	}
	
	return num/data;
}
/**********************************************************************************************
 *【函 數 名】:u16 First_Filter(u8 time,u16 data)
 *【功    能】:一階濾波函式
 *【介面變數】: 
 *【內部變數】:無
 *【返 回 值】:無
 *【撰 寫 人】:szp   撰寫日期:2018年4月12日
 *【修 改 人】:         修改日期:                修改原因:
 ***********************************************************************************************/
u16 First_Filter(u8 bufleng,u16 data)
{
	double  buff = 0.0;
	u16 num = 0;
	
	static double Old_data = 1.1;
	
    if(bufleng > WAVEFILTERINGBUFMAXLENG)
    {
        return 0;
    }
    
	buff = data*bufleng/256.0 + Old_data*(256 - bufleng) /256.0;   //計算濾波值
	
	Old_data = buff;
	
	num = buff;
	
	return num;

}

/**********************************************************************************************
 *【函 數 名】: u16 Calculated_normal_distribution(s16 buf, u16 num)
 *【功    能】:計算陣列資料的正太分佈,找出陣列中佔比最大的資料
 *【介面變數】: 
 *【內部變數】:無
 *【返 回 值】:無
 *【撰 寫 人】:szp   撰寫日期:2017年5月6日
 *【修 改 人】:         修改日期:                修改原因:
 ***********************************************************************************************/
u16 Calculated_normal_distribution(u16 *buf, u8 bufleng)
{  
     u8 i = 0;
     u8 j = 0;
     u8 maxnumbuf = 0;
     u8 maxnum = 0;
    
    if(bufleng > WAVEFILTERINGBUFMAXLENG)
    {
        return 0;
    }
    
    
    for(i = 0; i < bufleng ;i++)
    {
        WaveFilteringBuf[i] = 0;//清空技術buf的值offset_num_buf 不能放置為區域性變數容易出現記憶體溢位
    }    
    /*依次遍歷整個buf,統計當前選擇buf的值與後面值相同的個數*/
    for(i = 0; i < bufleng; i++)                                                                      
    {                                                                                           
        for( j = i+1; j < bufleng; j++)                                                            
        {                                                                                       
            if(buf[i] == buf[j])                                                                    
            {                                                                                   
                WaveFilteringBuf[i]++; // 統計buf[i] 之後所有與buf[i] 值相同的個數      
            }                                                                                   
        }                                                                                       
    }                                                                                                
    maxnumbuf = WaveFilteringBuf[0];  //找到重複次數最多的那個數重複的次數
    maxnum = 0;
    for(j = 1; j < bufleng; j++)                                                                  
    {                                                                                           
        if(maxnumbuf < WaveFilteringBuf[j])                                                                          
        {                                                                                       
            maxnumbuf = WaveFilteringBuf[j];   
            maxnum = j;   //查詢最大個數的位置
        }                                                                                       
    } 
    /*buf中出現次數對多的個數為 maxnumbuf+1  */
    return buf[maxnum];
}