Skocz do zawartości
  • 👋 Witaj na MPCForum!

    Przeglądasz forum jako gość, co oznacza, że wiele świetnych funkcji jest jeszcze przed Tobą! 😎

    • Pełny dostęp do działów i ukrytych treści
    • Możliwość pisania i odpowiadania w tematach
    • System prywatnych wiadomości
    • Zbieranie reputacji i rozwijanie swojego profilu
    • Członkostwo w jednej z największych społeczności graczy

    👉 Dołączenie zajmie Ci mniej niż minutę – a zyskasz znacznie więcej!

    Zarejestruj się teraz

AutoHotkey - multiImagesearch()


Rekomendowane odpowiedzi

Opublikowano

Wrzucam rozbudowaną przeze mnie funkcję Gdip_ImageSearch() - mam nadzieję, że się komuś przyda. Powstała ona na potrzeby mojego bota do Clash of Clans: http://runcbot.com
Obsługuje zarówno tryb zwykły jak i pracę w tle.
 
Przed użyciem warto zmodyfikować, jeśli to potrzebne, wartości w sekcji "USTAWIENIA DOMYŚLNE" (są ustawione pod BlueStacks o określonych wymiarach okna) - w innym przypadku trzeba będzie za każdym razem podawać ustawienia okna jako parametr funkcji
 
Jeśli będą chętni to opublikuję bliźniaczą funkcję dla wyszukiwania pikseli (muszę dokończyć dla niej dokumentację).
 
Reszta dokumentacji w treści.

 

 

 

