Jump to content

kakemoms

Members
  • Posts

    2
  • Joined

  • Last visited

Recent Profile Visitors

37 profile views

kakemoms's Achievements

Seeker

Seeker (1/7)

0

Reputation

  1. Ok. I made a color version for the icon search. I also added a icon reader and a function to dump it to the screen. It works quite well compared to the Black&White one: Func FindIconCol($x,$y,$wcol1,$wcol2,$digarr) ; Searches full screen for Color icon: FindIconCol(xsize,ysize,mincolor,maxcolor,digital array) Local $pz=0 For $a=0 To $x-1 For $b=0 To $y-1 $pz=$pz+$digarr[$a][$b] ;Sum up number of white pixels to search for Next Next Local $v1 Local $v2 Local $v3 Local $vam Local $vax Local $van Local $found=0 Local $siz=$x Local $sym=Abs($x-$y) ;symmetry is 0 if xsize and ysize equal Local $iconpos[2] If $y>$x Then $siz=$y $ResIcon = FFSnapShot() ;Full screen snapshot FFResetExcludedAreas() FFResetColors() $w = Hex($wcol1,6); $w1 = Dec(StringMid($w,1,2)) ;Red $w2 = Dec(StringMid($w,3,2)) ;Green $w3 = Dec(StringMid($w,5,2)) $u = Hex($wcol2,6); $u1 = Dec(StringMid($u,1,2)) ;Red $u2 = Dec(StringMid($u,3,2)) ;Green $u3 = Dec(StringMid($u,5,2)) $t1=Abs($w1-$u1) $t2=Abs($w2-$u2) $t3=Abs($w3-$u3) ; Find max variation: If $t1>=$t2 And $t1>=$t3 Then $vax=$t1/2 $vam=$t2/2 If $t2>$t3 Then $vam=$t3/2 ElseIf $t2>=$t3 Then $vax=$t2/2 $vam=$t1/2 Else $vax=$t3/2 $vam=$t1/2 EndIf ; So we have a vam value that is the minumum variation if the threshold is put at $w+$vam ; and a vax value that is the maximum variation if the threshold is put at $w+$vax ; "worst" case is that vam is 0 (one of the colors is $ff) and vax is 128 (one color is $00) ; The number of colors to be added to the filter is vax*2/16 which can be up to 16: ; Each step is minimum 16 with 8 variation (+/-8) $van=Ceiling(($vax*2/16)) ; Number of steps For $a=0 To ($van-1) ;Round($a*$vax/$van,0) ; Step Threshold based on $van $v1=Ceiling(($a+0.5)*$t1/$van) ; Step Threshold based on $van steps. Since variation will be +/-0.5 around a certain color step ;$w1=0 -> $vax=127 -> $van=16 ;$v1=0.5*255/16=8, $v1=1.5*255/16=24, ..., $v1=15.5*255/16=247 ;$v1+w1=8,24,...,247 $v2=Ceiling(($a+0.5)*$t2/$van) ;$w2=127 ;$v2=0.5*128/16=4, $v2=1.5*255/16=12, ... $v3=Ceiling(($a+0.5)*$t3/$van) ;$w2=254 ;$v2=0.5*1/16=0, $v1=1.5*1/16=0, ..., $v1=15.5*1/16=1 Local $string=(Hex(($v1+$w1),2)&Hex(($v2+$w2),2)&Hex(($v3+$w3),2)) ; Assumes that w1,w2,w3 are the lowest values (check for this later) ;ConsoleWrite($string & @CRLF) ; FFAddColor(Dec($string)) Next $var=Ceiling($vax/$van)*3 ;Variation for all the colors (3 colors) ;ConsoleWrite($var & @CRLF) ; ;FFAddColor(0xFFFFFF) ;FFAddColor($white) ;$w=Round(($w1+$w2+$w3)/3,0) FFAddExcludedArea(0,0,1920,200) ; Dont search menu lines FFAddExcludedArea(0,1020,1920,1080) ; Dont search window border FFAddExcludedArea(0,200,20,1020) ; Dont search window border FFAddExcludedArea(1895,200,1920,1020) ; Dont search browser border ;FFAddExcludedArea(20,350,900,1020) ; Dont search left side of screen Local $match=0 do ; Find a spot that contains $z pixels within $x * $y size $ResIcon = FFBestSpot($siz, $pz-5, $pz, 00, 400, -1 , $var, false) ;$ResIcon = FFNearestSpot($siz, $pz, 1920, 400, -1 , $var, false) if (IsArray($ResIcon)) Then ; potential match found $maxmatch=0 for $c=0 to ($x/2) ; Has to move pattern test around if it is not symmetric to get "perfect" match for $d=0 to ($y/2) $match=0 For $a=0 To $x-1 For $b=0 To $y-1 $z = Hex(FFGetPixel($ResIcon[0]+$a-($x/2)+$c,$ResIcon[1]+$b-($y/2)+$d),6); $z1 = Dec(StringMid($z,1,2)) ;Red $z2 = Dec(StringMid($z,3,2)) ;Green $z3 = Dec(StringMid($z,5,2)) ;$z=Round(($z1+$z2+$z3)/3,0) If ($z1>=($w1)) And ($z2>=($w2)) And ($z3>=($w3)) Then If $digarr[$b][$a]=1 Then $match+=1 ;Sum up number of matching white pixels Else ; Fail, so quit (only perfect match allowed) ;$a=$x-1 ;$b=$y-1 EndIf Else If $digarr[$b][$a]=0 Then $match+=1 ;Sum up number of matching white pixels Else ; Fail, so quit (only perfect match allowed) ;$a=$x-1 ;$b=$y-1 EndIf EndIf Next Next If $match>$maxmatch Or ($c=0 And $d=0) Then $maxmatch=$match $iconpos[0]=$ResIcon[0]-($x/2)+$c $iconpos[1]=$ResIcon[1]-($y/2)+$d EndIf next next ;drawCircle($iconpos[0]*1920/1280,$iconpos[1]*1080/720) IF $maxmatch=($x*$y) Then local $sMsg = "Found at x="&$iconpos[0]&",y="&$iconpos[1]&":match="&$maxmatch&",t="&($w-(3*$var)) FFTrace(" ** "&$sMsg&@lf&"") TrayTip("Found", $sMsg, 2000) $found=1 drawCircle($iconpos[0]*1920/1280,$iconpos[1]*1080/720) sleep(1000) Else ;local $sMsg = "Not at x="&$iconpos[0]&",y="&$iconpos[1]&":match="&$maxmatch&",t="&($w-(3*$var)) ;FFTrace(" ** "&$sMsg&@lf&"") ;TrayTip("Potential", $sMsg, 2000) ;drawCircle($iconpos[0]*1920/1280,$iconpos[1]*1080/720) ;FFSetPixel($x, $y, $Color, $NoSnapShot=$FFLastSnap) For $a=0 To $x-1 For $b=0 To $y-1 FFSetPixel($iconpos[0]+$a,$iconpos[1]+$b, 0) ; Instead of excluding, draw black across false spot; speeds up consecutive searches Next Next ;FFAddExcludedArea($iconpos[0]+1,$iconpos[1]+1,$iconpos[0]+$x,$iconpos[1]+$y) ; Remove this pattern from search as it didnt match ;sleep(1000) EndIf EndIf until ((Not IsArray($ResIcon)) OR $found=1) If ((Not IsArray($ResIcon)) AND $found<>1) Then ;Sleep(1000) local $sMsg = "No match found!" FFTrace(" ** "&$sMsg&@lf&"") TrayTip("No icon match", $sMsg, 2000) EndIf EndFunc For reading an icon & printing it to the console (as AutoIT code): Func ReadIconCol($x,$y,$white) ; Read a 16x16 area with "white" as threshold and put it into $digarr. $ResIcon = FFSnapShot() ;Full screen snapshot FFResetExcludedAreas() FFResetColors() $w = Hex($white,6); $w1 = Dec(StringMid($w,1,2)) ;Red $w2 = Dec(StringMid($w,3,2)) ;Green $w3 = Dec(StringMid($w,5,2)) $w=Round(($w1+$w2+$w3)/3,0) Local $pz=0 Local $mean=0 Local $varmax=0 Local $var=0 For $a=0 To 15 For $b=0 To 15 $z = Hex(FFGetPixel($x+$b,$y+$a),6); $z1 = Dec(StringMid($z,1,2)) ;Red $z2 = Dec(StringMid($z,3,2)) ;Green $z3 = Dec(StringMid($z,5,2)) ;Blue $z=Round(($z1+$z2+$z3)/3,0) If ($z1>=$w1) And ($z2>=$w2) And ($z3>=$w3) Then $digarr[$b][$a]=1 $pz+=1 $var=$var+$z If $z1>$varmax Then $varmax=$z1 If $z2>$varmax Then $varmax=$z2 If $z3>$varmax Then $varmax=$z3 Else $digarr[$b][$a]=0 EndIf Next Next $mean=$var/$pz ; mean "white" color if ($mean-$w)>($varmax-$mean) Then $var=$mean-$w Else $var=$varmax-$mean EndIf Return $digarr EndFunc Func PrintIcon($digarr) Local $sString = "[" For $a=0 To 15 $sString = $sString &"[" For $b=0 To 15 If $digarr[$b][$a]=1 Then $sString = $sString & "1" Else $sString = $sString & "0" EndIf If $b<>15 Then $sString = $sString & "," Else $sString = $sString & "]" EndIf Next If $a=15 Then $sString = $sString & "]" Else $sString = $sString & ", _" EndIf ConsoleWrite($sString & @CRLF) ; $sString = "" Next EndFunc Enjoy!
  2. Hi! Great library! I am trying to do some pattern recognition and while your library doesn't provide that part I am using it as a fast first-step filter to find useable sites for the pattern. For example, I have a cross that looks like this: 00011000 00011000 00011000 11111111 11111111 00011000 00011000 00011000 My program adds the number of positive bits (e.g. "1") and finds that the 8x8 pixel pattern contains 28 white pixels. My routine then do a FFNearestSpot for a 8x8 area with 28 white pixels. Your function finds a match and my routine will compare the found 8x8 area to this pattern and generate a matching value based on the number of bits that match. It will then exclude this 8x8 bit area from the search using FFAddExcludedArea and repeat the search until no more 8x8 areas with 28 white pixels can be found. The area that has the best matching value will then "win" and is reported as the closest match to the pattern recognition. This works quite well if the searched area is not too big. If it comes over a certain size with too many "matches" to the FFNearestSpot, it stops working. E.g. it does not report the same area over and over again as I exclude them with FFAddExcludedArea, but is simply does not find all the spots with 8x8 areas that have 28 pixels in them. Is this a problem with FFAddExcludedArea or is there something else that doesn't work? (see below for update) Here is the routine I use: Func FindIconBW($x,$y,$var,$white,$digarr) ; Searches full screen for BW icon: FindIconBW(xsize,ysize,shadevariation,whitecolor,digital array) Local $z=0 For $a=0 To $x-1 For $b=0 To $y-1 $z=$z+$digarr[$a][$b] ;Sum up number of white pixels to search for Next Next Local $found=0 Local $siz=$x Local $sym=Abs($x-$y) ;symmetry is 0 if xsize and ysize equal Local $iconpos[2] If $y>$x Then $siz=$y $ResIcon = FFSnapShot() ;Full screen snapshot FFResetExcludedAreas() FFAddColor(0xFFFFFF) FFAddColor($white) $w = Hex($white,6); $w1 = Dec(StringMid($w,1,2)) ;Red $w2 = Dec(StringMid($w,3,2)) ;Green $w3 = Dec(StringMid($w,5,2)) $w=Round(($w1+$w2+$w3)/3,0) FFAddExcludedArea(0,0,1920,350) ; Dont search menu lines FFAddExcludedArea(0,1020,1920,1080) ; Dont search window border FFAddExcludedArea(0,350,20,1020) ; Dont search window border FFAddExcludedArea(1890,350,1920,1020) ; Dont search browser border ;FFAddExcludedArea(20,350,1600,1020) ; Dont search left side of screen Local $match=0 do ; Find a spot that contains $z pixels within $x * $y size $ResIcon = FFBestSpot($siz, $z-1, $z, 0, 0, -1 , $var, false, 0, 0, 0, 0) ;$ResIcon = FFNearestSpot($siz, $z, 0, 0, -1 , $var, false) if (IsArray($ResIcon)) Then ; potential match found $maxmatch=0 for $c=0 to $sym*3 ; Has to move pattern test around if it is not symmetric to get "perfect" match for $d=0 to $sym*3 $match=0 For $a=0 To $x-1 For $b=0 To $y-1 $z = Hex(FFGetPixel($ResIcon[0]+$a-($x/2)+$c,$ResIcon[1]+$b-($y/2)+$d),6); $z1 = Dec(StringMid($z,1,2)) ;Red $z2 = Dec(StringMid($z,3,2)) ;Green $z3 = Dec(StringMid($z,5,2)) $z=Round(($z1+$z2+$z3)/3,0) If ($z>=($w-(3*$var))) Then If $digarr[$b][$a]=1 Then $match+=1 ;Sum up number of matching white pixels Else If $digarr[$b][$a]=0 Then $match+=1 ;Sum up number of matching white pixels EndIf Next Next If $match>$maxmatch Or ($c=0 And $d=0) Then $maxmatch=$match $iconpos[0]=$ResIcon[0]-($x/2)+$c $iconpos[1]=$ResIcon[1]-($y/2)+$d EndIf next next IF $maxmatch=($x*$y) Then local $sMsg = "Found at x="&$iconpos[0]&",y="&$iconpos[1]&":match="&$maxmatch&",t="&($w-(3*$var)) FFTrace(" ** "&$sMsg&@lf&"") TrayTip("Found", $sMsg, 2000) $found=1 Else local $sMsg = "Not at x="&$iconpos[0]&",y="&$iconpos[1]&":match="&$maxmatch&",t="&($w-(3*$var)) FFTrace(" ** "&$sMsg&@lf&"") TrayTip("Potential", $sMsg, 2000) FFAddExcludedArea($iconpos[0],$iconpos[1],$iconpos[0]+$x,$iconpos[1]+$y) ; Remove this pattern from search as it didnt match EndIf EndIf until ((Not IsArray($ResIcon)) OR $found=1) If ((Not IsArray($ResIcon)) AND $found<>1) Then Sleep(1000) local $sMsg = "No match found!" FFTrace(" ** "&$sMsg&@lf&"") TrayTip("No icon match", $sMsg, 2000) EndIf EndFunc Local $homeicon[16][16]=[[0,0,0,1,1,0,0,0],[0,0,0,1,1,0,0,0],[0,0,0,1,1,0,0,0],[1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1],[0,0,0,1,1,0,0,0],[0,0,0,1,1,0,0,0],[0,0,0,1,1,0,0,0]] FindIconBW(8,8,46,0xD0E0F0,$homeicon) If I include the "don't search left side of screen" line in this code, it finds the icon every time. If I don't include it, it fails. Using FFNearestSpot also seems to give slightly more positives, but still the same result: After a number of negative matches it fails to find the spot with the icon. Any idea what is wrong? Typical! I ask a question and I find the solution myself If you want to use this routine, change the name of the $z parameter that contains the number of white pixels to $pz or something as $z was reused in the routine. If you also want to exclude any non-perfect match you can speed it up considerably by quitting on a negative: If ($z>=($w-(3*$var))) Then If $digarr[$b][$a]=1 Then $match+=1 ;Sum up number of matching white pixels Else ; Fail, so quit (only perfect match allowed) $a=$x-1 $b=$y-1 EndIf Else If $digarr[$b][$a]=0 Then $match+=1 ;Sum up number of matching white pixels Else ; Fail, so quit (only perfect match allowed) $a=$x-1 $b=$y-1 EndIf EndIf Update: I also found that the FFNearestSpot is better if you have an idea on were on the screen to start the search. Another problem seems to be that the search time increases with the number of Excluded areas, so a better way may be to simply color the false positives with black color: For $a=0 To $x-1 For $b=0 To $y-1 FFSetPixel($iconpos[0]+$a,$iconpos[1]+$b, 0) ; Instead of excluding, draw black across false spot; speeds up consecutive searches Next Next ;FFAddExcludedArea($iconpos[0]+1,$iconpos[1]+1,$iconpos[0]+$x,$iconpos[1]+$y) ; Remove this pattern from search as it didnt match For color search you could change the routine to search for the three color components instead of combining them to a grayscale. I will try to see if I can get that to work.
×
×
  • Create New...