Jump to content

Extraordinary PixelSearch


Recommended Posts

Is it possible to make a pixelsearch that clicks in the middle of this:

Posted Image

Normal PixelSearch function:

$Left=0
$Top=0
$Right=1279
$Bottom=1023
While 1
$Search=PixelSearch ($Left,$Top,$Right,$Bottom,0xFFFFFF,1,1)
If Not @error Then MouseClick ("Left",$Search[0],$Search[1],1,10)
Sleep(20)
WEnd

The normal pixelsearch won't work because this has the red color 2 times before it has the one in the midle... It isn't possible to know the exact position as it's supposed to be a game, and you must hit in the midle, and it isn't allways at the same place.

I don't even know which game it is, I just wonder if it is possible to hit the one in the midle.

Hope some of you know the answer! :)

Edited by Reinn
Link to comment
Share on other sites

Is it always a perfect circle??

Then you can find the 4 points on the edges (where it becomes white) and find the middle from there...

Else you can count red, then white, then red then white then red kind of thing... So you search till you find red, then youserch till white etc.

I'm sure its possible, you just gotta work out the logistics.

MDiesel

Link to comment
Share on other sites

;=========================================================
;Reinn's 'Shooting gallery' bot
;=========================================================
;Version 1.0
;=========================================================
;Made by:
;Reinn at www.Fleud.com
;Reinn at www.Autoitscript.com
;FleudReinn at www.Youtube.com
;=========================================================
;www.Fleud.com for updates
;=========================================================
;Credits to: Fleud.com, AutoItscript.com for making AutoIt
;=========================================================
;Extra credits to: MDiesel, More to come!
;=========================================================

#include <GUIConstants.au3>

HotKeySet('^A', 'Search')

$Form1 = GUICreate("Reinn's 'Shooting gallery' bot", 354, 179, 193, 125)
$Combo1 = GUICtrlCreateCombo("1280 * 1024", 112, 112, 121, 25)
GUICtrlSetData(-1, "1024 * 768")
$Label1 = GUICtrlCreateLabel("Resolution:", 144, 88, 57, 17)
$Edit1 = GUICtrlCreateEdit("", 16, 8, 321, 73)
GUICtrlSetData(-1, StringFormat("This bot was made by Reinn from www.Fleud.com\r\n\r\n1. Start your web browser, and go to the "&Chr(34)&"Shooting gallery"&Chr(34)&" url.\r\n2. Start a game.\r\n3. Hold down CTRL, SHIFT & press on "&Chr(34)&"S"&Chr(34)&".\r\n\r\nFleud.com nor Reinn are responsible for what this is used for - Educational purposes only."))
GUISetState(@SW_SHOW)

$Left=200
$Top=1000
$Right=800
$Bottom=500

While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch
    $Search=PixelSearch ($Left,$Top,$Right,$Bottom,#ff0000,1,1)
    Switch $Search
    If Not @error Then MouseClick ("Left",$Search[0],$Search[1],1,10)
    Sleep(20)
    ;After you've shoot 5 times it needs to reload by clicking at: MouseClick("Left",598,549,1) if you use 1024*768 & at: MouseClick("Left",760,713,1) if you use 1280*768
    EndSwitch
WEnd

I've got this so far... And I don't care if it presses in the complete mid, just that it hits the circle...

Link to comment
Share on other sites

That switch statement is wrong.

Switch Var
Case Statement
;;;
EndSwitch

So that won't work.

As far as Clicking in different places for reloading, Use macros where possible.

MDesel

It's the same place you reload, it's just the resolution of your screen... Some have 1024 * 768 & some have 1280 * 1024 :) (I use the seconds one ^^)
Link to comment
Share on other sites

Well, this looked like a fun one to play with, but I've changed my mind! It's my first time playng with pixels and is a pain-in-the-butt!