;*********************************************************************************************************************************************************************
;
; multiImageSearch()
;
;********************************************************************************************************************************************************************
;
; autor: kap (Maciej Caderek)
; ostatnia modyfikacja: 2015-03-28 06:45
; Licensed under CC BY-SA 3.0 -> http://creativecommons.org/licenses/by-sa/3.0/
;
; Wymagania:
; Gdip by tic (Tariq Porter) - http://www.autohotkey.com/board/topic/29449-gdi-standard-library-145-by-tic/
; Gdip_ImageSearch() by MasterFocus - https://github.com/MasterFocus/AutoHotkey/blob/master/Functions/Gdip_ImageSearch/Gdip_ImageSearch.ahk
;
;********************************************************************************************************************************************************************
;
;--------------------------------
; ++OPIS++
;--------------------------------
;
; Funkcja posiada trzy główne mechanizmy:
; 1) Wielokrotnie wyszukuje wzorzec - przydatne gdy szukany element nie jest widoczny na ekranie cały czas.
; 2) Wyszykuje element wśród całego zestawu wzorców - przydatne gdy w badanym obszarze mogą występować różne elementy.
; 3) Dzieli podany wzorzec na plastry o szerokości 1px i wyszukuje kolejne plastry na ekranie aż do uzyskania trafienia
;    - przydatne gdy obraz na ekranie nie zawsze dokładnie odpowiada zadanemu wzorcowi.
; Wszystkie powyższe mechanizmy można zastosować równocześnie.
;
;--------------------------------
; ++PARAMETRY++
;--------------------------------
;
;-> pathSet [string]:             (wymagana) zmienna określa ścieżkę dostępu do wzorca lub zestawu wzorców (aby podać zestaw wzorców należy rozdzielić nazwy plików znakami |)
;                                 uwaga: jeżeli określono zestaw wzorców to funkcja sprawdza je po kolei i kończy działanie jeśli znajdzie jeden z nich 
;                                        (kolejność sprawdzania zgodna z zapisem)
;                                 uwaga: póki co zestaw wzorców musi znajdować się w tym samym folderze
;
;       PRZYKŁADY
;       "folder\wzorce\img.png"
;       "obrazy\img1|img2|img3|img4.png"
;       "obrazy\img1|img3|img2.png"
;
;-> coordSet [string]:            (opcjonalna) zmienna zawiera ciąg ustawień współrzędnych wejściowych i wyjściowych
;
;       Domyślna wartość:         "0, 0, clientW, clientH | 0 | topLeft"
;       Schemat ciągu:            "inputCoords | tolerance | outputCoords"
;       Objaśnienie:              inputCoords      - koordynanty obszaru wyszukiwania - dozwolone jest podanie dwóch lub czterech współrzędnych:
;                                                       a) dwie współrzędne - użytkownik określa spodziewany punkt początkowy wystąpienia wzorca na ekranie,
;                                                       funkcja automatycznie ustawi jako obszar szukania prostokąt wielkości wzorca powiększony z każdej strony o wartość parametru tolerance
;                                                        cztery współrzedne - użytkownik określa dokładny obszar szukania - punkt początkowy i końcowy   
;                                 tolerance        - rozszerzenie obszaru wyszukiwania w stosunku do wielkości wzorca (ma zastosowanie gdy użytkownik poda dwie współrzędne w parametrze inputCords
;                                 outputCoords     - względne wobec wzorca położenie współrzędnych zwracanych przez funkcję, dozwolone wartości:
;                                                       a) słowo kluczowe: topLeft, topRight, bottomLeft, bottomRight, center
;                                                        dowolny punkt względem lewego górnego rogu wzorca  - jeśli stosujemy zestaw wzorców możemy podać odpowiadajaca mu liczbę
;                                                          par współrzędnych lub jedną wspólną parę współrzędnych, współrzędne oddzielamy znakami "," a poszczególne pary znakami ";"
;       
;       PRZYKŁADY
;       "50, 60"
;       "50, 60 | 10 | center"
;       "0, 0, 800, 600 | | 10, 15"
;       "37,200 | | 10,15 ; 13,10 ; 14,27"
;       "| | ; 25,20 ; center ; ; 20,25"       uwaga: w przypadku outputCords pominięte elementy zostaną zastąpione wartością pierwszego elementu,
;                                                   jeśli pierwszy element zostanie pominięty przyjmie on wartość domyślną (topLeft)
;
;-> searchSet [string]:           (opcjonalna) zmienna zawiera ciąg standardowych ustawień wyszukiwania da funkcji Gdip_ImageSearch()
;                                 uwaga: poniżej zamieszczono tylko skrótowe informacje - pełen opis w Gdip_ImageSearch.ahk
;
;       Domyślna wartość:         "0 | 1 |   | ; | ,"
;       Schemat ciągu:            "variation | instances | trans | searchDirection | lineDelim | coordDelim"
;       Objaśnienie:              variation        - liczba dopuszczalnych wariacji (odcieni) każdej z wartości RGB - dozwolone wartości: 0-255
;                                 instances        - maksymalna liczba wyszukiwanych wzorców - dozwolone wartości: 0+ (0 = all)
;                                 trans            - kolor, który ma byc zastąpiony przezroczystością - dozwolone wartości: 0-0xFFFFFF
;                                 lineDelim        - separator poszczególnych trafień - dozwolone wartości: dowolny znak
;                                 coordDelim       - separator poszczególnych współrzędnych - dozwolone wartości: dowolny znak
;       
;       PRZYKŁADY
;       "40 | 0 "                   uwaga: pominięte parametry przyjmą ustawienia domyślne
;       "20 |   | 0xFFFFFF | 8"     uwaga: wszelkie spacje są opcjonalne
;
;-> repeatSet [string]:           (opcjonalna) zmienna zawiera ciąg ustawień powtarzania wyszukiwania wzorca
;
;       Domyślna wartość:         "1 | 500"
;       Schemat ciągu:            "repeatMax | repeatPeriod"
;       Objaśnienie:              repeatMax        - maksymalna liczba powtórzeń wyszukiwania - dozwolone wartości: 1+
;                                 repeatPeriod     - odstęp w milisekundach pomiędzy kolejnymi próbami wyszukania wzorca - dozwolone wartości: 0+
;       
;       PRZYKŁADY
;       "5"                       uwaga: pominięte parametry przyjmą ustawienia domyślne
;       "20 | 1000"               uwaga: wszelkie spacje są opcjonalne
;  
;-> sliceSet [string]:            (opcjonalna) zmienna zawiera ciąg ustawień wyszukiwania wzorca pociętego na plastry
;
;       Domyślna wartość:         "none | 1"
;       Schemat ciągu:            "sliceType | sliceHits"
;                                 sliceType        - kierunek cięcia wzorca - dozwolone wartości: none, horizontal, vertical, both
;                                 sliceHits        - liczba trafień poszczególnych plastrów jaka jest potrzebna aby uznać wzorzec za dopasowany
;                                                    opcja póki co nieaktywna - przyjęta jest wartość 1
;       
;       PRZYKŁADY
;       "horizontal"              uwaga: pominięte parametry przyjmą ustawienia domyślne
;       "both | 3"                uwaga: wszelkie spacje są opcjonalne (póki co cyfra 3 zostanie zignorowana)
;
;-> clientSet [string]:           (opcjonalna) zmienna zawiera ciąg ustawień okna roboczego
;
;       Domyślna wartość:         "BlueStacks App Player | 868 | 720"
;       Schemat ciągu:            "winName | clientW | clientH"
;       Objaśnienie:              winName          - nazwa używanego okna
;                                 clientW          - szerokość obszaru roboczego używanego okna
;                                 clientH          - wysokość obszaru roboczego używanego okna
;       
;       PRZYKŁADY
;       "Window Name | 800 | 600"      
;
;
;--------------------------------
; ++ZWRACANE WARTOŚCI++
;--------------------------------
;
;   Funkcja zwraca tablicę asocjacyjną zawierającą następujące elementy:
;       
;       arrayName["hits"]         - liczba trafień: 1 - znaleziono wzorzec, 0 - nie znaleziono wzorca, liczba ujemna - błąd podczas wykonywania funkcji
;       arrayName["coord"]*       - współrzędne punktu, w którym znaleziono wzorzec (lub współrzędne zmodyfikowane przez parametr outputCoords)
;       arrayName["name"]*        - nazwa pliku (bez rozszerzenia) ze znalezionym wzorcem
;
;       *elementy oznaczone gwiazdką będą dostępne tylko jeśli funkcja zaliczy trafienie
;
;********************************************************************************************************************************************************************
;
;   UWAGA: Jeśli pozostawisz wszstkie wartości jako domyślne wynik działania funkcji będzie podobny do zwykłego ImageSearch / Gdip_ImageSearch()
;
;********************************************************************************************************************************************************************
;********************************************************************************************************************************************************************

