Moin,
Anbei eine Möglichkeit um 1D Arrays eine "Kantenglättung" zu verpassen. Genutzt wird die übliche Quadratmethode (also 25% des linken Nachbarn + 25% des rechten Nachbarn + 50% der Mitte = Inhalt des neuen Elements).
Wissenswertes:
- Das Array darf nur Zahlen enthalten (int oder float)
- Es wird das gesamte Array verändert, im ersten Element darf also kein UBound stehen
- Für große Unschärfewerte (iSmooth) und große Arrays nimmt die Funktion viel Zeit in Anspruch (ein 5000 Teile Array benötigt ca. 1 Sekunde für 100x Glättung)
- Der letzte Parameter ermöglicht es einzustellen ob Start- und Endpunkt fixiert werden sollen.
- Es wird angenommen, dass der Abstand zwischen zwei Arrayteilen immer gleich ist. Daher ist diese Glättungsmethode für Ereignisse mit Zeitstempel vollkommen ungeeignet.
[Blockierte Grafik: http://i.imgur.com/qLMaFaf.png]
; Nur für die Anzeige im Testskript
#include <Array.au3>
Local $aTest = DefaultArray()
_ArrayDisplay($aTest)
;~ _ArraySmooth($aTest, 15, True)
Local $t = TimerInit()
_ArraySmooth($aTest, 15, False)
ConsoleWrite(TimerDiff($t) & @CRLF)
_ArrayDisplay($aTest)
Func DefaultArray($n = 50) ; Zufälliges Array mit einer Kurve erzeugen
Local $aRet[$n], $o = Random(0, 10)
For $i = 0 To $n - 1 Step 1
$aRet[$i] = Round(Sin($i/5 + $o) * Random(5, 10) + Random(5, 10), 0) + 1
Next
Return $aRet
EndFunc
; #INDEX# =======================================================================================================================
; Title .........: _ArraySmooth
; AutoIt Version : 3.3.14.1
; Date ..........: 02.02.2016
; Modified ......:
; Language ......: Deutsch
; Description ...: Funktion um ein 1D Array welches nur Zahlen enthält zu glätten
; Author(s) .....: Mars
; ===============================================================================================================================
; #CURRENT# =====================================================================================================================
; _ArraySmooth
; ===============================================================================================================================
; #INTERNAL_USE_ONLY# ===========================================================================================================
; __ArraySmooth
; __ArraySum
; ===============================================================================================================================
; #FUNCTION# ====================================================================================================================
; Author ........: Mars
; Description ...: Glättet ein 1D Array welches nur Zahlen enthält mit Quadratischer Unschärfe
; Parameter .....: $aArray - Enthält vom ersten, bis zum letzten Element nur Zahlen
; $iSmooth - Anzahl Durchläufe der Glättfunktion. Höhere Zahlen bedeuten stärkeres glätten
; $bFix - True: Start, und Endpunkt bleiben unverändert, False: Start und Endpunkt werden mit geglättet
; ===============================================================================================================================
Func _ArraySmooth(ByRef $aArray, $iSmooth = 1, $bFix = False)
If Not IsArray($aArray) Then Return SetError(1, 0, 0)
If UBound($aArray, 0) <> 1 Then Return SetError(2, 0, 0)
If Not IsInt($iSmooth) Or $iSmooth < 1 Or $iSmooth > 1e9 Then Return SetError(3, 0, 0)
For $i = 1 To $iSmooth Step 1
$aArray = __ArraySmooth($aArray, $bFix)
Next
EndFunc
; #INTERNAL_USE_ONLY# ===========================================================================================================
; Author ........: Mars
; Description ...: Glättet ein 1D Array ein einziges Mal quadratisch, Rückgabe ist das geglättete Array.
; ===============================================================================================================================
Func __ArraySmooth($aArray, $bFix)
Local $iUBound = UBound($aArray), $aCopy[$iUBound], $nSum = $bFix ? __ArraySum($aArray, 1, $iUBound - 1) : 0, $nSum2
$aCopy[0] = $bFix ? $aArray[0] : 0.75 * $aArray[0] + 0.25 * $aArray[1]
For $i = 1 To $iUBound - 2 Step 1
$aCopy[$i] = 0.25 * $aArray[$i - 1] + 0.5 * $aArray[$i] + 0.25 * $aArray[$i + 1]
Next
$aCopy[$iUBound - 1] = $bFix ? $aArray[$iUBound - 1] : 0.75 * $aArray[$iUBound - 1] + 0.25 * $aArray[$iUBound - 2]
$nSum2 = $bFix ? __ArraySum($aCopy, 1, $iUBound - 1) : 0
If $bFix Then
For $i = 1 To $iUBound - 2 Step 1
$aCopy[$i] *= $nSum/$nSum2
Next
EndIf
Return $aCopy
EndFunc
; #INTERNAL_USE_ONLY# ===========================================================================================================
; Author ........: Mars
; Description ...: Summiert alle Elemente eines 1D Arrays von einem Startpunkt bis zu einem Zielpunkt
; ===============================================================================================================================
Func __ArraySum(ByRef $aArray, $iStart = 0, $iEnd = -1)
If $iEnd = -1 Then $iEnd = UBound($aArray)
Local $n
For $i = $iStart To $iEnd - 1 Step 1
$n += $aArray[$i]
Next
Return $n
EndFunc
Alles anzeigen
Falls es jemand gebrauchen kann, hier ist es
Edit: Hatte noch C&P Fragmente im UDF-Header... Diese wurden entfernt.
Edit2: Erklärung der Quadratmethode.
Jeder Wert aus dem ursprünglichen Array wird in drei Teile mit den Faktoren 1/4 | 1/2 | 1/4 aufgespalten. Der Mittlere Teil wandert "geradeaus" zum Element des neuen Arrays mit gleichem Index, die beiden kleinen Teile wandern zum linken, bzw. rechten Nachbarn. Nach zweimaliger Anwendung dieser Methode ist ein Element des ursprünglichen Arrays also auf fünf Teile mit den Faktoren 1/16 | 4/16 | 6/16 | 4/16 | 1/16 verteilt. In Analogie zum Pascalschen-Dreieck (1x Anwenden = 1 2 1, 2x Anwenden = 1 4 6 4 1, usw) ergibt sich als Grenzwert (viele Anwendungen) eine Normalverteilung. Man sieht, dass trotz der extrem einfachen Überlegung im Endeffekt die mathematisch kompliziertere Gauß'sche Unschärfe angewendet werden kann, ohne irgendwelche nicht elementar integrierbaren Funktionen numerisch zu integrieren, oder sonstige anspruchsvolle Berechnungen durchzuführen.
lg
M