I thought you'd first want to locate a group of consecutive white pixels on a horizontal line. Since PixelSearch() works in a rectange, I realized that, for instance, a white square on the left of the screen, would register a hit, and I'd need special handling to continue the search on the same line. So I dropped PixelSearch(). The image quality came to be a problem, there's a wide variety of "red" in that image, and colors other than red and white. Maybe you uploaded it in low-quality, but I had to widen the definition of "red" considerably, and still do cleanup on the image. I got the following routine to get a "hit" on the bullseye, but it currently only has a paragraph to vertically scan the image, so the red and whites stripes in an Amerian flag would also get a hit as a bullseye. It would be easy to add a horizontal scan (a Find_Hbands paragraph) after the vertical to be more precise, but then an image of concentric red and whites squares would still be considered a hit. You'd have to delve into geometry and test points along the radius to truly confirm a circle. So attaining perfection seems a lot of work.

Anyway, the following is my really-rough first draft that does get a hit on the cleaned-up bullseye image attached to this post. I'm sure there are better ways to go about it, and lots of room for refinement. I just stuck an abrupt exit in it when it thinks it's found a bullseye. After 90 minutes, and realizing the headaches involved, I somewhat lost interest. The function is rather slow as well. I suppose there's API stuff out there that would help...

HotKeySet("{ESC}", "Abort")

Global $v, $h, $HCenter, $VCenter, $bands, $VBandCenter[10]
Global $white = 0xFFFFFF, $red = 0xFF0000
$xy = WinGetPos("Program Manager")
Global $Left=0
Global $Top=0
Global $Right=$xy[2] - 1
Global $Bottom=$xy[3] - 1
$v = $top -1

While 1
    $v += 2 
    If $v > $Bottom Then ExitLoop
    $h = $left - 1
    While 1
        $h += 2
        If $h > $Right Then ExitLoop
;       ToolTip($v & "  " & $h)
        If PixelGetShade($h, $v) = $white Then
            Find_HCenter()
        EndIf
    WEnd
WEnd

Func Find_HCenter()
    For $x = $h to $Right
        If PixelGetShade($x, $v) <> $white Or $x = $Right Then
            If $x - $h > 7 Then; minimum length of white line to review
                $HCenter = ($h + $x) / 2
                Find_VBands()
            EndIf
            $h = $x
            ExitLoop
        EndIf
    Next
EndFunc

Func Find_VBands()
    Local $band = 0, $bandcolor = $white, $bandstart = $v
    For $x = $v to $Bottom Step 2
        $y = PixelGetShade($HCenter, $x)
;       MouseMove($HCenter, $x, 0)
        Switch $y
            Case $white
                If $bandcolor = $red Then
                    $VBandCenter[$band] = ($bandstart + $x) / 2
                    $band += 1
                    $bandcolor = $white
                    $bandstart = $x
                Endif
            Case $red
                If $bandcolor = $white Then
                    $VBandCenter[$band] = ($bandstart + $x) / 2
                    $band += 1
                    $bandcolor = $red
                    $bandstart = $x
                Endif
            Case Else
                $VBandCenter[$band] = ($bandstart + $x) / 2
                Exitloop
        EndSwitch
    Next
    If $band = 6 Then; # of bands (white/red or red/white transitions) (0-based)
            MouseMove($HCenter, $VBandCenter[3],5)
            Beep(800,100)
            Sleep(200)
            Exit
    EndIf
EndFunc

;-------------------------------------------------------------------------------
Func PixelGetShade($xloc, $yloc)
    $color = Hex(PixelGetColor($xloc, $yloc))
    $Rcolor = StringMid($color, 3, 2)
    $Gcolor = StringMid($color, 5, 2)
    $BColor = StringMid($color, 7, 2)
    If $Rcolor > "F0" And $Gcolor > "F0" And $BColor > "F0" Then
        Return $white
    EndIf
    If $Rcolor > "F0" And $Gcolor < "DF" And $BColor < "DF" Then 
        Return $red
    EndIf
    Return $color   
EndFunc

Func Abort()
    Exit
EndFunc
Edited by Spiff59
Link to comment
Share on other sites

This is my code so far, I think if I get help with the counter, I'm almost done :)

;=========================================================
;Reinn's 'Shooting gallery' bot
;=========================================================
;Version 1.0
;=========================================================
;Made by:
;Reinn at www.Fleud.com
;Reinn at www.Autoitscript.com
;FleudReinn at www.Youtube.com
;=========================================================
;www.Fleud.com for updates
;=========================================================
;Credits to: Fleud.com, AutoItscript.com for making AutoIt
;=========================================================
;Extra credits to: MDiesel, More to come!
;=========================================================

