我想寫一個程序,平滑了一些傳感器數據。用於減少信號數據噪聲的算法?
該傳感器提供了一個閾值輸入0到100.它通常在2個單位左右準確,但閱讀跳躍閱讀。
我每秒獲得很多次輸入,並希望從這個數據中創建動態平均值,而不是那麼跳躍。
如何才能平均近期輸入的方式,使您能夠獲得平滑的移動數字,更精確的數字(與讀數實時保持同步)顯示在界面上?
感謝您的任何幫助。
我想寫一個程序,平滑了一些傳感器數據。用於減少信號數據噪聲的算法?
該傳感器提供了一個閾值輸入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 鎳的加權和,其中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
的值設置爲懶惰,正常或渴望。
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
你可以看到懶計算還沒有達到6
5迭代之後,也許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
。
謝謝,這是一個很好的方向指針。 BUFLEN =緩衝區長度,還是我想要使用的歷史值的數量? – boom
是的,我添加了定義。 – gaborsch
我推薦的是玩弄一些樣本數據,看看你會得到什麼算法和什麼參數(BUFLEN,q)。 – gaborsch