濾波演算法集合(中位數、中位數平均、平均、加權平均、一階加權、正太分佈)
阿新 • • 發佈:2019-01-28
/********************************************************************************/ /********************************************************************************/ /*本檔案支援濾波函式: */ /* 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]; }