#include <GUIConstants.au3>

HotKeySet('{F8}', 'Search')
HotKeySet('{ESC}', 'Stop')

$Form1 = GUICreate("Reinn's 'Shooting gallery' bot", 354, 179, 193, 125)
$Combo1 = GUICtrlCreateCombo("1280 * 1024", 112, 112, 121, 25)
GUICtrlSetData(-1, "1024 * 768")
$Label1 = GUICtrlCreateLabel("Resolution:", 144, 88, 57, 17)
$Edit1 = GUICtrlCreateEdit("", 16, 8, 321, 73)
GUICtrlSetData(-1, StringFormat("This bot was made by Reinn from www.Fleud.com\r\n\r\n1. Start your web browser, and go to the "&Chr(34)&"Shooting gallery"&Chr(34)&" url.\r\n2. Start a game.\r\n3. Hold down CTRL, SHIFT & press on "&Chr(34)&"S"&Chr(34)&".\r\n\r\nFleud.com nor Reinn are responsible for what this is used for - Educational purposes only."))
GUISetState(@SW_SHOW)

$Left=0
$Top=0
$Right=1000
$Bottom=800

While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch
WEnd

Dim $Count = 0

Func Search()
    $Search=PixelSearch ($Left,$Top,$Right,$Bottom,0xFF0000,5,2)
        If Not @error Then MouseClick ("Left",$Search[0],$Search[1],1,10)
        Sleep(20)
        $Count =+ 1
        MsgBox(1, "Test", $Count)
        ;The MsgBox comes up with 1 each time, help me to fix... (The MsgBox is only to see if it works - will delete when it works)
EndFunc
    
If $Count = 5 Then Reload()
    
Func Reload()
    If $Combo1 = "1024 * 768" Then
        MouseClick("Left",598,549,1)
    ElseIf $Combo1 = "1280 * 1024" Then
        MouseClick("left",754,716,1)
    EndIf
EndFunc

Func Stop()
    ;ShellExecute("http://www.Fleud.com")
    Exit
EndFunc
Link to comment
Share on other sites

As i've already said, you can get the resolution of your screen using macros, which will make it easier.

Also, how about loading the game first, using IE funcitons, just to be extra professional.

I think its a spiffing idea (see what I did there? :)) if you count the pixels of colour ... and then see if its a line, but make it speedy, and go up in 3's or 4's.

MDiesel

Link to comment
Share on other sites

As i've already said, you can get the resolution of your screen using macros, which will make it easier.

Also, how about loading the game first, using IE funcitons, just to be extra professional.

I think its a spiffing idea (see what I did there? :)) if you count the pixels of colour ... and then see if its a line, but make it speedy, and go up in 3's or 4's.

MDiesel

I have a headache and I can't concentrate much right now... But what are Macro(s) ? (Haven't worked with them) And the IE could be easy, I think I'll use ShellExecute, so it uses the standard browser :idea:

And what about the count thing... I still don't get how to fix it ... :party:

Link to comment
Share on other sites

