[整理]Matlab 之中心平滑濾波


滑動平均(moving average):在地球物理異常圖上,選定某一尺寸的窗口,將窗口內的所有異常值做算術平均,將平均值作為窗口中心點的異常值。按點距或線距移動窗口,重復此平均方法,直到對整幅圖完成上述過程,這種過程稱為滑動平均。

滑動平均相當於低通濾波,在重力勘探和測井資料處理解釋中常用此方法。

如果滑動窗長為 n 的話,滑動平均就是讓數據通過一個 n 點的 FIR 濾波器,濾波器抽頭系數都是 1,這樣取滑動平均就是起到序列平滑的作用。

Matlab 中有多種滑動平均方法,比如 filter 和 tsmovavg 方法都可以實現。

普通滑動平均

基於filter的普通無權重滑動平均,有關於 filter 函數,可以 doc filter進行詳細信息的查看,這里我們由於只使用了簡單的滑動平均,在此記錄一種簡單的滑動平均方法。

seqOriginal = rand(1,100);
windowSize  = x;
seqFilter   = filter( ones(1, windowSize) / windowSize, 1, seqOriginal );

上述命令實際計算的是:

x表示seqOriginal, y表示seqFilter, a表示windowSize。
y(1) = (1 / a) * x(1);
y(2) = (1 / a) * x(2) + (1 / a) * x(1);
...
y(a) = (1 / a) * x(a) + (1 / a) * x(a - 1) + ... + (1 / a) * x(1);
...
y(i) = (1 / a) * x(i) + (1 / a) * x(i - 1) + ... + (1 / a) * x(i - a + 1);
...

注:該方法由於是計算該點和之前 windowSize 的點的平均值,故其輸出結果相對於原數據趨勢有一個滯后。如果數據量比較少,可能影響較大。

中心滑動平均

還有一種滑動平均的方法為中心滑動平均,數據點位於滑動窗的中心進行平均值的計算。則上述的計算變為(在此為了方便虛數,設a為奇數):

y(1) = (1 / a) * x(1) + (1 / a) * x(2) + ... + (1 / a) * x((a+1) / 2);
y(2) = (1 / a) * x(1) + (1 / a) * x(2) + ... + (1 / a) * x((a+1) / 2 + 1);
...
y((a + 1) / 2) = (1 / a) * x(1) + (1 / a) * x(2) + ... + (1 / a) * x((a+1) / 2) + (1 / a) * x(a);
...
y(i) = (1 / a) * x(i - (a - 1) / 2) + (1 / a) * x(i - (a - 1) / 2 + 1) + ... + (1 / a) * x(i) + ... + (1 / a) * x(i + (a+1) / 2);
...

將上述式子轉換為 Matlab 語句為:

seqOriginal = rand(1,100);
windowSize  = x;
seq1        = filter( ones(1, windowSize / 2 + 1) / windowSize, 1, seqOriginal );
seq2        = filter( ones(1, windowSize / 2 + 1) / windowSize, 1, fliplr(seqOriginal) );
seqFilter   = seq1 + fliplr(seq2) - 1 / windowSize * seqOriginal;

為了方便使用,為其寫了一個 function 函數用來調用。

%fun_CenterAverageFilter
%--
%   seqFilter = fun_CenterAverageFilter(seqOriginal, windowSize)
%   中心滑動平均
%--
%   seqFilter   |Matrix|    濾波后輸出序列  
%   seqOriginal |Matrix|    原始序列
%   windowSize  |Double|    滑動窗口
%--
%Author:    Liu Tong
%History:
%----
%Rev:  1.0
%Date: 2016/12/22
%   create.
%--
function seqFilter = fun_CenterAverageFilter(seqOriginal, windowSize)
seq1        = filter( ones(1, windowSize / 2 + 1) / windowSize, 1, seqOriginal );
seq2        = filter( ones(1, windowSize / 2 + 1) / windowSize, 1, fliplr(seqOriginal) );
seqFilter   = seq1 + fliplr(seq2) - 1 / windowSize * seqOriginal;
end


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM