Moin,
Habe für einen Unschärfealgorithmus (in Go, daher gibts hier keinen AutoIt-Code) verschiedene Integrale der Gaußkurve gebraucht. Zum Glück konnte mir AspirinJunkie mit seiner Stat-UDF aushelfen. Für den extrem unwahrscheinlichen Fall, dass irgendjemand manuell einen Gauß-Filter basteln möchte (und noch einen Filterkern braucht) kann er sich gerne an meinem Skript dazu bedienen. Sowas kann man sich auch auf die Schnelle selbst zusammenbasteln, aber schön aufgeräumt/formatiert sieht es doch besser aus, villeicht spart dieses Skript irgendwem 5 Minuten seiner Lebenszeit ein, dann bin ich schon zufrieden
#include-once
; #INDEX# =======================================================================================================================
; Title .........: GaussKernel (23.07.18)
; AutoIt Version : BETA 3.3.15.x -> Nur knapp getestet, ob es mit der BETA und der STABLE
; STABLE 3.3.14.x -> Probleme gibt. Lief bei beiden wie erwartet.
; Date ..........: 23.07.18
; Modified ......: -
; Language ......: Deutsch
; Description ...: Aus welchen Gründen auch immer man einen GaussKernel (z.B. für einen Unschärfefilter) brauchen sollte, hier be
; kommt man einen.
; Author(s) .....: Mars@AutoIt.de
; Diebstahl .....: Es werden Funktionen von AspirinJunkie@AutoIt.de verwendet.
; ===============================================================================================================================
; #CURRENT# =======================================================================================
; _GK_KernelCreate
; _GK_KernelExportToConsole
; =================================================================================================
; #INTERNAL_USE_ONLY# =============================================================================
; __GK_ArraySumLeft
; __GK_Exit
; __GK_FormatNormGK
; __GK_FormatREM
; __GK_KernelCreate
; __GK_LoadMSVCR
; __GK_ReminderCreate
; __GK_stat_erfc
; __GK_stat_norm_cdf
; =================================================================================================
Global $h_DLL_MSVCR = __GK_LoadMSVCR()
OnAutoItExitRegister('__GK_Exit')
; #EXAMPLE# =======================================================================================
If @ScriptName = 'GaussKernel.au3' Then
; Kernel erstellen mit
; Radius = 10 Pixel -> Durchmesser = 21 Pixel
; Sigma = 2.5 -> 98.7% sind innerhalb
; Digits = 4 -> 4 Kommastellen Genauigkeit
Local $aKernel = _GK_KernelCreate(10, 2.5, 4)
; In der Konsole anschauen
; Kernel = $aKernel -> Den haben wir gerade erstellt
; Mode = 'Go' -> Kann man C&P in Go einfügen.
ConsoleWrite(@CRLF)
_GK_KernelExportToConsole($aKernel, 'Go')
ConsoleWrite(@CRLF)
; In der Konsole anschauen
; Kernel = $aKernel -> Den haben wir gerade erstellt
; Mode = 'Excel' -> Falls man ein Diagramm mit Excel will. Excel liebt Kommas ,,,,....
_GK_KernelExportToConsole($aKernel, 'Excel')
ConsoleWrite(@CRLF)
EndIf
; =================================================================================================
; #FUNCTION# ======================================================================================
; Name ..........: _GK_KernelCreate()
; Description ...: Create GaussKernel and Reminder arrays with given params
; Syntax ........: _GK_KernelCreate($iRadius[, $fSigma = 2[, $iDigits = 5]])
; Parameters ....: $iRadius -
; $fSigma - [optional] (default:2)
; $iDigits - [optional] (default:5)
; Return values .: Array[0] - Array[$iRadius * 2 + 1] = GaussKernel values
; Array[1] - Array[$iRadius] = Reminder values
; Array[2] - Float = Radius (ist IMMER ein INT.5 oder INT Wert)
; Array[3] - Float = Sigma
; Null - @error = 1 -> Radius is no integer
; Author ........: Mars
; =================================================================================================
Func _GK_KernelCreate($iRadius, $fSigma = 2, $iDigits = 5)
If Not IsInt($iRadius) Then Return SetError(1, 0, Null)
$iRadius = $iRadius * 2 + 1 ; Es gibt NUR ungerade Kernels, ein Pixel muss in der "Mitte" sein.
Local $aGaussKernel = __GK_KernelCreate($iRadius, $fSigma)
__GK_FormatNormGK($aGaussKernel, $iDigits)
Local $aReminder = __GK_ReminderCreate($aGaussKernel)
__GK_FormatREM($aReminder, $iDigits)
Local $aRet = [$aGaussKernel, $aReminder, StringFormat('%.1f', $iRadius / 2), $fSigma]
Return $aRet
EndFunc ;==>_GK_KernelCreate
; #FUNCTION# ======================================================================================
; Name ..........: _GK_KernelExportToConsole()
; Description ...: Console output with Copyable Kernels für different purposes
; Syntax ........: _GK_KernelExportToConsole($iRadius[, $fSigma = 2[, $iDigits = 5]])
; Parameters ....: $aKernel - Das was aus _GK_KernelCreate herauskommt
; $sMode - [optional] (default:'Excel')
; Return values .: -
; Null - @error = 1 -> $aKernel is no Array
; Null - @error = 2 -> $sMode is not supported
; Author ........: Mars
; =================================================================================================
Func _GK_KernelExportToConsole($aKernel, $sMode = 'Excel')
If Not IsArray($aKernel) Then Return SetError(1, 0, Null)
Local $aGaussKernel = $aKernel[0], $aReminder = $aKernel[1]
Switch $sMode
Case 'Go'
ConsoleWrite('# Go #' & @CRLF)
ConsoleWrite('// GaussKernel' & @CRLF & '// Radius = ' & $aKernel[2] & ' | Sigma = ' & StringFormat('%.3f', $aKernel[3]) & @CRLF)
ConsoleWrite('gauss' & UBound($aGaussKernel) & ' = [...]float32{')
For $i = 0 To UBound($aGaussKernel) - 1 Step 1
ConsoleWrite($aGaussKernel[$i] & ($i = UBound($aGaussKernel) - 1 ? '' : ', '))
Next
ConsoleWrite('}' & @CRLF & 'remind' & UBound($aGaussKernel) & ' = [...]float32{')
For $i = 0 To UBound($aReminder) - 1 Step 1
ConsoleWrite($aReminder[$i] & ($i = UBound($aReminder) - 1 ? '' : ', '))
Next
ConsoleWrite('}' & @CRLF)
Case 'Excel'
ConsoleWrite('# Excel #' & @CRLF)
For $i = 0 To UBound($aGaussKernel) - 1 Step 1
ConsoleWrite(StringReplace($aGaussKernel[$i], '.', ',', 0, 1) & @TAB)
Next
ConsoleWrite(@CRLF)
Case Else
Return SetError(2, 0, Null)
EndSwitch
EndFunc ;==>_GK_KernelExportToConsole
; #INTERNAL# ======================================================================================
; Author ........: Mars
; =================================================================================================
Func __GK_ArraySumLeft(ByRef $a, $i)
Local $iSum = 0
For $ii = 0 To $i Step 1
$iSum += $a[$ii]
Next
Return $iSum
EndFunc ;==>__GK_ArraySumLeft
; #INTERNAL# ======================================================================================
; Author ........: Mars
; =================================================================================================
Func __GK_Exit()
DllClose($h_DLL_MSVCR)
EndFunc ;==>__GK_Exit
; #INTERNAL# ======================================================================================
; Author ........: Mars
; =================================================================================================
Func __GK_FormatNormGK(ByRef $aGaussKernel, $iDigits = 5)
Local $iSum = 0, $iLen = UBound($aGaussKernel), $rewind = False, $index = -1, $iTmp, $iSum2 = 0
For $i = 0 To $iLen - 1 Step 1
$iSum2 += $aGaussKernel[$i]
Next
For $i = 0 To $iLen - 1 Step 1 ; Normieren und Formatieren
$aGaussKernel[$i] = StringFormat('%.' & $iDigits & 'f', $aGaussKernel[$i] / $iSum2)
$iSum += $aGaussKernel[$i]
Next
For $i = 0 To Int($iLen / 2) - 1 Step 1 ; Asymmetriecheck, Gott weiß was hier passiert...
$iTmp = $aGaussKernel[$i] - $aGaussKernel[$iLen - $i - 1] ; Das macht im Endeffekt nichts aus, aber es ist schöner.
If Abs($iTmp) >= 10 ^ - ($iDigits + 1) Then ; Das Ergebnis ist dadurch ggf. an der letzten
$rewind = True ; Nachkommastelle um 0.5 falsch.
$index = $i
If $iTmp > 0 Then ; symmetrisch ist.
$aGaussKernel[$iLen - $i - 1] = StringFormat('%.' & $iDigits & 'f', $aGaussKernel[$iLen - $i - 1] + 10 ^ - ($iDigits))
Else
$aGaussKernel[$i] = StringFormat('%.' & $iDigits & 'f', $aGaussKernel[$i] + 10 ^ - ($iDigits))
EndIf
EndIf
Next ; Damit alles auf 1 aufgeht in der Mitte etwas draufrechnen oder abziehen.
$aGaussKernel[Int($iLen / 2)] = StringFormat('%.' & $iDigits & 'f', $aGaussKernel[Int($iLen / 2)] - ($iSum - 1))
If $rewind Then __GK_FormatNormGK($aGaussKernel, $iDigits) ; Rekursion falls korrigiert wurde
EndFunc ;==>__GK_FormatNormGK
; #INTERNAL# ======================================================================================
; Author ........: Mars
; =================================================================================================
Func __GK_FormatREM(ByRef $aReminder, $iDigits = 5)
Local $iSum = 0, $iLen = UBound($aReminder)
For $i = 0 To $iLen - 1 Step 1
$aReminder[$i] = StringFormat('%.' & $iDigits & 'f', $aReminder[$i])
Next ; im Prinzip nicht mehr auftreten sollten, sofern man $iDigits <= 6 wählt.
EndFunc ;==>__GK_FormatREM
; #INTERNAL# ======================================================================================
; Author ........: Mars
; =================================================================================================
Func __GK_KernelCreate($iDiameter = 3, $iSigma = 2)
Local $aGaussKernel[$iDiameter], $fStep = Round($iSigma / $iDiameter * 2, 5), $fSum = -$iSigma
For $i = 0 To $iDiameter - 1 Step 1 ; Nackt und unformatiert
$aGaussKernel[$i] = __GK_stat_norm_cdf($fSum + $fStep) - __GK_stat_norm_cdf($fSum)
$fSum += $fStep
Next ; OBACHT: Die Kiste ist noch nicht normiert. Die "Ränder" Fehlen!
Return $aGaussKernel
EndFunc ;==>__GK_KernelCreate
; #INTERNAL# ======================================================================================
; Author ........: Mars
; =================================================================================================
Func __GK_ReminderCreate($aGaussKernel)
Local $iLen = Int(UBound($aGaussKernel) / 2)
Local $aReminder[$iLen]
For $i = 0 To UBound($aReminder) - 1 Step 1
$aReminder[$i] = __GK_ArraySumLeft($aGaussKernel, $iLen - $i - 1)
Next
Return $aReminder
EndFunc ;==>__GK_ReminderCreate
; #DIEBSTAHL# =====================================================================================
; Die folgenden Funktionen sind aus der Stat-UDF von AspirinJunkie. Der Prefix _GK wurde hinzugefüg
; t um Namenskollisionen zu verhindern, falls diese UDF schon im Skript eingebunden ist.
; =================================================================================================
; #INTERNAL# ======================================================================================
; Name ..........: __GK_LoadMSVCR()
; Description ...: Load Standard-C-Library
; Syntax ........: __GK_LoadMSVCR()
; Return values .: none
; Author ........: AspirinJunkie
; =================================================================================================
Func __GK_LoadMSVCR()
Local $hDll
For $i = 200 To 90 Step -10
$hDll = DllOpen('msvcr' & $i & '.dll')
If $hDll <> -1 Then ExitLoop
Next
If $hDll = -1 Then Exit MsgBox(48, 'Fehler', 'Kein Zugriff auf msvcrt.dll!')
Return $hDll
EndFunc ;==>__GK_LoadMSVCR
; #INTERNAL# ======================================================================================
; Name ..........: _stat_erfc()
; Description ...: complementary Gauss error function
; Syntax ........: _stat_erfc(Const $z)
; Parameters ....: Const $z -
; Author ........: AspirinJunkie
; =================================================================================================
Func __GK_stat_erfc(Const $z)
Return DllCall($h_DLL_MSVCR, 'double:cdecl', 'erfc', 'double', $z)[0]
EndFunc ;==>__GK_stat_erfc
; #INTERNAL# ======================================================================================
; Name ..........: _stat_norm_cdf()
; Description ...: Cumulative density function for the gaussian normal distribution
; Syntax ........: _stat_norm_cdf($x[, $mu = 0[, $sigma = 1]])
; Parameters ....: $x -
; $mu - [optional] (default:0)
; $sigma - [optional] (default:1)
; Return values .: Success
; Failure
; Author ........: AspirinJunkie
; Remarks .......: default values for mu and sigma lead to "standard normal distribution"
; =================================================================================================
Func __GK_stat_norm_cdf($x, $mu = 0, $sigma = 1)
Return 0.5 * __GK_stat_erfc(-0.707106781186547524 * ($x - $mu) / $sigma)
EndFunc ;==>__GK_stat_norm_cdf
Alles anzeigen
Edit: Für AutoIt gibts absichtlich keinen Konsolen Export, da man das Skript einfach einfügen kann und die nötigen Daten zur Laufzeit generieren kann. Den Teil zu programmieren ist kein großer Aufwand, wer es unbedingt braucht kann ihn gerne ergänzen
Edit2: Es gibt auch einen Online Generator unter LINK. Dieser hat aber eine andere Interpretation, sodass dort eine andere Abhängigkeit zwischen Sigma und dem Radius vorliegt (z.B. ist _GK_KernelCreate(2, 2.5, 4) äquivalent zu Sigma = 1 und Durchmesser = 5 im Online Generator, unten in der angezeigten Grafik auf der Seite sieht man auch deutlich, dass die Rechtecke bei 2.5 Sigma aufhören). Welche Interpretation die richtige ist weiß nur der Wind.
lg
M