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.
Beiträge von Mars
-
-
Wir können ja einen Forenabschnitt "UDF" einführen, weil aktuell landen alle UDFs im "Skripte" Forum.
Dazu noch einen Standadisierten Header:
CodeName : 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
-
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
Alles anzeigen#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
lg
M
-
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.
-
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)...
-
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.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.
-
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.
-
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...
Villeicht bastelt ja noch ein Student mit zuviel Freizeit eine weitere Lösung sodass die Ergebnisse kombiniert besser sind als einzeln.
-
Da hat aber jemand ein gutes Teleskop
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
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.
-
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.
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.
-
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.
-
Ich habe gerade alles hier durchgelesen und konnte meinen Augen nicht trauen
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. -
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... -
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
Alles anzeigenFor $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
lg
M
-
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
-
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)
-
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
Alles anzeigen#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)
-
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)
-
Die 36 Spiele kommen von den 9 Teilnehmern im Test. (9^2-9)/2
-
AutoIt
Alles anzeigen#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
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