|
分類:[VB.NET/VB2005 以降]
懲りずにすみません。
もう一度「Savitzky-Golayフィルター」と思われるのを作ってみました。
実際のデータで試しもしたのですが、それらしい結果となっていました。
でも最初の2つと最後の2つだけは異常な数値となってしまいます。
結果
result(0) は -1.397782
result(1) は -0.4681684
result(2) は 2
< 中略>
result(98) は 98
result(99) は 100.46817
result(100)は 101.397781
------------------------------------------------------
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'データの作成
Dim da(0 To 100) As Single
For i = 0 To 100
da(i) = i
Next i
'
Dim N As Integer = 5 '窓幅を5
Dim M As Integer = 3 '次数を3
Dim result() As Single
result = SGFilter(da, N, M)
Stop
End Sub
'Savitzky-Golayフィルター
Private Function SGFilter(ByVal data() As Single, ByVal windowSize As Integer, ByVal polyOrder As Integer) As Single()
Dim filteredData(data.Length - 1) As Single
Dim halfWindowSize As Integer = windowSize \ 2
For i As Integer = 0 To data.Length - 1
Dim sum As Double = 0
Dim weightSum As Double = 0
For j As Integer = -halfWindowSize To halfWindowSize
Dim index As Integer = i + j
If index >= 0 AndAlso index < data.Length Then
Dim weight As Double = GetSGWeight(j, windowSize, polyOrder)
sum += data(index) * weight
weightSum += weight
End If
Next
filteredData(i) = CSng(sum / weightSum)
Next
Return filteredData
End Function
Private Function GetSGWeight(ByVal x As Integer, ByVal windowSize As Integer, ByVal polyOrder As Integer) As Double
Dim k As Integer = Math.Abs(x)
Dim numerator As Double = 0
Dim denominator As Double = 0
For m As Integer = 0 To polyOrder
numerator += (2 * m + 1) * Math.Pow(-1, m) * Binomial(polyOrder, m) * Binomial(polyOrder + m, m) * Math.Pow(k, m)
denominator += Binomial(windowSize - 1, m) * Binomial(2 * polyOrder + 1, m) * Math.Pow(k, m)
Next
Return numerator / denominator
End Function
Private Function Binomial(ByVal n As Integer, ByVal k As Integer) As Double
If k = 0 Then
Return 1
End If
Dim result As Double = 1
For i As Integer = 1 To k
result *= (n - i + 1) / i
Next
Return result
End Function
|