tom13 Posted May 24, 2009 Posted May 24, 2009 Hey there, I've found the following pixelchecksumsearch function: expandcollapse popup;=============================================================================== ; Function Name: _PixelCheckSumFindAll ; Description: Finds all instances of Checksum within a given area and returns array with Total and all locations X and Y. ; Parameters: $Pixel Colour value of pixel to find (in decimal or hex). ; $chksum Previously generated checksum value of the region per(PixelChecksum) ; $CS_l left coordinate of rectangle. (amount to subtract) ; $CS_t Top coordinate of rectangle. (amount to subtract) ; $CS_r Right coordinate of rectangle. (amount to add) ; $CS_b Bottom coordinate of rectangle. (amount to add) ; $SB_l left coordinate of total area to search. Default is 0 (far left side of screen) ; $SB_t top coordinate of total area to search. Default is 0 (top most Side of screen) ; $SB_r Right coordinate of total area to search. Default is @DesktopWidth (Far Right side of screen) ; $SB_b Bottom coordinate of total area to search. Default is @DesktopHeight (Bottom most side of screen) ; Syntax: _PixelCheckSumFindAll($pixel, $chksum, $CS_l, $CS_t, $CS_r, $CS_b[, $SB_l, $SB_t, $SB_r, $SB_b]) ; Author(s): ofLight ; Returns: $Array[0][0] = 0 on failure, $Array on success ;=============================================================================== Func _PixelCheckSumFindAll($pixel,$chksum,$CS_l,$CS_t,$CS_r,$CS_b,$SB_l=0,$SB_t=0,$SB_r=@DesktopWidth,$SB_b=@DesktopHeight) $SB_b_Max = $SB_b $SB_l_Max = $SB_l Dim $Array[2][2] $Array[0][0] = "0" $Count = "0" While 1 $xy = PixelSearch($SB_l,$SB_t,$SB_r,$SB_b,$pixel, 0) If @error And $SB_b = $SB_b_Max Then SetError(1) Return $Array ElseIf @error Then $SB_t = $SB_b + 1 $SB_b = $SB_b_Max $SB_l = $SB_l_Max ElseIf $chksum = PixelCheckSum($xy[0]-$CS_l, $xy[1]-$CS_t, $xy[0]+$CS_r, $xy[1]+$CS_B) Then $Count = $Count+1 $Array[0][0] = $Count ReDim $Array[$Count+1][2] $Array[$Count][0] = $xy[0] $Array[$Count][1] = $xy[1] $SB_t = $xy[1] $SB_b = $SB_t $SB_l = $xy[0] + 1 Else $SB_t = $xy[1] $SB_b = $SB_t $SB_l = $xy[0] + 1 EndIf WEnd EndFunc It works great. The only problem is that I need to add somekind of a shade variation. So that a slightly different checksum (eg. because of slight transparency) will still match. Anyone has any idea how to do this?
Valuater Posted May 24, 2009 Posted May 24, 2009 PixelSearch ( left, top, right, bottom, color [, shade-variation [, step [, hwnd]]] )8)
tom13 Posted May 24, 2009 Author Posted May 24, 2009 PixelSearch ( left, top, right, bottom, color [, shade-variation [, step [, hwnd]]] ) 8) Well, what about the pixelchecksum part? If the pixel is a bit different then the pixelchecksum is aswell.
Moderators SmOke_N Posted May 25, 2009 Moderators Posted May 25, 2009 No, you can't do PixelCheckSum with shade variation. Defeats the whole purpose of getting a "unique" checksum value for a region (X-Width by Y-Height). 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.
tom13 Posted May 25, 2009 Author Posted May 25, 2009 No, you can't do PixelCheckSum with shade variation. Defeats the whole purpose of getting a "unique" checksum value for a region (X-Width by Y-Height). Alright, well I tried to create a variant with pixelsearch. However, it doesn't seem to work. Do you see the flaw? expandcollapse popupFunc GetCornerSum($aTopLeft, $aBottomRight) Local $aCornerSum[4] $aCornerSum[0] = PixelGetColor($aTopLeft[0], $aTopLeft[1]) ;top left $aCornerSum[1] = PixelGetColor($aBottomRight[0], $aTopLeft[1]) ;top right $aCornerSum[2] = PixelGetColor($aTopLeft[0], $aBottomRight[1]) ;bottom left $aCornerSum[3] = PixelGetColor($aBottomRight[0], $aBottomRight[1]) ;bottom right Return $aCornerSum EndFunc Func FindCornerSum($aCornerSum, $iWidth, $iHeight, $aTopLeft, $aBottomRight, $iShade = 0) $cSearch = _PixelSearchEX($aTopLeft[0], $aTopLeft[1], $aBottomRight[0], $aBottomRight[1], $aCornerSum[0], $iShade) If Not IsArray($cSearch) Then Return 0 ;return 0 when the top left pixel can not be found at all For $i = 1 To UBound($cSearch, 2) - 1 ;check for each found pixel whether this is the square PixelSearch($cSearch[0][$i] + $iWidth, $cSearch[1][$i], $cSearch[0][$i] + $iWidth, $cSearch[1][$i], $aCornerSum[1], $iShade) ;top right If Not @error Then ;check other corners PixelSearch($cSearch[0][$i], $cSearch[1][$i] + $iHeight, $cSearch[0][$i], $cSearch[1][$i] + $iHeight, $aCornerSum[2], $iShade) ;bottom left If Not @error Then ;check other corners PixelSearch($cSearch[0][$i] + $iWidth, $cSearch[1][$i] + $iHeight, $cSearch[0][$i] + $iWidth, $cSearch[1][$i] + $iHeight, $aCornerSum[3], $iShade) ;bottom right If Not @error Then ;check other corners Local $aReturn[2] $aReturn[0] = $cSearch[0][$i] $aReturn[1] = $cSearch[1][$i] Return $aReturn EndIf EndIf EndIf Next Return 0 ;no match EndFunc Func _PixelSearchEX($iXStart, $iYStart, $iXEnd, $iYEnd, $vColor, $iShade = 0, $iStep = 1, $iSleep = 0) Local $iXCurrent = 0, $iYCurrent = 0 Local $iXElement, $iYElement While 1 $aSearch = PixelSearch(($iXStart + $iXCurrent), ($iYStart + $iYCurrent), $iXEnd, $iYEnd, $vColor, $iShade, $iStep) If Not IsArray($aSearch) Then ExitLoop If IsArray($aSearch) Then $iXElement &= $aSearch[0] & @LF $iYElement &= $iYStart + $iYCurrent & @LF If $iXStart + $iXCurrent >= $iXEnd Then $iXCurrent = 0 $iYCurrent += 1 Else $iXCurrent = ($aSearch[0] - $iXStart) + 1 EndIf Else If $iXStart + $iXCurrent >= $iXEnd Then $iXCurrent = 0 $iYCurrent += 1 Else $iXCurrent += 1 EndIf EndIf Sleep($iSleep) WEnd If $iXElement = '' Then Return SetError(1, 0, 0) $iXElement = StringSplit(StringTrimRight($iXElement, 1), @LF) $iYElement = StringSplit(StringTrimRight($iYElement, 1), @LF) Local $aElements[2][UBound($iXElement)] For $xCount = 1 To UBound($iXElement) - 1 $aElements[0][$xCount] = $iXElement[$xCount] $aElements[1][$xCount] = $iYElement[$xCount] Next Return $aElements EndFunc
Moderators SmOke_N Posted May 25, 2009 Moderators Posted May 25, 2009 (edited) Find the error? Don't have a clue what you're even doing (although I do recognize one of those funcs ). If you still trying to find a sum with variant shade colors, you're going to be sadly disappointed. Especially if any of the colors in a x by y region could be different shades. Just simply adding regions together is not going to give you the right return. Your best bet is to capture the area, do a monochrome or black white conversion, then go from there. I believe Manadar made something that may help you to get the values out of the image on disk after the conversion process. Edited May 25, 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.
tom13 Posted May 25, 2009 Author Posted May 25, 2009 Find the error? Don't have a clue what you're even doing (although I do recognize one of those funcs ).If you still trying to find a sum with variant shade colors, you're going to be sadly disappointed. Especially if any of the colors in a x by y region could be different shades. Just simply adding regions together is not going to give you the right return.Your best bet is to capture the area, do a monochrome or black white conversion, then go from there. I believe Manadar made something that may help you to get the values out of the image on disk after the conversion process.Eh, I'm just getting the 4 pixels from all corners of a square. Then search for the top left pixel with a shade variation and see if the other corners match this pixel with that shade variation.That should work. Just that something is wrong in my functions I think.. not sure what however.
Moderators SmOke_N Posted May 25, 2009 Moderators Posted May 25, 2009 Eh, I'm just getting the 4 pixels from all corners of a square. Then search for the top left pixel with a shade variation and see if the other corners match this pixel with that shade variation.That should work. Just that something is wrong in my functions I think.. not sure what however.Why do you say it should work?How many different values do you think you'd have if you allowed just 3 different shade variations (mind you, that's actually 6 because the shade variation could be 3 more or 3 less) + the original value? 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.
tom13 Posted May 25, 2009 Author Posted May 25, 2009 Why do you say it should work?How many different values do you think you'd have if you allowed just 3 different shade variations (mind you, that's actually 6 because the shade variation could be 3 more or 3 less) + the original value?Not that much I think. Because the top left pixel has to match first and the object color is a lot different than the background color.
Moderators SmOke_N Posted May 25, 2009 Moderators Posted May 25, 2009 See if this works for your needs:expandcollapse popup; Array of colors UBound must match number of pixels searching ; Array of variations UBound must match number of pixels searching Local $a_clr[4] = [0xFF0000, 0xFF00FF, 0x00FF00, 0x00FFFF] Local $a_vrn[4] = [1,2,4,2] _Pixel_Range_Validate(10, 38, 11, 39, $a_clr, $a_vrn) ; @error 0 = Succes ; @error 1 = UBound of colors was incorrect ; @error 2 = UBound of variations was incorrect ; @error 3 = Variation match failed ConsoleWrite("Error = " & @error & @CRLF) Func _Pixel_Range_Validate($i_x1, $i_y1, $i_x2, $i_y2, $a_colors, $a_variations, $h_wnd = 0) Local $i_x_loops = Abs($i_x2 - $i_x1) + 1 Local $i_y_loops = Abs($i_y2 - $i_y1) + 1 Local $i_total = $i_x_loops * $i_y_loops Local $a_col = $a_colors, $a_var = $a_variations If IsArray($a_colors) Then If (UBound($a_colors) <> $i_total) Then Return SetError(1, 0, 0); Array out of bounds Else Local $a_col[$i_total] For $i = 0 To ($i_total) - 1 $a_col[$i] = $a_colors Next EndIf If IsArray($a_variations) Then If (UBound($a_variations)) <> $i_total Then Return SetError(2, 0, 0); Array out of bounds Else Local $a_var[$i_total] For $i = 0 To ($i_total) - 1 $a_var[$i] = $a_variations Next EndIf Local $i_c = 0 For $y = $i_y1 To $i_y2 For $x = $i_x1 To $i_x2 PixelSearch($x, $y, $x, $y, $a_col[$i_c], $a_var[$i_c], 1, $h_wnd) If @error Then Return SetError(3, 0, 0) EndIf $i_c += 1 Next Next Return SetError(0, 0, 1) EndFunc 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.
tom13 Posted May 25, 2009 Author Posted May 25, 2009 Thanks Smoke but that function doesn't know where to search for the square, right? It needs to search for it in a given area. If that's what the first 4 parameters do, then how does it know how far corner B is from corner A, etc.?
Moderators SmOke_N Posted May 25, 2009 Moderators Posted May 25, 2009 (edited) Thanks Smoke but that function doesn't know where to search for the square, right? It needs to search for it in a given area. If that's what the first 4 parameters do, then how does it know how far corner B is from corner A, etc.?What are you on about lol?It simply checks a region you specify with shade variation, if that region doesn't have your variation of colors, it sets @error and returns zero. What you do to implement it to meet your logic is up to you.Edit:In other words, if you're checking four different regions (regions being the rectangular area you want to search), then you would call that function 4 times with the x start, y start, x end and y end positions, along with their prospective color and variation arrays. Edited May 25, 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.
Moderators SmOke_N Posted May 25, 2009 Moderators Posted May 25, 2009 (edited) Hmm, seems that PixelSearchEx() function is wrong, should be something like:Func _Pixel_SearchEx( _ $i_x_start, $i_y_start, _ $i_x_end, $i_y_end, _ $i_color, $i_shade = 0, _ $i_step = 1, $h_wnd = 0, $i_sleep = 0) Local $i_x_c, $i_y_c, $a_found, $i_c Local $a_ret[((Abs($i_x_end - $i_x_start) + 1) * (Abs($i_y_end - $i_y_start) + 1)) + 1][2] For $i_y_c = $i_y_start To $i_y_end Step $i_step $i_x_c = $i_x_start While 1 $a_found = PixelSearch($i_x_c, $i_y_c, $i_x_end, $i_y_c, $i_color, $i_shade, $i_step, $h_wnd) If @error Then ExitLoop $i_c += 1 $a_ret[$i_c][0] = $a_found[0] $a_ret[$i_c][1] = $a_found[1] If $a_found[0] + 1 > $i_x_end Then ExitLoop $i_x_c = $a_found[0] + 1 WEnd Next If $i_c = 0 Then Return SetError(1, 0, 0) ReDim $a_ret[$i_c + 1][2] $a_ret[0][0] = $i_c Return $a_ret EndFuncThe results from this seemed to be correct unlike the other version. Edit: Fixed something after testing it. 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.
Moderators SmOke_N Posted May 26, 2009 Moderators Posted May 26, 2009 (edited) Well, after playing the Memorial Day family game, and feeling like a stuffed pig. I thought I'd read through this thread once more to see if I can grasp what exactly you are trying to do.If I'm right, you're almost trying to do something that imagesearch.au3 does but without the dll. You have a set number of pixels you want to search, and a "possible" variation for each pixel (not sure if imagesearch does that).With that in mind, I kind of made my own imagesearch with pixel variation option.Things to know.You must send an array of colors, these colors will be left to right, up to down (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, 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).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 EndFuncSure hope this is close to what you were hoping to do.Edit:(Don't try and post an edit during maintenance time !!!! )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. 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.
tom13 Posted May 26, 2009 Author Posted May 26, 2009 Thanks a lot Smoke. I'm sure I and the whole AutoIt community will be able to use those functions very often. For this situation however, the fixed version of _Pixel_SearchEX did the job (and a bit of improvement of my own code). Here's what I got now and it works great! Basically, this checks if the 4 corners of a square match in a certain area with a given shade variation. expandcollapse popupFunc _FindCornerSum($aCornerSum, $aTopLeft, $aBottomRight, $iShade = 0) $cSearch = _Pixel_SearchEX($aTopLeft[0], $aTopLeft[1], $aBottomRight[0], $aBottomRight[1], $aCornerSum[0], $iShade) If @error Then Return 0 ;return 0 when the top left pixel can not be found at all For $i = 1 To $cSearch[0][0] ;check for each found pixel whether this is the top left pixel of the square PixelSearch($cSearch[$i][0] + $aCornerSum[4], $cSearch[$i][1], $cSearch[$i][0] + $aCornerSum[4], $cSearch[$i][1], $aCornerSum[1], $iShade) ;top right If Not @error Then ;if this is a match, check bottom left corner PixelSearch($cSearch[$i][0], $cSearch[$i][1] + $aCornerSum[5], $cSearch[$i][0], $cSearch[$i][1] + $aCornerSum[5], $aCornerSum[2], $iShade) ;bottom left If Not @error Then ;if this is a match, check bottom right corner PixelSearch($cSearch[$i][0] + $aCornerSum[4], $cSearch[$i][1] + $aCornerSum[5], $cSearch[$i][0] + $aCornerSum[4], $cSearch[$i][1] + $aCornerSum[5], $aCornerSum[3], $iShade) ;bottom right If Not @error Then ;if this is a match, return the x and y of the square Local $aReturn[2] $aReturn[0] = $cSearch[$i][0] $aReturn[1] = $cSearch[$i][1] Return $aReturn EndIf EndIf EndIf Next Return 0 ;no match EndFunc Func _Pixel_SearchEx($i_x_start, $i_y_start, $i_x_end, $i_y_end, $i_color, $i_shade = 0, $i_step = 1, $h_wnd = 0, $i_sleep = 0) Local $i_x_c, $i_y_c, $a_found, $i_c Local $a_ret[((Abs($i_x_end - $i_x_start) + 1) * (Abs($i_y_end - $i_y_start) + 1)) + 1][2] For $i_y_c = $i_y_start To $i_y_end Step $i_step $i_x_c = $i_x_start While 1 $a_found = PixelSearch($i_x_c, $i_y_c, $i_x_end, $i_y_c, $i_color, $i_shade, $i_step, $h_wnd) If @error Then ExitLoop $i_c += 1 $a_ret[$i_c][0] = $a_found[0] $a_ret[$i_c][1] = $a_found[1] If $a_found[0] + 1 > $i_x_end Then ExitLoop $i_x_c = $a_found[0] + 1 WEnd Next If $i_c = 0 Then Return SetError(1, 0, 0) ReDim $a_ret[$i_c + 1][2] $a_ret[0][0] = $i_c Return $a_ret EndFunc Func _GetCornerSum($aTopLeft, $aBottomRight) Local $aCornerSum[6] $aCornerSum[0] = PixelGetColor($aTopLeft[0], $aTopLeft[1]) ;top left $aCornerSum[1] = PixelGetColor($aBottomRight[0], $aTopLeft[1]) ;top right $aCornerSum[2] = PixelGetColor($aTopLeft[0], $aBottomRight[1]) ;bottom left $aCornerSum[3] = PixelGetColor($aBottomRight[0], $aBottomRight[1]) ;bottom right $aCornerSum[4] = $aBottomRight[0] - $aTopLeft[0] ;width $aCornerSum[5] = $aBottomRight[1] - $aTopLeft[1] ;height Return $aCornerSum EndFunc
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