[英]Algorithm for reducing noise from signal data?
我正在嘗試編寫一個程序來平滑一些傳感器數據。
傳感器提供0到100的閾值輸入。它通常精確到2個單位左右,但讀數是跳躍的。
我每秒輸入很多次,並希望從這些數據中創建動態平均值,而不是那么跳躍。
如何以一種可以獲得平滑移動數字,更准確數字(與讀數實時保持在一起)顯示在界面上的方式來平均最近的輸入?
謝謝你的幫助。
根據您的數據,您可以通過計算平均值來平衡測量值。
使用一定數量的先前結果
int values[BUFLEN]; value = // your new raw measured value index = index++ % BUFLEN; values[index] = value; avg = 0; for(int i=0; i<BUFLEN; i++) { avg = avg + values[i] / BUFLEN; // evenly weighted }
如果你願意,也可以使用不均勻的重量。 此外,如果您使用相同的權重,則可以優化此循環。
使用浮動平均值
avg = (avg * 0.9) + (value * 0.1) // slow response avg = (avg * 0.5) + (value * 0.5) // fast response float q = // new ratio avg = (avg * (1.0 - q)) + (value * q) // general solution
浮動平均值(數學上)是所有元素的加權和,其中權重是q Ni ,其中N
是總測量值, i
是元素的運行索引。 所有元素都涉及平均值,而不僅僅是有限數量的元素。
您可以檢查錯誤措施的頻率,與平均值的距離是什么,您希望您的(計算的)措施遵循實際流程的響應等等。
此外,如果你有離散值(整數),你必須小心使用舍入的東西。 我建議以浮點進行所有計算,然后將結果舍入到最接近的整數。 但是將計算的平均值存儲在下一輪的浮點數中。
更新:
為了反映您在同一時間保持最新和准確的問題:
問題是我們不確定最新數據是顯示趨勢還是錯誤閱讀的結果。 我會告訴你一個例子:
SEQ1: 15 15 14 15 15 [10] 6 6 5 6 6
SEQ2: 15 15 14 15 15 [10] 20 15 14 15 15
那么, [10]
在每個序列中意味着什么:在第一個序列中,它代表一個嚴肅的運動,一個趨勢。 在第二個中,這只是一個誤讀。 但是當你剛讀完[10]
,你不知道下一個是什么。 所以,你必須延遲讀取的效果。 所以,它不會是最新的 。
同樣,您使用的是平均值,即計算值。 所以,它不准確 。
這是一種平衡的情況 。 值越新,准確性越低(誤讀的次數越多)。 數據越准確,延遲就越大。 根據數據系列,您必須明智地選擇它。
我使用第二種(浮動平均)算法為您計算了三種情景。 q
的值設置為lazy , normal或eager 。
SEQ1: 15 15 14 15 15 10 6 6 5 6 6
// q=0.25, "lazy"
Avg 15.00 15.00 14.75 14.81 14.86 13.64 11.73 10.30 8.98 8.23 7.67
Rounded 15 15 15 15 15 14 12 10 9 8 7
// q=0.5, "normal"
Avg 15.00 15.00 14.50 14.75 14.88 12.44 9.22 7.61 6.30 6.15 6.08
Rounded 15 15 15 15 15 12 9 7 6 6 6
// q=0.75, "eager"
Avg 15.00 15.00 14.25 14.81 14.95 11.23 7.31 6.33 5.33 5.83 5.96
Rounded 15 15 14 15 15 11 7 6 5 5 6
您可以看到延遲計算在5次迭代后仍未達到6
,可能還需要3次。
正常幾乎不容易出錯,(14.5只是四舍五入),但幾乎可以立即跟隨趨勢。
渴望熱切關注這些措施,只是略微緩解曲線。 它甚至無法檢測到15-14-15的錯誤讀數。
該系列的最佳值之上將約為0.4
- 0.45
我想。 有必要使用實際測量數據的樣本來查看什么是參數值的行為。
實際上我最喜歡的是浮動平均算法,它易於實現並且給出了良好的結果(如果參數化良好)。
免責聲明:這將導致非常平滑的結果 - 即使在此期間價值上下波動,這可能只是顯示一條直線。 這將顯示平均隨時間的變化。 如果不希望這樣,這個答案可能不是你想要的。
假設我們對最后的k
輸入值進行平均。
首先要注意的是:
Average at time i = (value[i] + value[i-1] + ... + value[i-k+1]) / k
= value[i]/k + value[i-1]/k + ... + value[i-k+1]/k
and
Average at time i-1 = value[i-1]/k + value[i-2]/k + ... + value[i-k+2]/k
thus, cancelling out common terms...
Average at time i = Average at time i-1 + value[i]/k - value[i-k+2]/k
並且,為了避免潛在的舍入問題,請將除以k
除以 - 除非得到平均值(這樣做不會使數學無效)。
那么,對於算法:
k
的圓形數組。 將此數組中的所有值初始化為0。 average = newValue - overriddenValue
k
則增加計數。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.