Got bored (again) so messed with this some more. Made some speed improvements, some color range recognition improvements (it'll nail the original image in the post now), and added a horizontal scan for the bars/stripes/bands in the target in addition to the vertical scan already in my first play script.

HotKeySet("{ESC}", "Abend")

Global $v, $h, $HCenter, $VCenter, $band, $VBandCenter[10]
Global $white = 0xFFFFFF, $red = 0xFF0000, $found = 0
$xy = WinGetPos("Program Manager")
Global $Left=0
Global $Top=0
Global $Right=$xy[2] - 1
Global $Bottom=$xy[3] - 1
$v = $Top

$timer = TimerInit()
While 1
    $v += 2 
    $x = PixelSearch($Left,$v,$Right,$Bottom,$red,20,2)
    $v = $x[1]
    If $v > $Bottom Then ExitLoop
    $h = $Left - 2
    While 1
        $h += 2
        If $h > $Right Then ExitLoop
;       ToolTip($v & "  " & $h)
        If PixelGetShade($h, $v) = $red and PixelGetShade($h, $v - 2) = $white Then
            Find_HCenter()
            If $found Then ExitLoop(2)
        EndIf
    WEnd
WEnd
$timer = TimerDiff($timer)
MsgBox(1,"","Time: " & $timer/1000)

Func Find_HCenter()
    For $x = $h to $Right
        If PixelGetShade($x, $v) <> $red Or $x = $Right Then
            If $x - $h > 7 Then; minimum length of line to review
                $HCenter = ($h + $x) / 2
                Find_VBands()
            EndIf
            $h = $x
            ExitLoop
        EndIf
    Next
EndFunc

Func Find_VBands()
    Local $band = 1, $bandcolor = $red, $bandstart = $v
    $y = $v + 70; Attempt to increase speed by limiting to height of target
    If $y > $Bottom Then $y = $Bottom   
    For $x = $v to $y Step 2
        $y = PixelGetShade($HCenter, $x)
;       MouseMove($HCenter, $x, 0)
        Switch $y
            Case $white
                If $bandcolor = $red Then
                    $VBandCenter[$band] = ($bandstart + $x) / 2
                    $band += 1
                    $bandcolor = $white
                    $bandstart = $x
                Endif
            Case $red
                If $bandcolor = $white Then
                    $VBandCenter[$band] = ($bandstart + $x) / 2
                    $band += 1
                    $bandcolor = $red
                    $bandstart = $x
                Endif
            Case Else
                $VBandCenter[$band] = ($bandstart + $x) / 2
                Exitloop
        EndSwitch
    Next
    If $band = 6 Then; # of bands (white/red or red/white transitions, 0-based)
            Find_HBands()
    EndIf
EndFunc

Func Find_HBands()
    Local $band = 0, $bandcolor = $red
    $y = $HCenter + 35; limit to radius of target
    If $y > $Right Then $y = $Right 
    For $x = $HCenter to $y Step 2
        $y = PixelGetShade($x, $VBandCenter[3])
        Switch $y
            Case $white
                If $bandcolor = $red Then
                    $band += 1
                    $bandcolor = $white
                Endif
            Case $red
                If $bandcolor = $white Then
                    $band += 1
                    $bandcolor = $red
                Endif
            Case Else
                Exitloop
        EndSwitch
    Next
    If $band <> 3 Then Return; not 3 bands to right
    
    $band = 0
    $bandcolor = $red
    $y = $HCenter - 35; limit to radius of target
    If $y < $Left Then $y = $left
    For $x = $HCenter to $y Step -2
        $y = PixelGetShade($x, $VBandCenter[3])
        Switch $y
            Case $white
                If $bandcolor = $red Then
                    $band += 1
                    $bandcolor = $white
                Endif
            Case $red
                If $bandcolor = $white Then
                    $band += 1
                    $bandcolor = $red
                Endif
            Case Else
                Exitloop
        EndSwitch
    Next
    If $band = 3 Then; 3 bands to left
            MouseMove($HCenter, $VBandCenter[3],0)
            Beep(800,100)
            $found = 1
    EndIf
EndFunc

;-------------------------------------------------------------------------------
Func PixelGetShade($xloc, $yloc)
    $color = Hex(PixelGetColor($xloc, $yloc))
    $Rcolor = Dec(StringMid($color, 3, 2))
    $Gcolor = Dec(StringMid($color, 5, 2))
    $BColor = Dec(StringMid($color, 7, 2))
    If $Rcolor > 176 And $Gcolor > 176 And $BColor > 176 Then
        Return $white
    EndIf
    If $Rcolor - $Gcolor > 20 and $Rcolor - $Bcolor > 20 Then
        Return $red
    EndIf
    Return $color   
EndFunc

Func Abend()
    Exit
EndFunc
Edited by Spiff59
Link to comment
Share on other sites

This works for me on all three symbols... .. . but ofcourse I cheated and used a checksum :)

HotKeySet("`","_find")
HotKeySet("~","record")
HotKeySet('{esc}', '_Exit')

Global $msg =   "Press Shift+tilde to Record " & @LF & _
                "Press tilde to Find " & @LF & _
                "info saved in Pixel.ini" 
Global $xy,$currentpixel

While 1
    $xy = MouseGetPos()
    $currentpixel = PixelGetColor($xy[0],$xy[1])
    ToolTip("Pixel color = " & $currentpixel & @LF & $msg)
    Sleep(100)
WEnd

Func record()
    IniWrite(".\Pixel.ini","Main","PixelColor",$currentpixel)
    Local $chksum = PixelChecksum($xy[0]-4, $xy[1]-20, $xy[0]+4, $xy[1]+20)
    IniWrite(".\Pixel.ini","Main","PixelCheckSum",$chksum)
    ToolTip("SAVED")    
    Sleep(1000)
    ;Exit
EndFunc

Func _find()
    Local $pixel =  Int(IniRead(".\Pixel.ini","Main","PixelColor","-1"))
    Local $chksum = Int(IniRead(".\Pixel.ini","Main","PixelCheckSum","-1"))
    
    $x = 5 ;LEFT pixel of Total Area to Search for $pixel
    $y = 5 ;TOP 
    $xpixel = @DesktopWidth - 5 ;Right
    $ypixel = @DesktopHeight - 5 ;Bottom
    
    While 1
        $xy = PixelSearch($x,$y,$xpixel,$ypixel,$pixel, 0)

        If @error And $ypixel = (@DesktopHeight - 5)Then
            MsgBox(4096,"@Error ","Could not find Checksum" & @LF & '     Finished Searching all of Screen', 4)
            exit
        ElseIf @error Then
            $y = $ypixel + 1
            $ypixel = (@DesktopHeight - 5)
            $x = 0
        ElseIf $chksum = PixelCheckSum($xy[0]-4, $xy[1]-20, $xy[0]+4, $xy[1]+20) Then 
            ToolTip("Found Checksum")
            MouseMove($xy[0],$xy[1], 20)
            Sleep(1000)
            Exit
        Else
            $y = $xy[1]
            $ypixel = $y
            $x = $xy[0] + 1
        EndIf
    WEnd
EndFunc

Func _Exit()
    ToolTip('          '&@CRLF&'  EXITING  '&@CRLF&'          ')
    Sleep(500)
    Exit
EndFunc

There is always a butthead in the crowd, no matter how hard one tries to keep them out.......Volly

Link to comment
Share on other sites

I see that PixelCheckSum() does the trick and quickly. It does have it's drawbacks as well. You have to know the exact value of all your target pixels prior to the search. So if an image were rendered differently depending on it's location on the screen, or what colors it borders, or screen resolution, etc, you're not going to get a match. I suppose there's also a minute chance that an entirely different image pattern could generate the same checksum.

This other method, a rudimentary attempt at pattern-recognition has it's flaws too (especially my kludgy first attempt here at playing with pixels). I worked a pixelsearch into the routine and a cheesy test to detect a circle versus a square and it finds a bullseye now in about a 1/10th of a second if it's near the top of the screen, and .6 seconds if it's near the bottom. It tries to ignore the size of the target pattern, or shade variations, but it's imperfect. Bumping $pixel_increment to 4 brings the max scan time down to .4 seconds, but rules out finding smaller targets. Anyway, were this my project, I'd probably take what I've learned, then pitch out my beta routine, and rewrite the whole thing.

HotKeySet("{ESC}", "Abend")

Global $v, $h, $HCenter, $VCenter, $band, $Vbandstart[10], $VBandCenter[10]
Global $white = 0xFFFFFF, $red = 0xFF0000, $found = 0
$xy = WinGetPos("Program Manager")
Global $Left=0
Global $Top=0
Global $Right=$xy[2] - 1
Global $Bottom=$xy[3] - 1
$v = $Top
$Pixel_Increment = 3; frequency of pixels to scan

$timer = TimerInit()
While 1
    $v += $Pixel_Increment  
    $x = PixelSearch($Left,$v,$Right,$Bottom,$red,20,2)
    If @error Then ExitLoop
    $v = $x[1]
    If $v > $Bottom Then ExitLoop
    $h = $Left
    While 1
        $h += $Pixel_Increment
        If $h > $Right Then ExitLoop
