Hilfe: sinnvolle Nutzung von Pixelsearch

  • Hallo,

    ich habe mir schon ein Skrip geschrieben, dann hatte ich jedoch eine idee dieses zu erweiter, nur leider weiß ich nicht wie:

    Das Script soll ein die Umrisse einer figur aus einem Bild (für den Anfang einfach zeichnungen mit schwarzer umrandung) mit hilfe von pixelsearch ausfindig machen und das dann in eine für ein Cad programm bestimmt steuersprache umsetzen, also z.b. würde ein Befehl lauten : Linie nach x,y und so weiter und diese koordinaten soll mir das script liefern und dann auch einfügen, sodass der das bild imprinzip übersetzt, sodass ich das mit dem cad programm ausscheiden laseen kann oder plottern lassen kann. (max DIN A4 größe) Nur leider weiß ich nioch nicht genau wie ich die koordinaten bekommen. weil ich will ja linien zeichnen. für Bögen gibt es ne extra funktion.


    Ich hoffe ihr habt mein Problem verstanden, wenn nciht sagt bescheid, dann erklär ich das mal ausführlicher.


    MfG
    filewalker

    • Offizieller Beitrag

    Probier mal die Funktion, hatte sie für einen anderen Zweck geschrieben, aber ich denke es könnte hier passen.

    Spoiler anzeigen
    [autoit]

    #include <SQLite.au3>
    #include <SQLite.dll.au3>

    [/autoit] [autoit][/autoit] [autoit]

    Dim $DateiOut = @ScriptDir & "\Scanergebnis.txt"
    Dim $Farbe = 0x000000
    Dim $Schrittweite = 1

    [/autoit] [autoit][/autoit] [autoit]

    _pix_scan($Farbe, $Schrittweite, $DateiOut)

    [/autoit] [autoit][/autoit] [autoit]

    ;------------------------------------------------------------------------------------------------------------
    ; Funktion _pix_scan($color, $step, $file)
    ;
    ; Beschreibung scannt Display nach gesuchter Farbe, Ausgabe in Datei
    ; Pixelbereiche 2-stufig sortiert
    ;
    ; Parameter $color: zu suchende Farbe
    ; $step: Rastergröße
    ; $file: Ausgabedatei
    ;
    ; Return Datei mit den gefundenen Pixelpositionen
    ;
    ; Erfordernisse Funktion: _Array2DSortFree( )
    ; Nach dem Funktionsaufruf wird der Scan erst mit {F9} gestartet
    ; um z.B. vorab ein Spiel starten zu können
    ;
    ; Autor BugFix ([email='bugfix@autoit.de'][/email])
    ;------------------------------------------------------------------------------------------------------------
    #include <File.au3>
    #Include <Misc.au3>
    Func _pix_scan($color, $step, $file)
    Local $endX = @DesktopWidth, $endY = @DesktopHeight
    Local $left = 0, $top = 0, $right = $step, $bottom = $step
    Local $arPos, $arSort[1][1]
    Do
    Sleep(100)
    Until _IsPressed("78") ; F9
    $fh = FileOpen($file,1)
    Do
    For $left = 0 To $endX Step $step
    $pos = PixelSearch($left, $top, $right, $bottom, $color, 0, $step)
    If IsArray($pos) Then FileWriteLine($file, $pos[0] & "|" & $pos[1])
    $right += $step
    Next
    $left = 0
    $right = $step
    $top += $step
    $bottom += $step
    Until $bottom > $endY
    FileClose($fh)
    Beep(500, 2000)
    _FileReadToArray($file, $arPos)
    FileDelete($file)
    ReDim $arSort[UBound($arPos)][2]
    For $i = 0 To UBound($arPos)-1
    $var = StringSplit($arPos[$i], "|")
    If ( IsArray($var) And UBound($var) = 3 ) Then
    $arSort[$i][0] = Number($var[1])
    $arSort[$i][1] = Number($var[2])
    EndIf
    Next
    _Array2DSortFree($arSort, '0|0,1|0')
    $fh = FileOpen($file,1)
    For $i = 0 To UBound($arSort)-1
    If $arSort[$i][0] <> "" And $arSort[$i][1] <> "" Then _
    FileWriteLine($fh, "X: " & $arSort[$i][0] & " , Y: " & $arSort[$i][1])
    Next
    FileClose($fh)
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    ;==================================================================================================
    ; Function Name: _Array2DSortFree($ARRAY, $sCOL_ASC)
    ; Description:: Sortierung von 1D/2D-Arrays nach freier Wahl
    ; 1D Sortierung Auf- oder Absteigend
    ; 2D mehrstufige Sortierung, Reihenfolge und Sortier-
    ; richtung (je Spalte) frei wählbar
    ; auch einzelne Spalte sortierbar
    ; Parameter(s): $ARRAY Das zu sortierende Array
    ; $sCOL_ASC String mit Sortierangaben "Spalte|Richtung [, Spalte|Richtung]"
    ; zu sortierende Spalte (0-Index)|Richtung (0-Asc, 1-Desc)
    ; z.B. Spalte 2 aufsteigend und in 2 absteigend Spalte 1
    ; _Array2DSortFree($ar2Sort, '2|0,1|1')
    ; Return Value(s): Erfolg 0
    ; Fehler 1 Set Error 1 $ARRAY ist kein Array
    ; 2 1D-Array, aber Spaltenangabe für 2D
    ; 3 SQL-Fehler
    ; 4 Angaben für Spalte|Sortierrichtung fehlerhaft
    ; Requirements: #include <SQLite.au3>
    ; #include <SQLite.dll.au3>
    ; Author(s): BugFix ([email='bugfix@autoit.de'][/email])
    ;==================================================================================================
    Func _Array2DSortFree(ByRef $ARRAY, $sCOL_ASC)
    If Not IsArray($ARRAY) Then Return SetError(1,0,1)
    Local $tableStr = "CREATE TABLE tblTEST ("
    Local $insertStr = '', $insertBase = "INSERT INTO tblTEST VALUES ("
    Local $sortOrder = '', $sortStr = "SELECT * FROM tblTEST ORDER BY "
    Local $aResult, $iRows, $iColumns, $iRval, $asc
    $sCOL_ASC = StringStripWS($sCOL_ASC, 8)
    Local $ub2nd = UBound($ARRAY, 2)
    If @error = 2 Then
    If (StringLen($sCOL_ASC) > 3) Or (StringLeft($sCOL_ASC, 1) <> '0') Then Return SetError(2,0,1)
    If StringRight($sCOL_ASC, 1) = 0 Then
    _ArraySort($ARRAY)
    Else
    _ArraySort($ARRAY, 1)
    EndIf
    Return 0
    Else
    Local $aOut[UBound($ARRAY)][$ub2nd]
    EndIf
    _SQLite_Startup ()
    If @error > 0 Then Return SetError(3,0,1)
    $hSQL = _SQLite_Open ()
    If @error > 0 Then
    _SQLite_Shutdown ()
    Return SetError(3,0,1)
    EndIf
    For $i = 0 To UBound($ARRAY, 2) -1
    $tableStr &= "'field" & $i & "',"
    Next
    $tableStr = StringTrimRight($tableStr, 1) & ");"
    For $i = 0 To UBound($ARRAY) -1 ; Erzeuge Insert-String
    $insertStr &= $insertBase
    For $k = 0 To UBound($ARRAY, 2) -1
    $insertStr &= "'" & $ARRAY[$i][$k] & "',"
    Next
    $insertStr = StringTrimRight($insertStr, 1) & ");"
    Next
    ; Erstelle Tabelle und füge Werte ein
    If _SQLite_Exec ( $hSQL, $tableStr & $insertStr ) <> $SQLITE_OK Then
    _SQLite_Shutdown ()
    Return SetError(3,0,1)
    EndIf
    If StringInStr($sCOL_ASC, ',') Then
    Local $aOrder = StringSplit($sCOL_ASC, ',')
    For $i = 1 To UBound($aOrder) -1
    If StringInStr($sCOL_ASC, '|') Then
    Local $var = StringSplit($aOrder[$i], '|')
    $asc = ' ASC'
    If $var[2] = 1 Then $asc = ' DESC'
    $sortOrder &= 'field' & $var[1] & $asc & ','
    Else
    _SQLite_Shutdown ()
    Return SetError(4,0,1)
    EndIf
    Next
    $sortOrder = StringTrimRight($sortOrder, 1) & ';'
    Else
    If (StringLen($sCOL_ASC) = 3) And (StringInStr($sCOL_ASC, '|')) Then
    Local $var = StringSplit($sCOL_ASC, '|')
    $asc = ' ASC'
    If $var[2] = 1 Then $asc = ' DESC'
    $sortOrder &= 'field' & $var[1] & $asc
    Else
    _SQLite_Shutdown ()
    Return SetError(4,0,1)
    EndIf
    EndIf
    $iRval = _SQLite_GetTable2d (-1, $sortStr & $sortOrder, $aResult, $iRows, $iColumns)
    If $iRval = $SQLITE_OK Then
    For $i = 1 To UBound($aResult) -1
    For $k = 0 To UBound($aResult,2) -1
    $aOut[$i-1][$k] = $aResult[$i][$k]
    Next
    Next
    Else
    _SQLite_Shutdown ()
    Return SetError(4,0,1)
    EndIf
    _SQLite_Exec ($hSQL, "DROP TABLE tblTEST;")
    _SQLite_Close ()
    _SQLite_Shutdown ()
    $ARRAY = $aOut
    Return 0
    EndFunc ;==> _Array2DSortFree

    [/autoit]
  • Vielen Dank, dass du mir dein Script zur Verfügung gestellt hast. Ich habe es schon ausprobiert und es Funktioniert auch super nur Leider habe ich eine Fragen:

    edit:

    ich habe dein script verstanden und abgeändert, leider habe ich jedoch noch ein probblem, dass ich nciht gelöst bekomme, vllt könnt ihr mir ja helfen: Für autoit ist ja oben rechts der Ursprung des Koordinatenkreuzes. Bei meinem Programm ist der Ursprung jedoch unten links, nach oben geht dann die y-Achse und nach rechts die x-Achse. Kann man das in Autoit irgendwie umstellen? oder kennt jemand einen weg die Koordinaten umzurechnen? Weil sonst ist das kopierte Bild ja spiegeltverkehrt.

    edit2:
    ich glaube ich habe edit1 gelöst (habe die koordinaten von @desktopheight bzw width abgezogen, so hab ich das koordinatensystem umgedreht, um das auf dinA4 zu bekommen hab ich die enstandenen Zahlen mit 300/@desktopwideth bzw 200/@desktopheight multipliziert) Bin mir aber nicht sicher. Was meint ihr dazu??

    Und ich habe noch eine Frage an BugFix: in deinem Script erstellst du sql tabellen. Muss dafür ein sql server laufen? weil du hast keinen sql dienst über _sqllie_open geöffnet, weil das sortieren funktioniert nicht richtig. Ich würde gerne die y-Koordinaten absteigend ordnenund dann die dazugehörigen x werte.

    Edit3 noch ein Problem: ich will ja Lienien nachbilden indem ein bild eingelesen wird, wenn ich jetzt aber die y-werte ordne. dann zeichntet der ja hin und her wenn das z.b. nen rechteck ist.


    Gruß

    filewalker

    2 Mal editiert, zuletzt von filewalker (6. Juni 2008 um 17:41)

    • Offizieller Beitrag

    Und ich habe noch eine Frage an BugFix: in deinem Script erstellst du sql tabellen. Muss dafür ein sql server laufen? weil du hast keinen sql dienst über _sqllie_open geöffnet, weil das sortieren funktioniert nicht richtig. Ich würde gerne die y-Koordinaten absteigend ordnenund dann die dazugehörigen x werte.

    Hi,
    da man in Datenbanken wunderbar mehrstufig sortieren kann, war mir die Idee gekommen einfach ein 2D-Array über den Umweg einer SQL-Tabelle mehrstufig zu sortieren.
    Und wenn du mal in Zeile 110 der Sortierfunktion schaust:

    [autoit]

    _SQLite_Startup ()
    If @error > 0 Then Return SetError(3,0,1)
    $hSQL = _SQLite_Open ()

    [/autoit]

    - wie du siehst wird hier die Datenbank temporär initialisiert. Ein SQL-Server wird nicht benötigt.

    Um Y absteigend und für gleiche Y dann X aufsteigend zu sortieren wäre der Sortierstring: "1|1,0|0"
    Somit würde die Reihenfolge der Koordinaten auf dem Desktop betrachtet von unten links nach oben rechts abgefahren.
    Da die Reihenfolge mit der Sortierung bestimmt wird, ist es ohne Belang wie die Scanrichtung ist.

  • ok. das mit dem sql server hab icgh übersehen. Die sortierfunktion habe ich auch schon verstnaden, das habe ich auch hinbekommen, nur leider nützten mir die ganzen koordinaten nichts, da ich die so nicht weiterverarbeiten kann.

    Kann man das Programm so verändern, dass es im prinzip nur die eckpunkte von Linien erkennt und nur die Koordinaten dieser Punkte aufführt?


    Gruß

    filewalker

    • Offizieller Beitrag

    Kann man das Programm so verändern, dass es im prinzip nur die eckpunkte von Linien erkennt und nur die Koordinaten dieser Punkte aufführt?


    Dazu mußt du festlegen, welche Bedingungen für die "Begrenzungspixel" gelten und daraufhin alle Pixel, für die diese Bedingungen nicht zutreffen entfernen.
    Ich würde in etwa so vorgehen:
    - linke Begrenzung: für jedes Y der kleinste X-Wert
    - rechte Begrenzung: für jedes Y der größte X-Wert
    jetzt umsortieren X-aufsteigend und innerhalb von X die Y-Werte absteigend
    - obere Begrenzung: für jedes X der kleinste Y-Wert
    - untere Begrenzung: für jedes X der größte Y-Wert
    Diese Variante erkennt nicht nur Eckpunkte, sondern alle Koordinaten des Umfangs (also auch Kreis oder Vieleck etc.).

  • so ähnlivh hab ich mir das schon gedacht, jedoch habe ich keine eindeutigen merkmale der begrenzungspixel gefunden. Ich würde das gerne mit deinen Merkmalen machen, aber wie kann ich alle werte mit allen vergleichen und dann aussortiren?