Moderators SmOke_N Posted May 26, 2009 Moderators Share Posted May 26, 2009 (edited) On a topic here: http://www.autoitscript.com/forum/index.php?showtopic=95554I was trying to understand what the OP was trying to do, I think I may have still missed the boat with him, but this function came out of it (so most of this is a simple copy and paste).Things to know.You must send an array of colors, these colors will be left to right, top to bottom (and must be the same ubound as the width*height). So if I have a 2 pixel width, and a 2 pixel height area I want to search, and for this example, my starting point is 0 for both x and y. My color array is [0xFF0000, 0x00FF00, 0x0000FF, 0x00FFFF] x-0, y-0 = 0xFF0000 x-1, y-0 = 0x00FF00 x-0, y-1 = 0x0000FF x-1, y-1 = 0x00FFFF In that example you see how you would set your array up (zero based array).Shade variation must also be an array. The ubound must be the same as the ubound of the color array (width of pixel search * height of pixel search). You can do different shade variations for each pixel. My example will just show a constant variation of 3 for simplicity.The parameters: x-start = the x starting position of the total search area y-start = the y starting position of the total search area x-end = the x ending position of the total search area y-end = the y ending position of the total search area width = total number of pixels to search (left to right) once first pixel color is found height = total number of pixels to search (top to bottom) once the first pixel color is found colors = array of colors to search in specific order (explained above) one the match is found [0] is used for the first search pattern shade = array of shade variations for each position found [0] is used for the first search pattern step = number of steps to make like pixelsearch main function, this is only used in the main search for patterns, once a match on the first color is found, the rest of the search is step 1 hwnd = handle to window if you want to use one quick match = If you only want the first match, set to true, and the array [n][n] will hold your values, otherwise default is to return all matches The return is a two dimensional array: [0][0] = total number of matches found [n][0] = x starting position the match was found [n][1] = y starting position the match was found Errors: 1 = the color variable sent was either not an array or the ubound did not match the total value of the width*height 2 = the shade variable sent was either not an array or the ubound did not match the total value of the width*height 3 = No match foundGuess I could have written a header, just didn't feel like it.expandcollapse popup; Example #include <array.au3> ; Array of colors UBound must match number of pixels searching Local $a_clr[9] = [0xFF4AA5, 0xFF4AA5, 0xFF4AA5, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFF4AA5, 0xFF4AA5] ; Array of variations UBound must match number of pixels searching Local $a_vrn[9] = [3,3,3,3,3,3,3,3,3] Local $a_found = _Pixel_Region_FindMatch(0, 0, 1678, 945, 3, 3, $a_clr, $a_vrn) If @error Then MsgBox(0, "Error", "Error was: " & @error) Else _ArrayDisplay($a_found) EndIf Func _Pixel_Region_FindMatch($i_x, $i_y, $i_x_end, $i_y_end, $i_width, $i_height, $a_colors, $a_shade, $i_step = 1, $h_wnd = 0, $f_quick_match = False) Local $i_total = $i_width * $i_height Local $a_col = $a_colors, $a_var = $a_shade $i_width -= 1 $i_height -= 1 If (IsArray($a_colors) = 0) Or (UBound($a_colors) <> $i_total) Then Return SetError(1, 0, 0) If (IsArray($a_shade) = 0) Or (UBound($a_shade) <> $i_total) Then Return SetError(2, 0, 0) Local $i_c, $i_c_n, $i_x_c, $i_y_c Local $a_found, $i_y_n, $i_x_n, $i_c_n, $i_match Local $a_ret[((Abs($i_x_end - $i_x) + 1) * (Abs($i_y_end - $i_y) + 1)) + 1][2] ; Simple search For $i_y_c = $i_y To $i_y_end Step $i_step $i_x_c = $i_x While 1 $a_found = PixelSearch($i_x_c, $i_y_c, $i_x_end, $i_y_c, $a_colors[0], $a_shade[0], $i_step, $h_wnd) If @error Then ExitLoop If ($a_found[0] + $i_width > $i_x_end) Then ExitLoop If ($a_found[1] + $i_height > $i_y_end) Then ExitLoop $i_match = 0 For $i_y_n = $a_found[1] To $i_height + $a_found[1] For $i_x_n = $a_found[0] To $i_width + $a_found[0] PixelSearch($i_x_n, $i_y_n, $i_x_n, $i_y_n, $a_colors[$i_match], $a_shade[$i_match], 1, $h_wnd) If @error Then ExitLoop 2 $i_match += 1 If $i_match = $i_total Then $i_c += 1 $a_ret[$i_c][0] = $a_found[0] $a_ret[$i_c][1] = $a_found[1] If $f_quick_match Then ExitLoop 4 EndIf Next Next $i_x_c = $a_found[0] + 1 WEnd Next If $i_c = 0 Then Return SetError(3, 0, 0) ReDim $a_ret[$i_c + 1][2] $a_ret[0][0] = $i_c Return $a_ret EndFuncThe example above found all the "@" symbols in scite for me (obviously the unique search was only for that symbol).I expected this to be to slow to use.I was pleasantly dissapointed there!Searching a 1678x945 area, the example provided found 7 "@" symbols in scite in 250 ms, 10 in 350 ms. Should give you ideas on how fast/slow it is.Also, this is a simple helper function if you want to use it, will get all the pixel colors and positions in a 2D-3 index array (Used it to help with the color array).; Should only be used for small regions, didn't feel like writing out bitblt method Func _Pixel_GetRegion($i_x_start, $i_y_start, $i_x_end, $i_y_end, $i_step = 1, $h_wnd = 0) Local $a_ret[((Abs($i_x_end - $i_x_start) + 1) * (Abs($i_y_end - $i_y_start) + 1)) + 1][3], $i_c = 0 For $i_y = $i_y_start To $i_y_end Step $i_step For $i_x = $i_x_start To $i_x_end Step $i_step $i_c += 1 $a_ret[$i_c][0] = $i_x $a_ret[$i_c][1] = $i_y $a_ret[$i_c][2] = PixelGetColor($i_x, $i_y, $h_wnd) Next Next ReDim $a_ret[$i_c + 1][3] $a_ret[0][0] = $i_c Return $a_ret EndFunc Edited May 26, 2009 by SmOke_N Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer. Link to comment Share on other sites More sharing options...
exolon Posted October 12, 2009 Share Posted October 12, 2009 On a topic here: http://www.autoitscript.com/forum/index.php?showtopic=95554 I was trying to understand what the OP was trying to do, I think I may have still missed the boat with him, but this function came out of it (so most of this is a simple copy and paste). Things to know. [*]You must send an array of colors, these colors will be left to right, top to bottom (and must be the same ubound as the width*height). So if I have a 2 pixel width, and a 2 pixel height area I want to search, and for this example, my starting point is 0 for both x and y.Smoke, This is pretty good - I tested this as a replacement for a version I wrote that does basically the same thing, and yours seems faster, although I'm not sure that it correctly handles cases where there are false matches earlier on the same horizontal line? In any case, there's one major problem with searching like this: if you're searching for a moving object, e.g. a sprite, the search can easily fail if the object was moving up the screen. i.e. at time t, the pixel pattern is on line 201. You search line 200 and find no match. At time t+k, the pixel pattern has moved up to line 200. You search 201 (and onwards) and find no match. Search ends having missed the object. It's basically a concurrency problem... so I guess the solution to this is to save a snapshot of the search area to a buffer and search that, so that searching is atomic. Any tips on how to do this gracefully and still be able to use the nice API like PixelSearch and PixelChecksum? Maybe you could draw a snapshot of the region to another window somewhere (perhaps even outside visible screen bounds) and search that normally, but it's a bit smelly. Link to comment Share on other sites More sharing options...
JRowe Posted October 12, 2009 Share Posted October 12, 2009 _ScreenCapture_Capture gets a region of the screen, using Manadar's pixel from memory UDF you could search it, combine Smoke_N's technique with those two, and you've neatly bypassed the concurrency issue. Performance will depend on how you put it together, but I don't see any problems. I'll take a whack at putting it together.Very cool, Smoke! [center]However, like ninjas, cyber warriors operate in silence.AutoIt Chat Engine (+Chatbot) , Link Grammar for AutoIt , Simple Speech RecognitionArtificial Neural Networks UDF , Bayesian Networks UDF , Pattern Matching UDFTransparent PNG GUI Elements , Au3Irrlicht 2Advanced Mouse Events MonitorGrammar Database GeneratorTransitions & Tweening UDFPoker Hand Evaluator[/center] Link to comment Share on other sites More sharing options...
sahunhong Posted November 27, 2009 Share Posted November 27, 2009 On a topic here: http://www.autoitscript.com/forum/index.php?showtopic=95554I was trying to understand what the OP was trying to do, I think I may have still missed the boat with him, but this function came out of it (so most of this is a simple copy and paste).Things to know.You must send an array of colors, these colors will be left to right, top to bottom (and must be the same ubound as the width*height).So if I have a 2 pixel width, and a 2 pixel height area I want to search, and for this example, my starting point is 0 for both x and y.My color array is [0xFF0000, 0x00FF00, 0x0000FF, 0x00FFFF]x-0, y-0 = 0xFF0000x-1, y-0 = 0x00FF00x-0, y-1 = 0x0000FFx-1, y-1 = 0x00FFFFIn that example you see how you would set your array up (zero based array).Shade variation must also be an array. The ubound must be the same as the ubound of the color array (width of pixel search * height of pixel search).You can do different shade variations for each pixel. My example will just show a constant variation of 3 for simplicity.The parameters:x-start = the x starting position of the total search areay-start = the y starting position of the total search areax-end = the x ending position of the total search areay-end = the y ending position of the total search areawidth = total number of pixels to search (left to right) once first pixel color is foundheight = total number of pixels to search (top to bottom) once the first pixel color is foundcolors = array of colors to search in specific order (explained above) one the match is found [0] is used for the first search patternshade = array of shade variations for each position found [0] is used for the first search patternstep = number of steps to make like pixelsearch main function, this is only used in the main search for patterns, once a match on the first color is found, the rest of the search is step 1hwnd = handle to window if you want to use onequick match = If you only want the first match, set to true, and the array [n][n] will hold your values, otherwise default is to return all matchesThe return is a two dimensional array:[0][0] = total number of matches found[n][0] = x starting position the match was found[n][1] = y starting position the match was foundErrors:1 = the color variable sent was either not an array or the ubound did not match the total value of the width*height2 = the shade variable sent was either not an array or the ubound did not match the total value of the width*height3 = No match foundGuess I could have written a header, just didn't feel like it.expandcollapse popup; Example #include <array.au3> ; Array of colors UBound must match number of pixels searching Local $a_clr[9] = [0xFF4AA5, 0xFF4AA5, 0xFF4AA5, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFF4AA5, 0xFF4AA5] ; Array of variations UBound must match number of pixels searching Local $a_vrn[9] = [3,3,3,3,3,3,3,3,3] Local $a_found = _Pixel_Region_FindMatch(0, 0, 1678, 945, 3, 3, $a_clr, $a_vrn) If @error Then MsgBox(0, "Error", "Error was: " & @error) Else _ArrayDisplay($a_found) EndIf Func _Pixel_Region_FindMatch($i_x, $i_y, $i_x_end, $i_y_end, $i_width, $i_height, $a_colors, $a_shade, $i_step = 1, $h_wnd = 0, $f_quick_match = False) Local $i_total = $i_width * $i_height Local $a_col = $a_colors, $a_var = $a_shade $i_width -= 1 $i_height -= 1 If (IsArray($a_colors) = 0) Or (UBound($a_colors) <> $i_total) Then Return SetError(1, 0, 0) If (IsArray($a_shade) = 0) Or (UBound($a_shade) <> $i_total) Then Return SetError(2, 0, 0) Local $i_c, $i_c_n, $i_x_c, $i_y_c Local $a_found, $i_y_n, $i_x_n, $i_c_n, $i_match Local $a_ret[((Abs($i_x_end - $i_x) + 1) * (Abs($i_y_end - $i_y) + 1)) + 1][2] ; Simple search For $i_y_c = $i_y To $i_y_end Step $i_step $i_x_c = $i_x While 1 $a_found = PixelSearch($i_x_c, $i_y_c, $i_x_end, $i_y_c, $a_colors[0], $a_shade[0], $i_step, $h_wnd) If @error Then ExitLoop If ($a_found[0] + $i_width > $i_x_end) Then ExitLoop If ($a_found[1] + $i_height > $i_y_end) Then ExitLoop $i_match = 0 For $i_y_n = $a_found[1] To $i_height + $a_found[1] For $i_x_n = $a_found[0] To $i_width + $a_found[0] PixelSearch($i_x_n, $i_y_n, $i_x_n, $i_y_n, $a_colors[$i_match], $a_shade[$i_match], 1, $h_wnd) If @error Then ExitLoop 2 $i_match += 1 If $i_match = $i_total Then $i_c += 1 $a_ret[$i_c][0] = $a_found[0] $a_ret[$i_c][1] = $a_found[1] If $f_quick_match Then ExitLoop 4 EndIf Next Next $i_x_c = $a_found[0] + 1 WEnd Next If $i_c = 0 Then Return SetError(3, 0, 0) ReDim $a_ret[$i_c + 1][2] $a_ret[0][0] = $i_c Return $a_ret EndFuncThe example above found all the "@" symbols in scite for me (obviously the unique search was only for that symbol).I expected this to be to slow to use.I was pleasantly dissapointed there!Searching a 1678x945 area, the example provided found 7 "@" symbols in scite in 250 ms, 10 in 350 ms. Should give you ideas on how fast/slow it is.Also, this is a simple helper function if you want to use it, will get all the pixel colors and positions in a 2D-3 index array (Used it to help with the color array).; Should only be used for small regions, didn't feel like writing out bitblt method Func _Pixel_GetRegion($i_x_start, $i_y_start, $i_x_end, $i_y_end, $i_step = 1, $h_wnd = 0) Local $a_ret[((Abs($i_x_end - $i_x_start) + 1) * (Abs($i_y_end - $i_y_start) + 1)) + 1][3], $i_c = 0 For $i_y = $i_y_start To $i_y_end Step $i_step For $i_x = $i_x_start To $i_x_end Step $i_step $i_c += 1 $a_ret[$i_c][0] = $i_x $a_ret[$i_c][1] = $i_y $a_ret[$i_c][2] = PixelGetColor($i_x, $i_y, $h_wnd) Next Next ReDim $a_ret[$i_c + 1][3] $a_ret[0][0] = $i_c Return $a_ret EndFuncNoob question:How would you get the actual coords in a variable, like the PixelSearch function?Thanks in advance. Link to comment Share on other sites More sharing options...
Sobiech Posted January 24, 2010 Share Posted January 24, 2010 Hmm how i can use this to click on one of these pixels?Need code example This world is crazy Link to comment Share on other sites More sharing options...
hot202 Posted January 25, 2010 Share Posted January 25, 2010 how come when i run this script i get a msgbox with Error was:3 Link to comment Share on other sites More sharing options...
Sobiech Posted January 25, 2010 Share Posted January 25, 2010 how come when i run this script i get a msgbox with Error was:3Errors:1 = the color variable sent was either not an array or the ubound did not match the total value of the width*height2 = the shade variable sent was either not an array or the ubound did not match the total value of the width*height3 = No match found This world is crazy Link to comment Share on other sites More sharing options...
hot202 Posted January 26, 2010 Share Posted January 26, 2010 well why didnt it find any thing? Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now