Array / Wenn nebenliegende Werte gleich, Mitte finden...

  • Hallo,

    ich habe eine Grafik von der die schwarzen Bereiche in ein Array geschrieben werden!

    Wenn nun mehrere Werte nebeneinander gleich sind möchte ich die Mitte als neuen Wert haben, weiss jemand nen Ansatz oder ne Lösung?

    Ich werd wohl mit If & ELSE arbeiten müssen, oder?

    Spoiler anzeigen
    [autoit]

    #include <GuiConstantsEx.au3>
    #include <WindowsConstants.au3>
    #include <GDIPlus.au3>
    #include <ScreenCapture.au3>
    #include <WinAPI.au3>
    #include <File.au3>
    #include <Array.au3>
    Opt('MustDeclareVars', 1)
    Local $hBitmap, $hImage, $sImageType, $iX, $iY, $iXc, $iYc, $iMemo, $iPixelColor, $Count, $File, $color1, $oForm, $color, $dc, $setpixel, $realesedc
    Local $hGraphic, $hBitmap, $hBackbuffer, $save, $hPen, $hWind
    $File = FileOpen(@ScriptDir & "\coords.txt", 2)
    _Main()
    Func _Main()
    _GDIPlus_Startup()
    $hImage = _GDIPlus_ImageLoadFromFile(@ScriptDir & '\Pic.jpg')
    $sImageType = _GDIPlus_EncodersGetCLSID("JPG")
    $iX = _GDIPlus_ImageGetWidth($hImage)
    $iY = _GDIPlus_ImageGetHeight($hImage)
    Local $aCoords[$iY][$iX]
    $oForm = GUICreate("GDI+", ($iX), ($iY))
    GUISetBkColor(0xFFFFFF)
    GUISetState()
    $hWind = WinGetHandle($oForm)
    $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hWind)
    $hBitmap = _GDIPlus_BitmapCreateFromGraphics($iX, $iY, $hGraphic)
    $hBackbuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)
    _GDIPlus_GraphicsClear($hBackbuffer, 0xFFFFFFFF)
    For $iYc = 0 To $iY - 1
    For $iXc = 0 To $iX - 1
    $iPixelColor = Hex(_GDIPlus_GetPixel($hImage, $iXc, $iYc), 6)
    If Dec($iPixelColor) < Dec('882829') Then
    $Count = $Count + 1
    FileWrite($File, $iXc & "," & $iYc & @CRLF)
    $aCoords[$iYc][$iXc] = 999999
    SetPixel($oForm, $iXc, $iYc, $color)
    $hPen = _GDIPlus_PenCreate(0xFF000000);
    _GDIPlus_GraphicsDrawLine($hBackbuffer, $iXc, $iYc, $iXc + 1, $iYc + 1, $hPen)
    _GDIPlus_GraphicsDrawLine($hGraphic, $iXc, $iYc, $iXc + 1, $iYc + 1, $hPen)
    Else
    $aCoords[$iYc][$iXc] = 0
    EndIf
    Next
    Next
    $save = _GDIPlus_ImageSaveToFile($hBitmap, @ScriptDir & '\Image1.jpg')
    Do
    Until GUIGetMsg() = $GUI_EVENT_CLOSE
    FileClose($File)
    _GDIPlus_Shutdown()
    _ArrayDisplay($aCoords, '', -1, 0)
    EndFunc ;==>_Main
    ; Gibt eine Zeile im Memo-Fenster aus
    Func MemoWrite($sMessage = '')
    GUICtrlSetData($iMemo, $sMessage & @CRLF, 1)
    EndFunc ;==>MemoWrite
    ; _GDIPlus_GetPixel
    Func _GDIPlus_GetPixel($hBitmap, $X, $Y)
    Local $result = DllCall($ghGDIPDLL, "int", "GdipBitmapGetPixel", "ptr", $hBitmap, "int", $X, "int", $Y, "dword*", 0)
    If @error Then Return SetError(1, 0, 0)
    Return SetError($result[0], 1, $result[4])
    EndFunc ;==>_GDIPlus_GetPixel
    ;SetPixel
    Func SetPixel($oForm, $X, $Y, $color)
    $dc = DllCall("user32.dll", "int", "GetDC", "hwnd", $oForm)
    $setpixel = DllCall("gdi32.dll", "long", "SetPixel", "long", $dc[0], "long", $X, "long", $Y, "long", $color)
    $realesedc = DllCall("user32.dll", "int", "ReleaseDC", "hwnd", 0, "int", $dc[0])
    EndFunc ;==>SetPixel

    [/autoit]

    Álso das Ergebnis soll ein 1-Pixel breites A sein...

    UPDATE:

    Also SEuBo hat mir helfen können, jedoch ist das Ergebnis noch nicht ganz perfekt. Ich müsste das ganze Horizontal und Vertikal durchführen, sodass keine 777777er nebeneinander liegen und die Linie nicht unterbrochen ist!

    Spoiler anzeigen
    [autoit]

    #include <GuiConstantsEx.au3>
    #include <WindowsConstants.au3>
    #include <GDIPlus.au3>
    #include <ScreenCapture.au3>
    #include <WinAPI.au3>
    #include <File.au3>
    #include <Array.au3>
    Opt('MustDeclareVars', 1)
    Local $hBitmap, $hImage, $sImageType, $iX, $iY, $iXc, $iYc, $iMemo, $iPixelColor, $count, $File, $color1, $oForm, $color, $dc, $setpixel, $realesedc
    Local $hGraphic, $hBitmap, $hBackbuffer, $save, $hPen, $hWind
    $File = FileOpen(@ScriptDir & "\coords.txt", 2)
    _Main()
    Func _Main()
    _GDIPlus_Startup()
    $hImage = _GDIPlus_ImageLoadFromFile(@ScriptDir & '\PicA.jpg')
    $sImageType = _GDIPlus_EncodersGetCLSID("JPG")
    $iX = _GDIPlus_ImageGetWidth($hImage)
    $iY = _GDIPlus_ImageGetHeight($hImage)
    Local $aCoords[$iY][$iX]
    $oForm = GUICreate("GDI+", ($iX), ($iY))
    GUISetBkColor(0xFFFFFF)
    GUISetState()
    $hWind = WinGetHandle($oForm)
    $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hWind)
    $hBitmap = _GDIPlus_BitmapCreateFromGraphics($iX, $iY, $hGraphic)
    $hBackbuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)
    _GDIPlus_GraphicsClear($hBackbuffer, 0xFFFFFFFF)
    For $iXc = 0 To $iX - 1
    For $iYc = 0 To $iY - 1
    $iPixelColor = Hex(_GDIPlus_GetPixel($hImage, $iXc, $iYc), 6)
    If Dec($iPixelColor) < Dec('882829') Then
    ;$count = $count + 1
    FileWrite($File, $iXc & "," & $iYc & @CRLF)
    $aCoords[$iYc][$iXc] = 999999
    SetPixel($oForm, $iXc, $iYc, $color)
    $hPen = _GDIPlus_PenCreate(0xFF000000);
    _GDIPlus_GraphicsDrawLine($hBackbuffer, $iXc, $iYc, $iXc + 1, $iYc + 1, $hPen)
    _GDIPlus_GraphicsDrawLine($hGraphic, $iXc, $iYc, $iXc + 1, $iYc + 1, $hPen)
    Else
    $aCoords[$iYc][$iXc] = 0
    EndIf
    Next
    Next
    $save = _GDIPlus_ImageSaveToFile($hBitmap, @ScriptDir & '\Image1.jpg')
    Do
    Until GUIGetMsg() = $GUI_EVENT_CLOSE
    FileClose($File)
    _GDIPlus_Shutdown()

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

    For $iXc = 0 To $iX - 1
    For $iYc = 0 To $iY - 1
    If $aCoords[$iXc][$iYc] = 999999 Then
    For $iYc2 = $iYc To $iY - 1
    If $aCoords[$iXc][$iYc2] = 0 Then
    ; $aCoords[$iYc][$iXc + Floor(($iXc2 - $iXc - 1) / 2)] = 777777 ; eher links ausgerichtet
    $aCoords[$iXc][$iYc + Floor(($iYc2 - $iYc) / 2)] = 777777 ; eher rechts ausgerichtet
    $iYc = $iYc2
    ExitLoop
    EndIf
    Next
    EndIf
    Next
    Next

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

    ;~ ; jede "zeile" durchgehen
    ;~ For $iYc = 0 To $iY - 1
    ;~ For $iXc = 0 To $iX - 1
    ;~ ; wenn schwarz "beginnt"
    ;~ If $aCoords[$iYc][$iXc] = 999999 Then
    ;~ ; gehe von dort aus ($iXc) weiter nach rechts, höchstens bis zum Ende des bildes.
    ;~ For $iXc2 = $iXc To $iX - 1
    ;~ ; Wenn jetzt wieder eine weißer pixel kommt, ist die schwarze linie vorbei.
    ;~ If $aCoords[$iYc][$iXc2] = 0 Then
    ;~ ; Jetzt nur noch den Mittelpunkt der Linie ermitteln (Linie ist $iXc2 [rechter endpunkt] - $iXc [linker startpunkt] lang)
    ;~ ; Davon nehmen wir die Hälfte und addieren das auf den startpunkt der linie.
    ;~ ; bsp: Linie geht von 5 bis 14. Linie ist also 9 px lang (=14-5). Jede hälfte ist dann 4,5 px lang.
    ;~ ; Die Mitte liegt dann bei 9,5 (=5+4,5). Wobei wir natürlich runden müssen.
    ;~ ; $aCoords[$iYc][$iXc + Floor(($iXc2 - $iXc - 1) / 2)] = 777777 ; eher links ausgerichtet
    ;~ $aCoords[$iYc][$iXc + Floor(($iXc2 - $iXc) / 2)] = 777777 ; eher rechts ausgerichtet
    ;~ $iXc = $iXc2
    ;~ ExitLoop
    ;~ EndIf
    ;~ Next
    ;~ EndIf
    ;~ Next
    ;~ Next
    _ArrayDisplay($aCoords, '', -1, 0)
    EndFunc ;==>_Main

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

    ; Gibt eine Zeile im Memo-Fenster aus
    Func MemoWrite($sMessage = '')
    GUICtrlSetData($iMemo, $sMessage & @CRLF, 1)
    EndFunc ;==>MemoWrite
    ; _GDIPlus_GetPixel
    Func _GDIPlus_GetPixel($hBitmap, $X, $Y)
    Local $result = DllCall($ghGDIPDLL, "int", "GdipBitmapGetPixel", "ptr", $hBitmap, "int", $X, "int", $Y, "dword*", 0)
    If @error Then Return SetError(1, 0, 0)
    Return SetError($result[0], 1, $result[4])
    EndFunc ;==>_GDIPlus_GetPixel
    ;SetPixel
    Func SetPixel($oForm, $X, $Y, $color)
    $dc = DllCall("user32.dll", "int", "GetDC", "hwnd", $oForm)
    $setpixel = DllCall("gdi32.dll", "long", "SetPixel", "long", $dc[0], "long", $X, "long", $Y, "long", $color)
    $realesedc = DllCall("user32.dll", "int", "ReleaseDC", "hwnd", 0, "int", $dc[0])
    EndFunc ;==>SetPixel

    [/autoit]

    Oder das das Array vllt. ungefair so dargestellt wird wie bei "Minesweeper". Das der Wert des Array-Feldes der Anzahl der nebenliegenden schwarzen Pixel beträgt!?!

    Kennt jemand so eine Formel?

    Oder das man wie oben erst einmal horizontal und dann nochmal vertikal "scannt"!

    Spoiler anzeigen
    [autoit]

    ;~ ; jede "zeile" durchgehen
    ;~ For $iYc = 0 To $iY - 1
    ;~ For $iXc = 0 To $iX - 1
    ;~ ; wenn schwarz "beginnt"
    ;~ If $aCoords[$iYc][$iXc] = 999999 Then
    ;~ ; gehe von dort aus ($iXc) weiter nach rechts, höchstens bis zum Ende des bildes.
    ;~ For $iXc2 = $iXc To $iX - 1
    ;~ ; Wenn jetzt wieder eine weißer pixel kommt, ist die schwarze linie vorbei.
    ;~ If $aCoords[$iYc][$iXc2] = 0 Then
    ;~ ; Jetzt nur noch den Mittelpunkt der Linie ermitteln (Linie ist $iXc2 [rechter endpunkt] - $iXc [linker startpunkt] lang)
    ;~ ; Davon nehmen wir die Hälfte und addieren das auf den startpunkt der linie.
    ;~ ; bsp: Linie geht von 5 bis 14. Linie ist also 9 px lang (=14-5). Jede hälfte ist dann 4,5 px lang.
    ;~ ; Die Mitte liegt dann bei 9,5 (=5+4,5). Wobei wir natürlich runden müssen.
    ;~ ; $aCoords[$iYc][$iXc + Floor(($iXc2 - $iXc - 1) / 2)] = 777777 ; eher links ausgerichtet
    ;~ $aCoords[$iYc][$iXc + Floor(($iXc2 - $iXc) / 2)] = 777777 ; eher rechts ausgerichtet
    ;~ $iXc = $iXc2
    ;~ ExitLoop
    ;~ EndIf
    ;~ Next
    ;~ EndIf
    ;~ Next
    ;~ Next

    [/autoit]