;       ToolTip($v & "  " & $h)
        If PixelGetShade($h, $v) = $red and PixelGetShade($h, $v - 3) = $white Then
            Find_HCenter()
            If $found Then ExitLoop(2)
        EndIf
    WEnd
WEnd
$timer = TimerDiff($timer)
MsgBox(1,"","Time: " & $timer/1000)

Func Find_HCenter()
    For $x = $h to $Right
        If PixelGetShade($x, $v) <> $red Or $x = $Right Then
            If $x - $h > 7 Then; minimum length of line to review
                $HCenter = ($h + $x) / 2
                Find_VBands()
            EndIf
            $h = $x
            ExitLoop
        EndIf
    Next
EndFunc

Func Find_VBands()
    Local $band = 1, $bandcolor = $red
    $VbandStart[$band] = $v
    $y = $v + 70; Attempt to increase speed by limiting to height of target
    If $y > $Bottom Then $y = $Bottom   
    For $x = $v to $y Step $Pixel_Increment
        $y = PixelGetShade($HCenter, $x)
;       MouseMove($HCenter, $x, 0)
        Switch $y
            Case $white
                If $bandcolor = $red Then
                    $VBandCenter[$band] = ($VbandStart[$band] + $x) / 2
                    $band += 1
                    $VbandStart[$band] = $x
                    $bandcolor = $white
                Endif
            Case $red
                If $bandcolor = $white Then
                    $VBandCenter[$band] = ($VbandStart[$band] + $x) / 2
                    $band += 1
                    $VbandStart[$band] = $x
                    $bandcolor = $red
                Endif
            Case Else
                $VBandCenter[$band] = ($VbandStart[$band] + $x) / 2
                Exitloop
        EndSwitch
    Next
    If $band = 6 Then; # of bands (white/red or red/white transitions, 0-based)
            Find_HBands()
    EndIf
EndFunc

Func Find_HBands()
    Local $band = 0, $bandcolor = $red
    $y = $HCenter + 35; limit to radius of target
    If $y > $Right Then $y = $Right 
    For $x = $HCenter to $y Step 2
        $y = PixelGetShade($x, $VBandCenter[3])
        Switch $y
            Case $white
                If $bandcolor = $red Then
                    $band += 1
                    $bandcolor = $white
                Endif
            Case $red
                If $bandcolor = $white Then
                    $band += 1
                    $bandcolor = $red
                Endif
            Case Else
                Exitloop
        EndSwitch
    Next
    If $band <> 3 Then Return; not 3 bands to right
    
    $band = 0
    $bandcolor = $red
    $y = $HCenter - 35; limit to radius of target
    If $y < $Left Then $y = $left
    For $x = $HCenter to $y Step -2
        $y = PixelGetShade($x, $VBandCenter[3])
        Switch $y
            Case $white
                If $bandcolor = $red Then
                    $band += 1
                    $bandcolor = $white
                Endif
            Case $red
                If $bandcolor = $white Then
                    $band += 1
                    $bandcolor = $red
                Endif
            Case Else
                Exitloop
        EndSwitch
    Next
    If $band = 3 Then; 3 bands to left
        $x = $VBandCenter[3] - ($VBandStart[3] + 1)
        If PixelGetShade($HCenter + $x, $VBandStart[3]) = $white Then
            MouseMove($HCenter, $VBandCenter[3],0)
            Beep(800,100)
            $found = 1
        EndIf
   EndIf
EndFunc

;-------------------------------------------------------------------------------
Func PixelGetShade($xloc, $yloc)
    $color = Hex(PixelGetColor($xloc, $yloc))
    $Rcolor = Dec(StringMid($color, 3, 2))
    $Gcolor = Dec(StringMid($color, 5, 2))
    $BColor = Dec(StringMid($color, 7, 2))
    If $Rcolor > 176 And $Gcolor > 176 And $BColor > 176 Then
        Return $white
    EndIf
    If $Rcolor - $Gcolor > 20 and $Rcolor - $Bcolor > 20 Then
        Return $red
    EndIf
    Return $color   
EndFunc

Func Abend()
    Exit
EndFunc
Edited by Spiff59
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...