;#Include Gdip.ahk
;#Include Gdip_ImageSearch.ahk

multiImageSearch(pathSet, coordSet = "", searchSet = "", repeatSet = "", sliceSet = "", clientSet = "")
{
    result := [] ; zainicjowanie tablicy wyników
    
    ;##### USTAWIENIA DOMYŚLNE #####
    
    screenMode := 1 ; 0 = normal / 1 = background
    
    variation := 0
    instances := 1
    trans := ""
    searchDirection := 1
    lineDelim := "+"
    coordDelim := ","
    
    repeatMax := 1
    repeatPeriod := 500
    
    sliceType := "none"
    sliceHits := 1
    
    winName := "BlueStacks App Player"
    clientW := 868
    clientH := 720
    gameW := clientW
    gameH := 672
    
    inputCoords := [0, 0, 0, 0]
    tolerance := 0
    outputCords := "topLeft"
    
    ;##### WCZYTYWANIE USTAWIEŃ #####
    
    SplitPath, pathSet, , dir, extension, nameNoExt
    imgNames := StrSplit(nameNoExt, "|", " ")
    
    if(searchSet != "")
    {
        searchSet := StrSplit(searchSet, "|", " ")
        searchSetCount := searchSet._MaxIndex()
        if(searchSet[1] != "")
            variation := searchSet[1]
        if(searchSetCount > 1 AND searchSet[2] != "")
            instances := searchSet[2]
        if(searchSetCount > 2 AND searchSet[3] != "")
            trans := searchSet[3]
        if(searchSetCount > 3 AND searchSet[4] != "")
            lineDelim := searchSet[4]
        if(searchSetCount > 4 AND searchSet[5] != "")
            coordDelim := searchSet[5]
    }
    
    if(repeatSet != "")
    {
        repeatSet := StrSplit(repeatSet, "|", " ")
        repeatSetCount := repeatSet._MaxIndex()
        if(repeatSet[1] != "")
            repeatMax := repeatSet[1]
        if(repeatSetCount > 1 AND repeatSet[2] != "")
            repeatPeriod := repeatSet[2]
    }
    
    if(sliceSet != "")
    {
        sliceSet := StrSplit(sliceSet, "|", " ")
        sliceSetCount := sliceSet._MaxIndex()
        if(sliceSet[1] != "")
            sliceType := sliceSet[1]
        if(sliceSetCount > 1 AND sliceSet[2] != "")
            sliceHits := sliceSet[2]
    }
    
    if(clientSet != "")
    {
        clientSet := StrSplit(clientSet, "|", " ")
        clientSetCount := clientSet._MaxIndex()
        if(clientSet[1] != "")
            winName := clientSet[1]
        if(clientSetCount > 1 AND clientSet[2] != "")
            clientW := clientSet[2]
        if(clientSetCount > 2 AND clientSet[3] != "")
            clientH := clientSet[3]
    }
    
    if(coordSet != "")
    {
        coordSet := StrSplit(coordSet, "|", " ")
        coordSetCount := coordSet._MaxIndex()
        if(coordSet[1] != "")
        {
            inputCoords := coordSet[1]
            inputCoords := StrSplit(inputCoords, ",", " ")
        }
        if(coordSetCount > 1 AND coordSet[2] != "")
        {
            tolerance := coordSet[2]
        }
        if(coordSetCount > 2 AND coordSet[3] != "")
        {
            outputCords := coordSet[3]
        }
    }
    outputCords := StrSplit(outputCords, ";", " ")
    
    if(inputCoords._MaxIndex() = 4)
    {
        x1 := inputCoords[1]
        y1 := inputCoords[2]
        x2 := inputCoords[3]
        y2 := inputCoords[4]
    }
    else if(inputCoords._MaxIndex() = 2)
    {
        x1 := inputCoords[1] - tolerance
        y1 := inputCoords[2] - tolerance
        subx2 := inputCoords[1] + tolerance
        suby2 := inputCoords[2] + tolerance
    }
    else
        MsgBox multiImageSearch() ERROR: line 256
        
    ;##### WYSZUKIWANIE BITMAPY #####
    
    pToken := Gdip_Startup()
    WinGetPos, winX, winY, winW, winH, %winName%
    winBorder := (winW-clientW)/2
    if(screenMode = 1)
    {
        wShiftX := winBorder
        wShiftY := winH-clientH-winBorder
    }
    else
    {
        winX := winX+winBorder
        winY := winY+(winH-clientH-winBorder)
    }

    
    i := 0
    Loop ; pętla powtarza wyszukiwanie zadana ilość razy (lub przerywa gdy trafi)
    {
        i++
        if(i > repeatMax)
        {
            result["hits"] := 0
            Gdip_ShutDown(pToken)
            return result
        }
        else if(i > 1)
            Sleep repeatPeriod
            
        if(screenMode = 1)
        {
            WinGet, hwnd, , %winName%
            windowArea := Gdip_BitmapFromHWND(hwnd)
            haystack := Gdip_CloneBitmapArea(windowArea, wShiftX, wShiftY, gameW, gameH)
            Gdip_DisposeImage(windowArea)
        }
        else
            haystack := Gdip_BitmapFromScreen(winX "|" winY "|" gameW "|" gameH)
        ;Gdip_SaveBitmapToFile(haystack, "haystack.png")
            
        for index, imgName in imgNames
        {
            path := dir "\" imgName "." extension
            pattern := Gdip_CreateBitmapFromFile(path)
            Gdip_GetDimensions(pattern, patternW, patternH)
            if(inputCoords._MaxIndex() = 2)
            {
                x2 := subx2 + patternW
                y2 := suby2 + patternH
            }

            Loop ; pętla wykonuje wyszukiwanie horyzontalne i wertykalne jeśli parametr sliceType = "both"
            {   
                if(sliceType = "both")
                {
                    sliceType := "horizontal"
                    onceAgain := true
                }
                movingCoord := 0
                Loop ; pętla wyszukuje kolejne linie wzorca aż do trafienia
                {
                    if(sliceType = "horizontal")
                    {
                        needleX := 0
                        needleY := movingCoord
                        endCoord := patternH
                        needleW := patternW
                        needleH := 1
                    }
                    else if(sliceType = "vertical")
                    {
                        needleX := movingCoord
                        needleY := 0
                        endCoord := patternW
                        needleW := 1
                        needleH := patternH
                    }
                    
                    if(sliceType = "horizontal" OR sliceType = "vertical")
                    {
                        if(movingCoord = endCoord)
                            break
                        needle := Gdip_CloneBitmapArea(pattern, needleX, needleY, needleW, needleH)
                    }
                    else
                        needle := pattern
                    
                    ;#########################################################################################################################################                   
                    hits := Gdip_ImageSearch(haystack, needle, coordList, x1, y1, x2, y2, variation, trans, , instances, lineDelim, coordDelim)
                    ;######################################################################################################################################### 
                    if(hits > 0)
                    {
                        if(outputCords[index] AND outputCords[index] != "")
                            outShift := outputCords[index]
                        else if(outputCords[1] != "")
                            outShift := outputCords[1]  
                        else
                            outShift := "topLeft"  

                        if(outShift = "topLeft")
                        {
                            xShift := 0
                            yShift := 0
                        }
                        else if(outShift = "center")
                        {
                            xShift := patternW / 2
                            yShift := patternH / 2
                        }
                        else if(outShift = "topRight")
                        {
                            xShift := patternW
                            yShift := 0
                        }
                        else if(outShift = "bottomLeft")
                        {
                            xShift := 0
                            yShift := patternH
                        }
                        else if(outShift = "bottomRight")
                        {
                            xShift := patternW
                            yShift := patternH
                        }
                        else
                        {
                            outShift := StrSplit(outShift, ",", " ")
                            xShift := outShift[1]
                            yShift := outShift[2]
                        }
                        
                        finalHits := 0                       
                        coordList := StrSplit(coordList, lineDelim, " ")
                        for indexx, coord in coordList
                        {
                            coord := StrSplit(coord, coordDelim, " ")
                            if(indexx = 1 OR coord[1] < lastX1 OR coord[1] > lastX2 OR coord[2] < lastY1 OR coord[2] > lastY2) ; sprawdzenie czy dany znaleziona igła nie nalezy do tego samego wzorca co poprzednia
                            {
                                if(sliceType = "horizontal")
                                {
                                    lastX1 := coord[1]
                                    lastY1 := coord[2] - movingCoord
                                    lastX2 := coord[1] + patternW
                                    lastY2 := coord[2] - movingCoord + patternH
                                    x := Round(coord[1] + xShift)
                                    y := Round(coord[2] - movingCoord + yShift)
                                }
                                else if(sliceType = "vertical")
                                {
                                    lastX1 := coord[1] - movingCoord
                                    lastY1 := coord[2]
                                    lastX2 := coord[1] - movingCoord + patternW
                                    lastY2 := coord[2] + patternH
                                    x := Round(coord[1] - movingCoord + xShift)
                                    y := Round(coord[2] + yShift)
                                }
                                else
                                {
                                    lastX1 := coord[1]
                                    lastY1 := coord[2]
                                    lastX2 := coord[1] + patternW
                                    lastY2 := coord[2] + patternH
                                    x := Round(coord[1] + xShift)
                                    y := Round(coord[2] + yShift)
                                }
                                if(indexx = 1)
                                    finalList := x "," y
                                else
                                    finalList := finalList ";" x "," y
                                finalHits++
                            }
                        }
                        
                        result["hits"] := finalHits
                        result["coords"] := finalList
                        result["name"] := imgName
                        Gdip_DisposeImage(pattern)
                        Gdip_DisposeImage(haystack)
                        Gdip_ShutDown(pToken)
                        
                        return result
                    }
                    else if(hits < 0)
                    {
                        result["hits"] := hits
                        Gdip_DisposeImage(pattern)
                        Gdip_DisposeImage(haystack)
                        Gdip_ShutDown(pToken)
                        return result
                    }
                    if(sliceType = "none")
                        break
                    Gdip_DisposeImage(needle)
                    movingCoord++
                }
                
                if(onceAgain = true)
                {
                    sliceType := "vertical"
                    onceAgain := false
                }
                else
                    break
            }
            Gdip_DisposeImage(pattern)         
            if(index = imgNames._MaxIndex())
                break
        }
        Gdip_DisposeImage(haystack)
    }
} 

 

 

Chcesz precyzyjnej i zrozumiałej odpowiedzi? - Zadaj precyzyjne i zrozumiałe pytanie. Nie przyjmuję zleceń.
Nie odpowiadam na priv na pytania, które można zadać na forum. Chcesz mojej pomocy - oznacz mnie w poście =>  @"Hans Kloss PL" 

Zarchiwizowany

Ten temat przebywa obecnie w archiwum. Dodawanie nowych odpowiedzi zostało zablokowane.

×
×
  • Dodaj nową pozycję...