Jump to content

Pixelsearch help


Recommended Posts

Is there a way to tell Pixelsearch to click a random pixel of the correct color instead of the first one it finds going top to bottom, left to right, ect? The correct color shows up on the screen in multiple places and I would like it to pick one of them randomly instead of the same one every time.

Link to comment
Share on other sites

Maybe the question is related to this thread: I need help with Arrays and Errors.

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2022-02-19 - Version 1.6.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (NEW 2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to comment
Share on other sites

Is there a way to tell Pixelsearch to click a random pixel of the correct color instead of the first one it finds going top to bottom, left to right, ect? The correct color shows up on the screen in multiple places and I would like it to pick one of them randomly instead of the same one every time.

Looks like you didn't already get what you needed /s

Link to comment
Share on other sites

Here are two methods.

This first method randomly selects a smaller area within the given search area, then, randomly searches that small area either left-to-right or right-to-left; and, either top-to-bottom or bottom-to-top.

#cs
    Script's objective:- A way to tell Pixelsearch to click a random pixel of the specified colour.
    From AutoIt help file:-
        PixelSearch ( left, top, right, bottom, color [, shade-variation = 0 [, step = 1 [, hwnd]]]
        The search direction varies as follows:
        Left-to-Right - left < right
        Right-to-Left - right < left
        Top-to-Bottom - top < bottom
        Bottom-to-Top - bottom < top
        Changing the search direction can be a useful optimization if the color being searched for frequently appears in in
        a specific quadrant of the search area since less searching is done if the search starts in the most common quadrant.
    #ce

    ; For full screen search
$a = _PixelSearchRandom(0, 0, @DesktopWidth, @DesktopHeight, 0x0000FF, 0) ; 0x0000FF = Blue
If @error Then
    MsgBox(0, "Error", @extended & " segments searched, colour not found.")
Else
    MouseMove($a[0], $a[1])
    MouseClick("primary")
EndIf


; Divide the search area along the X-axis into $iX_NumOfSeg, and, along the Y-axis into $iY_NumOfSeg, thus creating ($iX_NumOfSeg multiply by
; $iY_NumOfSeg) number of segements.   Then randomly select a segment, and randomly search that segment either Left-to-Right or Right-to-Left,
; and, either Top-to-Bottom or Bottom-to-Top.   Continue selecting and searching random segments until colour is found.
Func _PixelSearchRandom($iLeft, $iTop, $iRight, $iBottom, $iColor, $shade_variation = 0, $iX_NumOfSeg = 16, $iY_NumOfSeg = 12, $iStep = 1, $hwnd = "")
    Local $iMiss = 0, $sUniqueSegNum = "|"
    Local $iSegWidth = ($iRight - $iLeft) / $iX_NumOfSeg
    Local $iSegHeight = ($iBottom - $iTop) / $iY_NumOfSeg
    ConsoleWrite("Segment Width x Height = " & $iSegWidth & " x " & $iSegHeight & @LF)
    ConsoleWrite("=========================================" & @LF)

    While 1
        Local $iSegment = Random(1, $iX_NumOfSeg * $iY_NumOfSeg, 1) ; Get Random segment.
        If StringInStr($sUniqueSegNum, "|" & $iSegment & "|") = 0 Then ; Ensures each segment is searched only once.
            ; Add random segment number to test string. Example: If $sUniqueSegNum = "|10|110|" then search for "|1|" will not be found, and,
            ;   "1|" will be added to end of $sUniqueSegNum, making $sUniqueSegNum = "|10|110|1|"
            $sUniqueSegNum &= $iSegment & "|"
        Else ; "|" & $iSegment & "|"  - already exists in the unique test string, $sUniqueSegNum,  so start loop again.
            ConsoleWrite("    " & $iSegment & "  Continue Loop" & @LF)
            ContinueLoop ; Start While loop again
        EndIf
        ConsoleWrite($iMiss & ": Random Segment = " & $iSegment)

        ; Find right-bottom corner of segment - coordinates ($iRightSegNumber_X, $iBottomSegNumber_Y)
        Local $iRightSegNumber_X = Mod($iSegment, $iX_NumOfSeg) + (Mod($iSegment, $iX_NumOfSeg) = 0) * $iX_NumOfSeg
        Local $iBottomSegNumber_Y = Ceiling($iSegment / $iX_NumOfSeg)
        ConsoleWrite("  Search segment with Right-Botton Corner, grid Coord (X, Y) = " & $iRightSegNumber_X & ", " & $iBottomSegNumber_Y & @TAB)

        ; Convert grid numbers to pixel lengths for PixelSearch function.
        Local $iLeftSeg = ($iRightSegNumber_X - 1) * $iSegWidth
        Local $iRightSeg = $iRightSegNumber_X * $iSegWidth
        Local $iTopSeg = ($iBottomSegNumber_Y - 1) * $iSegHeight
        Local $iBottomSeg = $iBottomSegNumber_Y * $iSegHeight

        ; Randomly change search direction.
        If Random(0, 1, 1) Then ; Search Left-to-Right when $iLeftSeg < $iRightSeg.  Or, search Right-to-Left when  $iRightSeg < $iLeftSeg.
            ; Swap, because random = 1
            $Temp = $iLeftSeg
            $iLeftSeg = $iRightSeg
            $iRightSeg = $Temp
        EndIf
        If Random(0, 1, 1) Then ; Search Top-to-Bottom when $iTopSeg < $iBottomSeg.  Or, search Bottom-to-Top when $iBottomSeg < $iTopSeg.
            ; Swap, because random = 1
            $Temp = $iTopSeg
            $iTopSeg = $iBottomSeg
            $iBottomSeg = $Temp
        EndIf

        $aCoord = PixelSearch($iLeftSeg, $iTopSeg, $iRightSeg, $iBottomSeg, $iColor, $shade_variation, $iStep, $hwnd)
        $iMiss += @error
        If IsArray($aCoord) Then Return SetError(0, $iMiss, $aCoord)
        If ($iMiss >= ($iX_NumOfSeg * $iY_NumOfSeg) - 1) Then Return SetError(1, $iX_NumOfSeg * $iY_NumOfSeg, 0) ; All segments searched - nothing found.
        ConsoleWrite("  Colour not found" & @LF)
    WEnd
EndFunc   ;==>_PixelSearchRandom

 

The next script can find all occurrences of a specified pixel colour with parameter "Step" = 1, and put all those  pixel's coordinates into an array.
To speed the process up, increase the "Step" size.  However, not all specified colour pixels are certain to be found.
Testing:-
Using Step = 1,  found 2483 pixels of specific colour in 78.667 secs; and, on the same search area,
using Step = 10,  found 20 pixels of specific colour in 0.870 secs.
Also,
using Step = 1,   found 222 pixels of specific colour in 7.531 secs; and, on the same search area,
using Step = 10,  found 10 pixels of specific colour in 0.455 secs.

#include <Array.au3>

Local $hTimer = TimerInit()
$aArray = _PixelSearchArray(0, 0, @DesktopWidth, @DesktopHeight, 0x0000FF, 0, 10)
If Not @error Then
    MsgBox(0, "Taken: " & Round(TimerDiff($hTimer) / 1000, 3) & " secs", "Start Random Selection")
    For $i = 1 To 4
        $Rnd = Random(1, UBound($aArray) - 1, 1) ; Random array index
        MouseMove($aArray[$Rnd][0], $aArray[$Rnd][1])
        MouseClick("primary")
        MsgBox(0, "Mouse click #" & $i & " of 4", 'Random array index "' & $Rnd & '"   Coords X, Y = ' & $aArray[$Rnd][0] & ', ' & $aArray[$Rnd][1])
    Next
    _ArrayDisplay($aArray)
Else
    MsgBox(0, "Error", "Colour not found.")
EndIf


; Returns an array of coordinates of all found specified colour in a search area. The rectangular search area
; being enclosed by the ($iLeft, $iTop) coordinate, to the ($iRight, $iBottom) coordinate.
Func _PixelSearchArray($iLeft, $iTop, $iRight, $iBottom, $iColor, $iShade_Variation = 0, $iStep = 1, $hWnd = "")
    Local $aRetArr[500][2], $iCount = 0

    Local $aCoord = PixelSearch($iLeft, $iTop, $iRight, $iBottom, $iColor, $iShade_Variation, $iStep, $hWnd)
    If Not @error Then
        $iCount += 1
        $aRetArr[$iCount][0] = $aCoord[0]
        $aRetArr[$iCount][1] = $aCoord[1]
    Else
        Return SetError(1, 0, 0)
    EndIf
    While 1
        If ($aRetArr[$iCount][0]) <= $iRight Then
            While 1 ; Search the rest of the line only, for more matching pixels.
                $aCoord = PixelSearch($aRetArr[$iCount][0] + 1, $aRetArr[$iCount][1], $iRight, $aRetArr[$iCount][1], $iColor, $iShade_Variation, $iStep, $hWnd)
                If Not @error Then
                    If UBound($aRetArr) - 1 = $iCount Then ReDim $aRetArr[UBound($aRetArr) + 200][2]
                    $iCount += 1
                    $aRetArr[$iCount][0] = $aCoord[0]
                    $aRetArr[$iCount][1] = $aCoord[1]
                Else ; No more matching pixels on this line.
                    ExitLoop
                EndIf
            WEnd
        EndIf
        ; Search the rest of the search area from Left to Right, Top to Bottom with new Top, being the last found pixel's line plus one.
        $aCoord = PixelSearch($iLeft, $aRetArr[$iCount][1] + 1, $iRight, $iBottom, $iColor, $iShade_Variation, $iStep, $hWnd)
        If Not @error Then
            If UBound($aRetArr) - 1 = $iCount Then ReDim $aRetArr[UBound($aRetArr) + 200][2]
            $iCount += 1
            $aRetArr[$iCount][0] = $aCoord[0]
            $aRetArr[$iCount][1] = $aCoord[1]
            ;_ArrayDisplay($aRetArr)
        Else
            ExitLoop
        EndIf
    WEnd
    ReDim $aRetArr[$iCount + 1][2]
    $aRetArr[0][0] = $iCount
    Return $aRetArr
EndFunc   ;==>_PixelSearchArray

 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...