1. Dashboard
  2. Mitglieder
    1. Letzte Aktivitäten
    2. Benutzer online
    3. Team
    4. Mitgliedersuche
  3. Forenregeln
  4. Forum
    1. Unerledigte Themen
  • Anmelden
  • Registrieren
  • Suche
Alles
  • Alles
  • Artikel
  • Seiten
  • Forum
  • Erweiterte Suche
  1. AutoIt.de - Das deutschsprachige Forum.
  2. Mitglieder
  3. Mars

Beiträge von Mars

  • AutoIt Package/Module Manager

    • Mars
    • 7. Juli 2018 um 13:21

    Ich meinte damit eigentlich nicht den Header in der UDF selbst, sondern im Forum, sodass jemand der gewisse Funktionen sucht direkt im Startpost in den ersten Zeilen lesen kann um was die UDF geht und sie dafür nicht erst herunterladen muss.

  • AutoIt Package/Module Manager

    • Mars
    • 6. Juli 2018 um 23:00

    Wir können ja einen Forenabschnitt "UDF" einführen, weil aktuell landen alle UDFs im "Skripte" Forum.

    Dazu noch einen Standadisierten Header:

    Code
    Name : Beispiel
    Info : Die UDF kann xyz
    Tags : Mathematik, Analysis, Stochastik, usw.
    Autor: Mars
    Datum: Heute
    
    Hallo Leute, ich habe hier eine kleine UDF um xyz.
    
    Anhang: zip-Archiv mit UDF-Files + UDF-Beispiel(en)

    Ich bin auch nicht so der "Manager" ich habe schon genug zu tun den Überblick über meine eigenen Sachen zu behalten ;(

  • Flood Fill

    • Mars
    • 6. Juli 2018 um 22:21

    Moin,

    ich habe wiedermal ein unnützes Problem und suche nützliche Kommentare:*

    Es geht um den FloodFill Algorithmus in 4 Richtungen (also Pixel die durch eine "1px breite Diagonale" getrennt sind gehören NICHT zusammen).

    Der Klassiker ist der einfache Rekursive Ansatz bei welchem man einfach Rekursiv mit x-1, x+1, y-1 und y+1 sich selbst aufruft und so jeden Pixel überprüft. Dabei geht die anzahl Rekursionsschritte aber sehr schnell durch die Decke, sodass diese Methode nicht nur relativ langsam, sondern auch nur für relativ kleine Anwendungen geeignet ist.

    UEZ hat dazu schonmal vor einiger Zeit einen Thread gestartet (im EN-Forum) bei dem vorgeschlagen (und auch umgesetzt) wurde, dass man einen Stack benutzt um die Rekursion loszuwerden.

    Das Problem ist aber villeicht nicht unbedingt der Stack, sondern die Methode ansich. Es gibt viele Wege um eine FloodFill Funktion zu realisieren und nur eine einzige davon ist es, für jeden Pixel (in 1 px Schritten) in alle 4 Richtungen zu suchen (Hier werden noch ein paar Methoden gezeigt). Im englischen Wikipedia ist z.B. noch eine Right-Hand Fill Method vermerkt (die im Deutschen fehlt). Im Deutschen Wiki ist dafür noch eine kurze Vermerkung zu einem gewissen Span Flood Fill.


    Und hier kommt der Hilfegesuch:

    Bevor ich jetzt 50 verschiedene Methoden (ich zähle eine Rekursive und eine Iterative Methode als EINE Methode, sofern sie gleich vorgeht) implementiere und gegeneinander antreten lasse möchte ich herumfragen ob jemand schonmal etwas in diese Richtung programmiert hat (vllt sogar in AutoIt) und dazu irgendein Statement hat welche Methode in AutoIt eventuell recht schnell arbeitet.

    Im Beispielskript sind 3 FloodFill Methoden eingebaut.

    - FloodFill1: Das erste was Wikipedia sagt muss auch zuerst implementiert werden.

    - FloodFill2: Genau wie FF1 mit dem Unterschied, dass man keinen "Schritt zurück" gehen kann. (also wenn ich x+1 gehe kann man im nächsten Schritt nicht x-1 gehen)

    - FloodFill3: Habe ich mir ausgedacht und später herausgefunden, dass das Ganze eine Variation des Recursive Scanline Flood Fill Algorithmus ist.

    Natürlich kann jeder der Lust hat auch Eigenkreationen ausprobieren, die können villeicht besser als alles was es bereits gibt sein ;)

    AutoIt
    #include <Array.au3>
    
    ; Einstellungen zum Ausprobieren
    Global Const $n = 10                                   ; Anzahl Runden deren mittlere Zeit gemessen wird
    Global Const $ArrayDisplay = False                       ; Will man die Arrays sehen ?
    
    ; Die "Bitmap" wird hier erstellt. Es wird angenommen, dass die FloodFill Algorithmen iW und iH kennen (global)
    Global Const $iW = 24
    Global Const $iH = 24
    Global $aBitmap[$iH][$iW], $aReads[$iH][$iW], $aWrites[$iH][$iW], $iPixel = 0
    Func Reset()                                            ; Hier kann sich jeder eine "bitmap" basteln mit 2 Farben
        $iPixel = 0
        For $y = 0 To $iW - 1 Step 1
            For $x = 0 To $iH - 1 Step 1
                $aBitmap[$y][$x] = ($x - 8) ^ 2 + ($y - 8) ^ 2 < 6 ^ 2 ? 2 : 1
                $aBitmap[$y][$x] = ($x - 16) ^ 2 + ($y - 16) ^ 2 < 6 ^ 2 ? 2 : $aBitmap[$y][$x]
                If $aBitmap[$y][$x] = 2 Then $iPixel += 1
                $aReads[$y][$x] = 0
                $aWrites[$y][$x] = 0
            Next
        Next
        $aBitmap[19][2] = 2
        $aBitmap[18][2] = 2
        $aBitmap[17][2] = 2
        $aBitmap[15][2] = 2
        $aBitmap[15][3] = 2
        $aBitmap[16][4] = 2
        $aBitmap[17][5] = 2
        $aBitmap[18][4] = 2
        $aBitmap[19][4] = 2
        $aBitmap[16][1] = 2
        $aBitmap[15][0] = 2
        $aBitmap[17][0] = 2
        $aBitmap[19][3] = 2
        $aBitmap[7][7] = 1
    
    EndFunc                                                 ;==>Reset
    ; ################################################################################
    
    Global $iTimer, $iTime
    Reset()
    If $ArrayDisplay Then _ArrayDisplay($aBitmap)
    
    ConsoleWrite('###############' & @CRLF)
    $iTime = 0
    For $i = 1 To $n Step 1
        Reset()
        $iTimer = TimerInit()
        FloodFill1(18, 18, 123)
        $iTime += TimerDiff($iTimer)
    Next
    ConsoleWrite('FF1: ' & StringFormat('%.3f', $iTime / $n) & ' ms' & @CRLF)
    Info(True)
    If $ArrayDisplay Then _ArrayDisplay($aBitmap)
    
    ConsoleWrite('###############' & @CRLF)
    $iTime = 0
    For $i = 1 To $n Step 1
        Reset()
        $iTimer = TimerInit()
        FloodFill2(18, 18, 123)
        $iTime += TimerDiff($iTimer)
    Next
    
    ConsoleWrite('FF2: ' & StringFormat('%.3f', $iTime / $n) & ' ms' & @CRLF)
    Info(True)
    If $ArrayDisplay Then _ArrayDisplay($aBitmap)
    
    ConsoleWrite('###############' & @CRLF)
    $iTime = 0
    For $i = 1 To $n Step 1
        Reset()
        $iTimer = TimerInit()
        FloodFill3(18,18, 123)
        $iTime += TimerDiff($iTimer)
    Next
    ConsoleWrite('FF3: ' & StringFormat('%.3f', $iTime / $n) & ' ms' & @CRLF)
    Info(True)
    If $ArrayDisplay Then _ArrayDisplay($aBitmap)
    
    ConsoleWrite('###############' & @CRLF)
    
    $iTime = 0
    For $i = 1 To $n Step 1
        Reset()
        $iTimer = TimerInit()
        FloodFill_Andy(18, 18, 123)
        $iTime += TimerDiff($iTimer)
    Next
    ConsoleWrite('Andy: ' & StringFormat('%.3f', $iTime / $n) & ' ms' & @CRLF)
    Info(True)
    If $ArrayDisplay Then _ArrayDisplay($aBitmap)
    
    ConsoleWrite('###############' & @CRLF)
    
    
    $iTime = 0
    For $i = 1 To $n Step 1
        Reset()
        $iTimer = TimerInit()
        FloodFill_Andy2(18, 18, 123)
        $iTime += TimerDiff($iTimer)
    Next
    ConsoleWrite('Andy2: ' & StringFormat('%.3f', $iTime / $n) & ' ms' & @CRLF)
    Info(True)
    If $ArrayDisplay Then _ArrayDisplay($aBitmap)
    
    ConsoleWrite('###############' & @CRLF)
    
    Func FloodFill_Andy($x, $y, $iColFill)
        Dim $liste[$iW * $iH]                               ;maximaler Füllbereich, normalerweise eine "leere" Bitmap
        Dim $bitmap_marker[$iW * $iH]
        Local $iColRead = Read($x, $y)
        $counter = 0                                        ;für Listenelement
        $listcounter = 0                                    ;anzahl elemente in liste
        $liste[$listcounter] = $y * $iW + $x                ;position pixel in bitmap
        Write($x, $y, $iColFill)
        While 1                                             ;$listende_nicht_erreicht
    
            ;koordinate nächstes Element in der Liste, diese umrecherei ist in einer bitmap völlig unnötig.....
            $x = Mod($liste[$counter], $iW)
            $y = Int($liste[$counter] / $iH)
    
    
            ;4 Nachbarpunkte auf $iColRead testen
            $xL = $x - 1                                    ;linker pixel
            $yL = $y
            $xR = $x + 1                                    ;rechter pixel
            $yR = $y
            $xO = $x                                        ;oberer Pixel
            $yO = $y - 1
            $xU = $x                                        ;unterer Pixel
            $yU = $y + 1
    
            If $xL >= 0 And $xL < $iW And $bitmap_marker[$yL * $iW + $xL] = 0 Then ;wenn im bereich und noch nicht in der Liste
                If Read($xL, $yL) = $iColRead Then          ;Pixel mit $iColRead gefunden
                    Write($xL, $yL, $iColFill)
                    $listcounter += 1
                    $liste[$listcounter] = $yL * $iW + $xL  ;position pixel in bitmap
                    $bitmap_marker[$yL * $iW + $xL] = 1
                EndIf
            EndIf
            If $xR >= 0 And $xR < $iW And $bitmap_marker[$yR * $iW + $xR] = 0 Then
                If Read($xR, $yR) = $iColRead Then          ;Pixel mit $iColRead gefunden
                    Write($xR, $yR, $iColFill)
                    $listcounter += 1
                    $liste[$listcounter] = $yR * $iW + $xR  ;position pixel in bitmap
                    $bitmap_marker[$yR * $iW + $xR] = 1
                EndIf
            EndIf
            If $yO >= 0 And $yO < $iH And $bitmap_marker[$yO * $iW + $xO] = 0 Then
                If Read($xO, $yO) = $iColRead Then          ;Pixel mit $iColRead gefunden
                    Write($xO, $yO, $iColFill)
                    $listcounter += 1
                    $liste[$listcounter] = $yO * $iW + $xO  ;position pixel in bitmap
                    $bitmap_marker[$yO * $iW + $xO] = 1
                EndIf
            EndIf
            If $yU >= 0 And $yU < $iH And $bitmap_marker[$yU * $iW + $xU] = 0 Then
                If Read($xU, $yU) = $iColRead Then          ;Pixel mit $iColRead gefunden
                    Write($xU, $yU, $iColFill)
                    $listcounter += 1
                    $liste[$listcounter] = $yU * $iW + $xU  ;position pixel in bitmap
                    $bitmap_marker[$yU * $iW + $xU] = 1
                EndIf
            EndIf
            If $listcounter = $counter Then ExitLoop
            $counter = $counter + 1
            ;    _arraydisplay($liste)
    ;~         If $ArrayDisplay Then _ArrayDisplay($aBitmap)
    
        WEnd
    
    ;~     If $ArrayDisplay Then _ArrayDisplay($areads)
    ;~     If $ArrayDisplay Then _ArrayDisplay($bitmap_marker)
    
    EndFunc                                                 ;==>FloodFill_Andy
    
    
    Func FloodFill_Andy2($x, $y, $iColFill)
        Dim $liste[$iW * $iH]                               ;maximaler Füllbereich, normalerweise eine "leere" Bitmap
        Dim $bitmap_marker[$iW * $iH]
        Local $iColRead = Read($x, $y)
        $counter = 0                                        ;für Listenelement
        $listcounter = 0                                    ;anzahl elemente in liste
        $liste[$listcounter] = $y * $iW + $x                ;position pixel in bitmap
        Write($x, $y, $iColFill)
    
        While 1                                             ;$listende_nicht_erreicht
    
            ;koordinate nächstes Element in der Liste, diese umrecherei ist in einer bitmap völlig unnötig.....
            $x = Mod($liste[$counter], $iW)
            $y = Int($liste[$counter] / $iH)
    
    
            ;4 Nachbarpunkte auf $iColRead testen
            $xL = $x - 1                                    ;linker pixel
            $xR = $x + 1                                    ;rechter pixel
            $yO = $y - 1
            $yU = $y + 1
    
            $pos = $y * $iW + $xL
            If $xL >= 0 And $bitmap_marker[$pos] = 0 Then   ;wenn im bereich und noch nicht in der Liste
                If Read($xL, $y) = $iColRead Then           ;Pixel mit $iColRead gefunden
                    Write($xL, $y, $iColFill)
                    $listcounter += 1
                    $liste[$listcounter] = $pos             ;position pixel in bitmap
                    $bitmap_marker[$pos] = 1
                EndIf
            EndIf
            $pos = $y * $iW + $xR
            If $xR < $iW And $bitmap_marker[$pos] = 0 Then
                If Read($xR, $y) = $iColRead Then           ;Pixel mit $iColRead gefunden
                    Write($xR, $y, $iColFill)
                    $listcounter += 1
                    $liste[$listcounter] = $pos             ;position pixel in bitmap
                    $bitmap_marker[$pos] = 1
                EndIf
            EndIf
            $pos = $yO * $iW + $x
            If $yO >= 0 And $bitmap_marker[$pos] = 0 Then
                If Read($x, $yO) = $iColRead Then           ;Pixel mit $iColRead gefunden
                    Write($x, $yO, $iColFill)
                    $listcounter += 1
                    $liste[$listcounter] = $pos             ;position pixel in bitmap
                    $bitmap_marker[$pos] = 1
                EndIf
            EndIf
            $pos = $yU * $iW + $x
            If $yU < $iH And $bitmap_marker[$pos] = 0 Then
                If Read($x, $yU) = $iColRead Then           ;Pixel mit $iColRead gefunden
                    Write($x, $yU, $iColFill)
                    $listcounter += 1
                    $liste[$listcounter] = $pos             ;position pixel in bitmap
                    $bitmap_marker[$pos] = 1
                EndIf
            EndIf
            If $listcounter = $counter Then ExitLoop
            $counter = $counter + 1
            ;    _arraydisplay($liste)
    ;~         If $ArrayDisplay Then _ArrayDisplay($aBitmap)
    
        WEnd
    
    ;~     If $ArrayDisplay Then _ArrayDisplay($areads)
    ;~     If $ArrayDisplay Then _ArrayDisplay($bitmap_marker)
    
    EndFunc                                                 ;==>FloodFill_Andy2
    
    
    
    Func FloodFill1($x, $y, $iColFill, $iColArea = 0)       ; Aus dem Bilderbuch bzw. Wikipedia.
        Local $iColRead = Read($x, $y)                      ; Tempo    : Bummelbahn mit angezogener Handbremse
        If $iColArea = 0 Then $iColArea = $iColRead         ; Rekursion: Sehr schnell sehr viele Rekursionen
        If $iColArea <> $iColRead Then Return               ; Reads    : So viel wie möglich (schlecht)
        If $iColFill = $iColRead Then Return
        Write($x, $y, $iColFill)
        If $x > 0 Then FloodFill1($x - 1, $y, $iColFill, $iColArea)
        If $x < $iW - 1 Then FloodFill1($x + 1, $y, $iColFill, $iColArea)
        If $y > 0 Then FloodFill1($x, $y - 1, $iColFill, $iColArea)
        If $y < $iH - 1 Then FloodFill1($x, $y + 1, $iColFill, $iColArea)
    EndFunc                                                 ;==>FloodFill1
    
    Func FloodFill2($x, $y, $iColFill, $iColArea = 0, $iLast = -1) ; Genau das gleiche wie FloodFill1 nur, dass man nicht mehr dahingehen kann wo man herkommt.
        Local $iColRead = Read($x, $y)                      ; Tempo    : Bummelbahn
        If $iColArea = 0 Then $iColArea = $iColRead         ; Rekursion: Sehr schnell sehr viele Rekursionen
        If $iColArea <> $iColRead Then Return               ; Reads    : Weniger als FloodFill1 und FloodFill3
        If $iColFill = $iColRead Then Return
        Write($x, $y, $iColFill)
        If $iLast <> 0 And $x > 0 Then FloodFill2($x - 1, $y, $iColFill, $iColArea, 2)
        If $iLast <> 2 And $x < $iW - 1 Then FloodFill2($x + 1, $y, $iColFill, $iColArea, 0)
        If $iLast <> 3 And $y > 0 Then FloodFill2($x, $y - 1, $iColFill, $iColArea, 1)
        If $iLast <> 1 And $y < $iH - 1 Then FloodFill2($x, $y + 1, $iColFill, $iColArea, 3)
    EndFunc                                                 ;==>FloodFill2
    
    Func FloodFill3($x, $y, $iColFill, $iColArea = 0)       ; Spontan ausgedacht. Nachschlagen ergab, dass eine ähnliche Methode Scanline Flood Fill heißt.
        If $iColArea = 0 Then $iColArea = Read($x, $y)      ; Tempo    : Mofa mit aufgebohrtem Zylinderkopf und zugepetztem Auspuff.
        Write($x, $y, $iColFill)                            ; Rekursion: Eine für jede "Linie" in jeder Zeile. Also irgendwas wie die CONST * AREAHEIGHT (sollte nicht so schnell wachsen)
        For $xMax = $x + 1 To $iW - 1 Step 1                ; Reads    : Weniger als FloodFill1 und mehr als FloodFill3
            $iColRead = Read($xMax, $y)
            If $iColRead <> $iColArea Then ExitLoop
            Write($xMax, $y, $iColFill)
        Next
        For $xMin = $x - 1 To 0 Step -1
            $iColRead = Read($xMin, $y)
            If $iColRead <> $iColArea Then ExitLoop
            Write($xMin, $y, $iColFill)
        Next
        $xMin += 1
        $xMax -= 1
    ;~     If $xMin = -1 Then $xMin = 0
    ;~     If $xMax = $iW Then $xMax = $iW - 1
        If $y > 0 Then
            For $i = $xMin To $xMax Step 1
                If Read($i, $y - 1) = $iColArea Then FloodFill3($i, $y - 1, $iColFill, $iColArea)
            Next
        EndIf
        If $y < $iH - 1 Then
            For $i = $xMin To $xMax Step 1
                If Read($i, $y + 1) = $iColArea Then FloodFill3($i, $y + 1, $iColFill, $iColArea)
            Next
        EndIf
    EndFunc                                                 ;==>FloodFill3
    
    Func Info($bPlot = False)
        Local $iReads, $iWrites
        If $bPlot Then ConsoleWrite('##################################### [ Reads | Writes ] ######################################' & @CRLF)
        For $y = 0 To $iH - 1 Step 1
            For $x = 0 To $iW - 1 Step 1
                $iReads += $aReads[$y][$x]
                $iWrites += $aWrites[$y][$x]
                If $bPlot Then ConsoleWrite('[' & $aReads[$y][$x] & '|' & $aWrites[$y][$x] & '] ')
            Next
            If $bPlot Then ConsoleWrite(@CRLF)
        Next
        ConsoleWrite('Reads:  ' & $iReads & @CRLF)
        ConsoleWrite('Writes: ' & $iWrites & @CRLF)
        If $bPlot Then ConsoleWrite('###############################################################################################' & @CRLF)
    EndFunc                                                 ;==>Info
    
    Func Read($x, $y)
        $aReads[$y][$x] += 1
        Return $aBitmap[$y][$x]
    EndFunc                                                 ;==>Read
    
    Func Write($x, $y, $iCol)
        $aWrites[$y][$x] += 1
        $aBitmap[$y][$x] = $iCol
    EndFunc                                                 ;==>Write
    Alles anzeigen

    lg

    M

  • AutoIt Package/Module Manager

    • Mars
    • 6. Juli 2018 um 21:59

    Ich habe da reinstes Chaos. Habe einige eigene UDFs gespeichert, aber bei weitem nicht alle. Von anderen Usern habe ich verstreut über mehrere Computer/Festplatten eine Hand voll UDFs gesichert. Wenn ich was suche lade ich es zumeist neu herunter.

    Eine Zentrale Verwaltung gibt es leider nicht, soetwas müsste von irgendwem gemanaged werden und dazu ist die Community zu klein, als dass sich das lohnt.

  • Pixelsearch / alternative für Bilder

    • Mars
    • 1. Juli 2018 um 15:10

    Hab meine AutoIt-Version nochmal umgebastelt, sodass keine quadratische Komplexität mehr beim Dateierzeugen vorherrscht (dateierzeugen geht jetzt recht flott). Der Rest ist aber immernoch unglaublich langsam. Von daher nicht viel besser oder schlechter als die Version die du schon hast (die 1h braucht). Die Go Version ist noch in der Mache, dauert noch, hab noch andere Sachen zu tun :/

    Die Ergebnisse aber bitte mit Vorsicht genießen, das ist eher eine "grobe Schätzung" als eine stichhaltige Analyse (in Go hab ich mehr Tempo und kann daher einen besseren Algorithmus zur Erkennung nutzen, da sollte das Ergebnis etwas besser sein, aber auch hier keine Garantie)...

    Dateien

    test2.zip 389 kB – 445 Downloads
  • Pixelsearch / alternative für Bilder

    • Mars
    • 29. Juni 2018 um 16:13

    Die Idee ist folgendes gewesen:

    Code
    ;   c b c     X
    ; c a # a c   # = Mitte aSum[0]
    ; b # X # b   a = Außen aSum[1]
    ; c a # a c   b = Außen aSum[2]
    ;   c b c     c = Außen aSum[3]

    aSum[0] = Durchschnittshelligkeit des inneren Bereichs, aSum[1] = Durchschnittshelligkeit des ersten äußeren Bereichs, usw, usw.

    Wenn man jetzt sagt (if aSum[0] > aSum[1] > aSum[2] > aSum[3] then Stern) erkennt man einen Bereich der in der Mitte heller ist als außen als Stern unabhängig von der Hintergrundhelligkeit.

    Leider habe ich bei der Methode wie die Sterne gespeichert werden (für die Textdatei) großen Mist gebaut mit der Hoch2 Komplexität.

    Um doppeltes Einfügen zu verhindern sollte man eine Liste mit Linearer Komplexität wie z.B. irgendwas hiervon Alternativen zum Array verwenden und nicht jedes Mal (fast) alles durchsuchen bevor man einen neuen Wert einfügt. Das mag bei ein paar hundert Einträgen noch gut laufen, aber später nicht mehr. Das baue ich später um.

    Den Hintergrund bekommt man auch gut weg, wenn man vom Bild ein geblurrtes Bild abzieht.

    ohnerauschen.png

    Das ganze zu berechnen (einlesen, Blurren, abziehen, speichern) hat in Go nichtmal eine Sekunde gedauert. Von daher schreibe ich gleich das ganze Teil in Go neu. (ein 7k Testbild zu blurren hat 2.8min (17:48Uhr - 1,3min, 19:43Uhr - 0,5min) gedauert... dachte das geht schneller :D) Edit: Ein bisschen basteln und es läuft in 30s. Kann man so stehen lassen.

  • Pixelsearch / alternative für Bilder

    • Mars
    • 29. Juni 2018 um 00:48

    Das ist nur eine andere Speichermethode für Variablen.

    AutoIt hat den Datentyp Variant (intern hat es schon richtige Datentypen, aber die üblichen Variablen mit $a kann man mit einer 5, einer 5.0, einem String oder ähnlichem füllen). Das Problem dabei ist, dass Dlls und ASM die Daten im Speicher finden müssen, damit das klappt kann man sie in DllStructs speichern (das sind C Structs) die von überall aus gut verwendbar sind.

    Ansich ist in AutoIt eine Struct langsamer als normale Variablen, der Zugriff von Außen ist aber dafür möglich.

  • Pixelsearch / alternative für Bilder

    • Mars
    • 28. Juni 2018 um 21:23

    Was kann es:

    - Sterne finden (naja.... so halbwegs)

    - Output in eine Textdatei und zur Veranschaulichung eine png

    - Langsam sein (Hochrechnung ergibt für 7000x7000px ca. 1h40m, da die Methode die Daten zusammenzufassen und in die .txt zu schreiben quadratische Komplexität hat wahrscheinlich unheimlich viel länger...)

    - Komplett auf Structs aufgebaut sein (ermöglicht "einfaches" schreiben einer dll in einer beliebigen Sprache die schneller ist als AutoIt)

    Probleme:

    1 - Es werden Sterne gefunden die nicht existieren (an manchen Stellen schlägt das Muster an, obwohl da nur Rauschen ist)

    2 - Es werden Sterne nicht gefunden obwohl sie da sind (passiert nur bei kleinen Sternen manchmal)

    3 - Es werden große Sterne als mehrere kleine interpretiert oder umgekehrt (zumindest den ersten Teil kann ich noch lösen)

    4 - Die Größenangaben sind nicht besonders akkurat (bisher "0" -> 1px, "1" -> 2px, "2" -> 2x2px, "3" -> 3x3px oder größer) (kann für große Sterne im Zuge der Lösung von Punkt 3 noch verbessert werden)

    5 - In Wolken werden keine 2px Sterne erkannt und auf die erkannten 1px Sterne würde ich nicht allzuviel geben.

    Von daher: Mit Vorsicht genießen, ich habe (aktuell) nichts zu tun und versuche daran demnächst weiterzubasteln (wollte schon seit Ewigkeiten mal eine DLL in Go schreiben, dann mach ich das gleich mit). Für mich sehen die Resultate fast wie Zufallszahlen aus^^

    Bitte nicht direkt auf die 7k Bitmap anwenden, das kann ewig dauern, probier lieber Teilstücke aus...

    Veranschaulichung.png

    Villeicht bastelt ja noch ein Student mit zuviel Freizeit eine weitere Lösung sodass die Ergebnisse kombiniert besser sind als einzeln.

    Dateien

    Test.zip 387,08 kB – 383 Downloads
  • Pixelsearch / alternative für Bilder

    • Mars
    • 28. Juni 2018 um 15:52

    Da hat aber jemand ein gutes Teleskop :D
    Bei 112.444 ist ein Staubkorn.

    Hab schon ein bisschen was gebastelt, für größere Bilder wird man da eine Dll schreiben müssen oder ASM benutzen.

    Meine Methode ist: Pixel für Pixel ein Abgleich mit einer 2D Normalverteilung der direkten Umgebung incl abzug der Hintergrundhelligkeit.

    Man sieht auch die Belichtungszeit, weil die meisten Punkte etwas in y Richtung langgezogen sind.

    Oder ich irre komplett und das hat nichts mit Sternen zu tun :D

    In den "Wolken" gibt es durch das große Hintergrundrauschen probleme dabei kleine Punkte zu erkennen.

    Edit1:

    Hab ne andere Methode die weniger Rechenintensiv ist als das mit der Normalverteilung und dennoch gut läuft.

    Irgendwann im Laufe des Abends poste ich was. Wird aber ohne DLL und ohne ASM und daher langsam sein. Sollte aber besser funktionieren als ein einfaches if Helligkeit(Pixel) > Schwelle then Stern. Das gibt nämlich Unfug raus.

  • Pixelsearch / alternative für Bilder

    • Mars
    • 27. Juni 2018 um 11:41

    Wenn die Datei 50MB groß ist, dann gib uns einen repräsentativen Bildausschnitt heraus der klein genug ist um ein Skript dazu zu schreiben.

    Ich fasse mal zusammen was mir bei sowas durch den Kopf geht:

    - Wie ist der Hintergrund beschaffen, eingescannt? Resttextur vom Papier? SchwarzWeiß/Farbig? Wie hoch ist der Kontrast von Punkt zu Hintergrund. Sind Punkte gleichmäßig gefüllt, sind die Punkte Rund, Oval, Eckig, Verpixelt, Abgerundet usw?

    - Wie groß sind die Punkte? Eingescannt -> Punkte können praktisch zwischen 1px und Beliebig vielen px sein, Kann man z.B. eine FloodFill (ohne Füllen, sondern nur ablaufen) Variation nutzen die alle Pixel eines Punktes abläuft, jede xy koordinate speichert und daraus den Mittelwert = Schwerpunkt des Punkts berechnet? Wie viele Pixel kann man zwischen Kontrollpixeln skippen? wenn die Punkte sehr klein sind gar keine, wenn sie sehr groß sind sehr viele. Sind alle Punkte gleich groß?

    - Welche Farbe haben die Punkte, werden sie zuverlässig erkannt wenn man nur einen festen Farbwert zum Vergleich benutzt? Sollte man statt festen Wert Kontrast zum Hintergrund als Vergleich heranziehen?

    - Wie hoch ist die Punktdichte (kann man z.B. eine Transformation von 2D auf 2x1D vornehmen, würde man die Punkte dann sehen?)

    - Können sich (im Fall ausgedehnter Punkte) mehrere Punkte berühren, müssen diese dann auch getrennt erkannt werden (2D Gauß/Rechteck/Dreieck/Lorentz/etc (ich weiß ja nicht wie die Punkte gefüllt sind) Fit über das Gebiet mit 2 Punkten regelt, aber ist das notwendig?)

    - Ist das eingescannte Bild in einem Din-Format (Verhältnis Sqrt2 von w zu h, sodass man aus dem "Rechteck" von 7000x7000 garnicht alle Pixel beachten muss). Sind 7k mal 7k Pixel notwendig um die Punkte zuverlässig zu erkennen? Kann man das Bild nicht vllt auf 2k mal 2k via Bildbearbeitungsprogramm/GDI+ herunterskalieren (Interpolationsmodus nicht vergessen) und anschließend analysieren? (von ca. 50Mio Px auf ca. 4Mio Px gibt es einen Geschwindigkeitsvorteil mit dem Faktor 12)

    - usw usw.

    Vermutlich denke ich zu viel nach, aber mein mechanisches Gehirn kann ein Problem nicht lösen ohne es zu erfassen.

    TestBild.png

    Künstlerische Darstellung von dunklen Kreisen auf aus google geklauter Papiertextur. Das sind keine Originaldaten, sondern nur ein Bildchen was ich aus langeweile gemacht habe.

  • Pixelsearch / alternative für Bilder

    • Mars
    • 26. Juni 2018 um 00:35

    Wie kommen diese Bitmaps eigentlich zustande?

    Ich wette, dass es möglich ist die schwarzen Pixel als dünn besetzte Matrix zu speichern (braucht dann nur ein paar (kilo) Byte (je nach Dichte) und anschließend in rasendem Tempo zu verarbeiten, anstatt eine 7k*7k Bitmap zu erzeugen.

    Edit: auch wenn es schon ein paar mal gesagt wurde: Wenn du eine Lösung willst die das ganze in unter 1 Sek schafft, gib uns eine anständige Einsicht in das Problem. Mindestanforderung damit irgendjemand damit arbeiten kann sind Testdaten. Als bmp speichern und mit winrar/7zip/etc (aber nicht das normale .zip) kleinmachen sollte ein Resultat unter 1MB liefern das du hier hochladen kannst.

  • Pixelsearch / alternative für Bilder

    • Mars
    • 25. Juni 2018 um 13:53

    Ich habe gerade alles hier durchgelesen und konnte meinen Augen nicht trauen :D

    Wie wäre es mit folgendem Ansatz:

    1. Das tif "Bild" in ein BMP32 oder BMP24 umwandeln (via GDI/GDI+)
    2. Ein RegEx draufhauen das einem direkt ein Array mit allen schwarzen Pixeln ausgibt. (geht sowas überhaupt? Ich bin kein RegEx Profi)

    Sollte selbst bei der Dateigröße nur wenige Sekunden dauern (format von xyz -> Bitmap geht immer schnell, RegEx Engine ist auch verdammt flott)

    Weiterhin, wenn er es wirklich via Bitmapgetpx BRAUCHT: Benutzt bitte einfach eine Struct und schreibt einen ganz einfachen for $iPx = 1 To $w*$h loop der jede Speicherstelle testet. Das lässt sich in ASM 1 zu 1 übersetzen und dauert dann nur noch eine Millisekunde.

  • GuiSetIconEx

    • Mars
    • 10. Juni 2018 um 23:52

    Ist jetzt zwar Offtopic, aber wie heißt die Skin die du benutzt?
    Ich suche soetwas ähnliches schon länger, habe aber bisher nichts gefunden...

  • Primitiver Hashtable

    • Mars
    • 31. Mai 2018 um 00:33

    Ahoi,

    Für eine Hausaufgabe musste ich einen Hashtable in Java basteln. Anschließend habe ich mich im Netz umgesehen, ob es eine (primitive, so wie die Hausaufgabe) Umsetzung in AutoIt bereits gibt und musste Feststellen: Einige UDFs sind gefühlte 50 Jahre alt (das muss nichts heißen, ich habe keine davon heruntergeladen und ausprobiert), andere benutzen WindowsCOM (sodass ein eventuell vorhandener Student der genau die Aufgabenstellung aus der Hausaufgabe gelöst haben will nichts aus den UDFs lernen kann). Von daher habe ich (mit etwas künstlerischer Freiheit) eine Version in AutoIt gebastelt.

    Verbesserungsvorschläge bzw Bugreports sind natürlich gerne gesehen.

    (Ich bin 100%ig sicher, dass es Bugs gibt, ich habe sie nur noch nicht gefunden)

    AutoIt: HT
    For $i = 1000 To 9000 Step 1000
        Test($i)
    Next
    
    Func Test($n = 1000)
    ;~     Local $aTable = HTCreate(0) ; Erstellt den Hashtable mit Initialgröße 0 ( er passt sich dynamisch an die gegebenheiten an )
        Local $aTable = HTCreate($n*2) ; Erstellt den Hashtable mit Initialgröße $n*2 sodass er beim Füllen nicht vergrößert werden muss.
    
        ConsoleWrite('Elemente: ' & $n & @CRLF)
    
        Local $t = TimerInit()
        For $i = 1 To $n Step 1
            HTInsert($aTable, HTElement('key:' & $i, 'data:' & $i ^ 2)) ; Fügt Elemente hinzu
        Next
        ConsoleWrite('Füllen  : ' & StringFormat('%.3f', TimerDiff($t)/$n) & ' ms / Element' & @CRLF)
    
        Local $t, $e, $time = 0
    
    
        For $i = 1 To $n Step 1
            $t = TimerInit()
            $e = HTGetElement($aTable, 'key:' & $i)
            $time += TimerDiff($t)
            If $e[1] <> 'data:' & $i ^ 2 Then Return ConsoleWrite('Error' & $i & @CRLF)
        Next
    
        ConsoleWrite('Abfragen: ' & StringFormat('%.3f', $time/$n) & ' ms / Element' & @CRLF & @CRLF)
    
    EndFunc
    
    ; Erstellt den Hashtable
    Func HTCreate($iSize = 0)
        Local $aArray[$iSize + 2] = [$iSize, 0]
        ; in [0] steht den Kapazität
        ; in [1] steht die Anzahl Vorhandener Elemente
        ; in [2] bis [2 + Kapazität] sind die Elemente verteilt.
        Return $aArray
    EndFunc
    
    ; Vergrößert oder Verkleinert den Hashtable je nach Füllstand
    Func HTRehash(ByRef $aTable, $bRehash)
        Local $aNewTable = HTCreate(Int($aTable[1] * 6 + 1)) ; Füllstand alt: ca 66%, Füllstand neu: ca. 17%
        For $i = 2 To UBound($aTable) - 1 Step 1 ; Linear durchgehen.
            If IsArray($aTable[$i]) And Not ($aTable[$i])[2] Then HTInsert($aNewTable, $aTable[$i], False)
        Next
        $aTable = $aNewTable
    EndFunc
    
    ; Fügt ein Element hinzu
    Func HTInsert(ByRef $aTable, $aElement, $bRehash = True)
        If $bRehash And ($aTable[1] + 1) > Int($aTable[0]/1.5) Then HTRehash($aTable, $bRehash) ; Füllstand > 66% ? -> Größer machen
        Local $iHash = Mod(HTHash($aElement[0], 1), $aTable[0]), $i = 2, $eTmp
        While True
            $eTmp = $aTable[$iHash + 2]
            If IsArray($eTmp) Then
                If $eTmp[2] Then ExitLoop
                If $eTmp[0] = $aElement[0] Then Return False ; Das gleiche geht nicht 2x
                $iHash = Mod(HTHash($aElement[0], $i), $aTable[0])
                $i += 1
            Else
                ExitLoop
            EndIf
        WEnd
        $aTable[1] += 1
        $aTable[$iHash + 2] = $aElement
    EndFunc
    
    ; Markiert ein Element als gelöscht und gibt das gelöschte Element zurück
    Func HTDelete(ByRef $aTable, $sKey)
        Local $iHash = Mod(HTHash($sKey, 1), $aTable[0]), $i = 2, $aElement
        While True
            $aElement = $aTable[$iHash + 2]
            If IsArray($aElement) Then
                If $aElement[0] = $sKey Then
                    If $aElement[2] = True Then Return False
                    $aElement[2] = True
                    $aTable[$iHash + 2] = $aElement
                    $aTable[1] -= 1
                    If $aTable[1] <= Int($aTable[0]/15) Then HTRehash($aTable, False) ; Füllstand < 7% ? -> kleiner machen
                    Return $aElement
                EndIf
                $iHash = Mod(HTHash($sKey, $i), $aTable[0])
                $i += 1
            Else
                Return False
            EndIf
        WEnd
    
    EndFunc
    
    ; Gibt das Element mit dem Key $sKey zurück
    Func HTGetElement(ByRef $aTable, $sKey)
        Local $iHash = Mod(HTHash($sKey, 1), $aTable[0]), $i = 2, $aElement
        While True
            $aElement = $aTable[$iHash + 2]
            If IsArray($aElement) Then
                If $aElement[0] = $sKey Then Return $aElement
                $iHash = Mod(HTHash($sKey, $i), $aTable[0])
                $i += 1
            Else
                Return False
            EndIf
        WEnd
    EndFunc
    
    ; Verpackung für das Element
    Func HTElement($sKey, $xData) ; [0] - Key, [1] - Daten, [2] - Marker obs gelöscht ist.
        Local $aElement = [$sKey, $xData, False]
        Return $aElement
    EndFunc
    
    ; Gibt den Key zurück
    Func HTElementGetKey($aElement)
        If IsArray($aElement) Then Return $aElement[0]
    EndFunc
    
    ; Gibt den Inhalt zurück
    Func HTElementGetData($aElement)
        If IsArray($aElement) Then Return $aElement[1]
        Return False
    EndFunc
    
    ; Hashfunktion: Marke Eigenbau, habe sie kurz mit verschiedenen Keys und "i" laufen lassen und geprüft und es sah ganz okay aus. Wahrscheinlich
    Func HTHash($sStr, $i = 1, $nBit = 16) ; ist sie aber im Vergleich zu anderen Hashfunktionen nicht so der Burner. "Schnell" ausrechnen kann sie
        If StringLen($sStr) <= 2 Then $sStr &= $i & $sStr ; auch nur AutoIt, weil hier ein pow(double, double) genausolange dauert wie ein int + 1.
        Local $bBin = StringToBinary($sStr), $iLen = BinaryLen($bBin), $exp = $i^0.111, $bRet = Int(BinaryMid($bBin, 1, 2))^$exp
        If Mod($iLen, 2) Then $bBin &= 'AA' ; 10101010
        For $ii = 3 To BinaryLen($bBin) Step 2
            $bRet = BitXOR($bRet, Int(Int(BinaryMid($bBin, $ii, 2))^$exp))
        Next
        Return BitAND($bRet, Int(2^$nBit - 1))
    EndFunc
    Alles anzeigen

    lg

    M

  • Mini-PCs

    • Mars
    • 20. Mai 2018 um 10:53
    Zitat von alpines

    Das wird aber nicht klappen, da du dann die ARM-Variante von Windows 10 auf dem Raspi läuft (die sind ja glaube ich nur mit ARMs bestückt) und AutoIt x86/x64 compiled.

    Ich habs selbst nicht ausprobiert, aber ANGEBLICH läuft das (neue) ARM Windows 10 mit einem emulation Layer, sodass (fast) jede übliche x86 Anwendung läuft. Also es soll gerade nicht die Probleme haben die das ARM Windows früher hatte wo nur eine geringe Auswahl an Apps lief und alles andere nicht. Muss man aber sicherlich mal selbst ausprobieren um da näheres auszuprobieren.

    https://www.pcwelt.de/a/windows-10-f…s-geben,3449809

    lg

    M

  • Ein fenster Klonen wie das programm OnTopReplice

    • Mars
    • 13. Mai 2018 um 10:41

    Sehr schön, Hilfe zur Selbsthilfe ist immer am besten ;)

    (PS: An einen Mod: Der Thread gehört in H&U und ist gelöst, ich kann ihn nicht verschieben)

  • Ein fenster Klonen wie das programm OnTopReplice

    • Mars
    • 12. Mai 2018 um 18:49

    Also dann spoiler ich mal ein Template für das Kopieren eines Desktopausschnitts. Wenn du aber irgendein sinnvolles Programm schreiben willst wirst du nicht darum herumkommen zu verstehen was das Programm tut. Erst die Arbeit, dann das Vergnügen.

    AutoIt
    #include <WinApi.au3>
    #include <WindowsConstants.au3>
    
    ; #############################################
    ;                 X    Y    W    H
    Global $aRect = [100, 100, 300, 200]
    ; #############################################
    
    Global $hGUI = GUICreate('Klon', $aRect[2], $aRect[3])
    Global $hDC_Desktop = _WinAPI_GetDC(_WinAPI_GetDesktopWindow())
    Global $hDC_GUI = _WinAPI_GetDC($hGUI)
    GUISetState(@SW_SHOW, $hGUI)
    
    While GUIGetMsg() <> -3
        _WinAPI_BitBlt($hDC_GUI, 0, 0, $aRect[2], $aRect[3], $hDC_Desktop, $aRect[0], $aRect[1], $SRCCOPY)
    WEnd
    
    _WinAPI_ReleaseDC(_WinAPI_GetDesktopWindow(), $hDC_Desktop)
    _WinAPI_ReleaseDC($hGUI, $hDC_GUI)
    Alles anzeigen
  • Ein fenster Klonen wie das programm OnTopReplice

    • Mars
    • 12. Mai 2018 um 11:09

    Hier eine Hand voll Tips:

    - Windowsfenster haben einen DC, in AutoIt gibt es _Winapi_GetDC

    - BitBlt kopiert Teile eines DC in einen anderen DC

    - AutoItFenster (GuiCreate) haben auch ein DC

    Das zu schreiben dauert 5 Minuten, aber du musst es selbst lernen um zukünftig zu verstehen was du gemacht hast und dann ggf. anderen bei dem gleichen Vorhaben auch Tips zu geben :)

    (Allerdings wird mit der DC Methode nur das "Bild" des Fensters geklont, nicht das "fenster selbst" Buttons usw werden so nicht funktionieren)

  • Turnierspiel Kombinationen

    • Mars
    • 26. Februar 2018 um 18:47

    Die 36 Spiele kommen von den 9 Teilnehmern im Test. (9^2-9)/2

  • Turnierspiel Kombinationen

    • Mars
    • 26. Februar 2018 um 18:01
    AutoIt
    #include <Array.au3>
    
    ;~ Global $aPlayerNames = ['Kathrin', 'Doris', 'Tamara', 'Gabi ', 'Oliver', 'Heinrich', 'Helmut', 'Werner']
    Global $aPlayerNames = ['Kathrin', 'Doris', 'Tamara', 'Gabi ', 'Oliver', 'Heinrich', 'Helmut', 'Werner', 'Johnson']
    
    JederGegenJeden($aPlayerNames)
    
    Func JederGegenJeden($aNames)
        Local $iPlayers = UBound($aNames) ; Anzahl Spieler
        Local $aGames[Int(($iPlayers ^ 2 - $iPlayers) / 2)][2] ; Alle Matchups
        Local $iDist = Int($iPlayers / 2) ; Optimale Distanz an Spielen
        Local $iGame = 0, $aPlayers[$iPlayers]
        Local $next = False, $Nochmal = False
    
        Do
    
            ; ############# Kompletter Neustart ################
            For $i = 0 To UBound($aGames) - 1 Step 1
                $aGames[$i][0] = -1
                $aGames[$i][1] = -1
            Next
            For $i = 0 To UBound($aPlayers) - 1 Step 1
                $aPlayers[$i] = 0
            Next
            $iGame = 0
            $Nochmal = False
            $next = False
            ; ###################################################
    
            For $i = 0 To 999 Step 1 ; Wahrscheinlichkeitsbasiert. 1000 Runden läuft!
                For $ii = 0 To 999 Step 1
    
                    ; #### Check ob das die gleichen wie vorher sind ####
                    Do
    
                        ; ### 2 zufällige unterschiedliche Spieler wählen ###
                        $aGames[$iGame][0] = Random(0, $iPlayers - 1, 1)
                        Do
                            $aGames[$iGame][1] = Random(0, $iPlayers - 1, 1)
                        Until $aGames[$iGame][0] <> $aGames[$iGame][1]
                        ; ###################################################
    
                    Until _
                            ($iGame > 0) ? (( _ ; Nur wenn Es nicht die allererste Runde ist
                            ($aGames[$iGame][0] <> $aGames[$iGame - 1][0]) And _ ;
                            ($aGames[$iGame][0] <> $aGames[$iGame - 1][1]) And _ ; 4 Vergleiche
                            ($aGames[$iGame][1] <> $aGames[$iGame - 1][0]) And _ ;
                            ($aGames[$iGame][1] <> $aGames[$iGame - 1][1]) _     ;
                            ) ? True : False) _ ; Falls alle unterschiedlich sind: True, sonst False
                             : True ; Es ist die erste Runde. True!
                    $aPlayers[$aGames[$iGame][0]] += 1
                    $aPlayers[$aGames[$iGame][1]] += 1
                    ; ###################################################
    
                    $next = True
                    If $aPlayers[$aGames[$iGame][0]] = $iPlayers Or $aPlayers[$aGames[$iGame][1]] = $iPlayers Then
                        $aPlayers[$aGames[$iGame][0]] -= 1
                        $aPlayers[$aGames[$iGame][1]] -= 1
                        $next = False
                    EndIf
    
                    If $next Then ExitLoop
                Next
    
                $iGame += 1
                If $iGame = UBound($aGames) Then ExitLoop
            Next
    
            For $i = 0 To $iPlayers - 1 Step 1
                If $aPlayers[$i] <> $iPlayers - 1 Then $Nochmal = True
            Next
    
        Until Not $Nochmal
    
        ; Ab hier waren alle Spieler genau sooft dran wie sie sollen
        ; Die Abstände sind aber nicht optimal. Optimal ist z.B. bei 8 Spielen jedes 4te dranzukommen.
        ; Jetzt kann man ggf. noch Spiele vertauschen (REGELN BEACHTEN) bis die Abstände besser sind.
    
        For $i = 0 To 99 Step 1
    
            ; Hier könnte irgendwelcher Code stehen...
    
        Next
    
    
        For $i = 0 To UBound($aGames) - 1 Step 1
            $aGames[$i][0] = $aNames[$aGames[$i][0]]
            $aGames[$i][1] = $aNames[$aGames[$i][1]]
        Next
    
        _ArrayDisplay($aPlayers)
        _ArrayDisplay($aGames)
    
    EndFunc   ;==>JederGegenJeden
    Alles anzeigen

    Da ich ein Freund des Zufalls bin habe ich was gebastelt:

    Es werden einfach zufällige Matchups genommen und nachträglich geschaut ob die Regeln eingehalten wurden.

    + Das Ergebnis müsste eine Matchupliste sein die die Anforderungen erfüllt

    + Ungerade Spielerzahlen

    - Es wird OHNE "Runden" gearbeitet, damit auch ungerade Spielerzahlen klargehen.

    - Milliardenfach mehr Rechenaufwand als wenn man die Zauberformel finden würde.

    - (Aktuell) Die Abstände sind schlecht verteilt (also ein Spieler kommt z.B. in 8 Spielen 3x oder 4x dran und danach 10 Spiele garnicht)

    M

Spenden

Jeder Euro hilft uns, Euch zu helfen.

Download

AutoIt Tutorial
AutoIt Buch
Onlinehilfe
AutoIt Entwickler
  1. Datenschutzerklärung
  2. Impressum
  3. Shoutbox-Archiv
Community-Software: WoltLab Suite™