Pixelsearch / alternative für Bilder

  • Andy ich mach es eben selbst und zwar mit meinen mitteln, klar das es schneller (VIEL Schneller ) geht, aber das kann ich eben (noch) nicht. Autoit ist leicht, aber nicht die schnellste Sprache. ( meine Meinung )

    Hab deinen Code mal versucht aber bekomme da einen Speicherfehler. Hab aber in die fileload tif mit reingenommen.

    Einmal editiert, zuletzt von vcopsmtl (24. Juni 2018 um 21:52)

  • 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.

  • bei mir braucht er für das Bild etwa 1h.

    Solltest du an dieser Vorgehensweise festhalten (es wurden ja bessere Vorschläge präsentiert) kann ich dir nur den Tipp geben einfach Pixel zu skippen.

    Wenn deine Flecken beispielsweise min. 50x50 Pixel groß sind, dann ist es unnötig jede X- und Y-Koordinate durchzurechnen, so kannst du den Aufwand auf 1/2500 reduzieren.

    Wenn du dann einen Fleck gefunden hast suchst du natürlich nach jedem Nachbarn ohne Pixel zu skippen, aber um die Löcher zu finden kannst du so die Suchzeit dramatisch kürzen.

  • Hab zZ nicht viel Zeit .. hab aber mal nach den ASM Unterstützungen gesucht .. leider finde ich keine FASM.au3 die asem*.au3 hab ich

    Die anderen Threads muss ich mal durchschauen wenn ich mehr zeit hab

  • 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.

  • Mars: das ist das Problem die Datei ist und bleibt nunmal 50MB+ gross, hatte glaub ich irgendwo geschrieben das es sich um ein eingescanntes Bild handelt.

    Die Geschwindigkeit ist zweitrangig, wichtig ist das alles erfasst wird. ( durch Andys ASM infos beschäftige ich mich aktuell damit, da 1h pro Bild doch sehr lange dauert )

    Mein weiterer Plan ( Ich bin Anfänger und machs daher mit meinen Kentnissen das wird nicht die schnellste und sauberste Lösung sein aber anders kann ichs eben nicht ) 1. Schritt Bild abscannen und Farben ab Schwellwert in Datei speichern

    2. Schritt einlesen der Werte aus der Datei und in 2d Array speichern [x][y] = Farbewert so kann ich mit meinen Kentnissen mit +[x][y] die Farbwerte auswerten und so den Fleck definieren

  • 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.

  • Skippen : - Bisher nicht da bei for .. next keine anderer Step während des aufrufens verwendet werden kann und ich dadurch relevante Koordinaten verlieren kann.

    Ich denke scann jedes einzelnen Pxels ist leider nötig. Um nix zu übersehen.

    Das Bild zeigt die Gesamtqualität.

    Gesucht werden jedoch nicht nur die "puren" schwarzen stellen, auch die "gewissen" Grauen da bin ich aber noch nicht im klaren bis welche Farbe.

    - min Punkt Grösse 2px also eher nicht skippen

    - Punkte unterschiedlich gross

    Mir wäre eine Erfassung den relevanten Pixel mit den Koordinaten ( x/y ) und dazugehörigem Farbwert wichtig

  • 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.

  • Da kennt sich einer aus :)

    for .. next hab ich in schleife aber dauert halt 1h bei mir.

    Die Sterne würde ich als seperates au3 schreiben ( die Koords aus dem 1. au3 sind als Datei gespeichert )

    Da wollte ich mit +/- x/y prüfen ob eine Koordinate gespeichert ist und daraus den Fleck / Stern speichern ( sollte min. 2x2 px sein sonst verwerfen )

    Andy hat mehrfach auf ein ASM Tut von sich verwiesen, leider finde ich es hier und in google nicht. Hab mir einige ASM Tuts angesehen aber die Verbindung zu AutoIt fehlt mir noch.

    Kann mir jemand eine gutes Tut diesbezüglich Posten.

  • 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.

  • Danke hab es mir gerade angeschaut Nicht getestet .. das mit den DLLStruc verstehe ich noch nicht, weiss zwar was es machen soll aber ist aktuell zu hoch und zu spät.

  • 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.

  • Skippen : - Bisher nicht da bei for .. next keine anderer Step während des aufrufens verwendet werden kann und ich dadurch relevante Koordinaten verlieren kann.

    Für Step kannst du natürlich nur einen konstanten Wert angeben... aber was hindert dich daran, den Wert innerhalb des Loops indirekt zu ändern?

  • Bitnugger

    Code
    For $i = 0 To 10 Step $step1
        For $j = 0 To 10 Step $step2
    ;~         MsgBox(0,"","step1 " & $step1 &  @CRLF & "step2 " & $step2 & @CRLF & "i " & $i & " j " & $j)
            If $i = 5 Then $step1 = 2
            If $j = 4 Then $step2 = 3
        Next
    Next
    MsgBox(0,"",$i & " " & $j)

    so hab ichs getestet und bei $j hat er den $step erst geändert als $j einmal durchlief und eine neue $i gestartet wurde.

    Stehts auch in der Hilfe so

    Mars : ich kann den Code soweit nachvollziehen $aSum[] enthält die Farbwerte der Pixel??

  • 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.

  • so hab ichs getestet und bei $j hat er den $step erst geändert als $j einmal durchlief und eine neue $i gestartet wurde.

    Das kannst du aber alles indirekt steuern...