Is there a way to discard the background while image compareing

Asked by Anunaya

HI Raiman

I am automating an android phone and there is a Music player icon on the home screen. I take the image of the icon and do a click but if I change the wall paper in the background, it does not work and gives an error find failed.

Is there a way I can discard the background colour so that even if i change the wall paper it does not effect my script.

Thanks in advance.

Question information

Language:
English Edit question
Status:
Solved
For:
SikuliX Edit question
Assignee:
No assignee Edit question
Solved by:
Anunaya
Solved:
Last query:
Last reply:
Revision history for this message
RaiMan (raimund-hocke) said :
#1

Make a shot of the icon, that has as little background as possible concentrating on the parts of the icon, that makes it unique (distinguishes from other icons).

Currently there is no feature, to ignore parts of an image (or take it as transparent).

Revision history for this message
Eugene Maslov (emaslov1) said :
#2

@Anunaya

If the icons are semi-transparent, so that cropping doesn't help, it's still possible to make several screenshots of the icons for each background and send it to a function selecting the best of them.
I mostly use this way for blinking buttons, which change their color with time.

It can be like that:

def findAny(thelist, theregion=SCREEN, timeout=False):
    if not timeout:
        timeout=theregion.getAutoWaitTimeout()
    res=None
    i=0
    for s in thelist:
        if i==0:
            t=timeout
        else:
            t=0
        found=theregion.exists(s,t)
        i+=1
        if found:
            res=found
            break
    return res
#usage:
thereg=Region(324,321,648,429)
findAny(["btn_bg1.png","btn_bg2.png","btn_bg3.png"], thereg,timeout=20).click()

Revision history for this message
Eugene Maslov (emaslov1) said :
#3

Sorry, this corrected function processes second image in the list quicker. Please discard the code in the answer #2.

import time

def findAny(thelist, theregion=SCREEN, timeout=False):
    if not timeout:
        timeout=theregion.getAutoWaitTimeout()
    res=None
    start_time=time.time()
    exit_time=start_time+timeout
    while time.time()<=exit_time:
        for s in thelist:
            found=theregion.exists(s,0)
            if found:
                res=found
                break
        if res:
            break
    return res

#usage:
thereg=Region(324,321,648,429)
findAny(["btn_bg1.png","btn_bg2.png","btn_bg3.png"], thereg,timeout=20).click()

Revision history for this message
RaiMan (raimund-hocke) said :
#4

@Eugene
thanks for your solution.
... I have some optimisations:

# import time # not necessary since already done by Sikuli

def findAny(thelist, theregion=SCREEN, timeout=False):
    if not timeout:
        timeout=theregion.getAutoWaitTimeout()
    res=None
    exit_time=time.time()+timeout
    while not res and time.time()<exit_time():
      for s in thelist:
        res=theregion.exists(s,0)
        if res:
          break
    return res

#usage:
thereg=Region(324,321,648,429)
btn = findAny(["btn_bg1.png","btn_bg2.png","btn_bg3.png"], 20)
if btn;
    btn.click()
else:
    # do some error handling

... since the return value of findAny might be None, None.click() would produce an odd exception.

Region.getAutoWaitTimeout() returns the global AutoWaitTimeout, if the Region does not have its own value at this time (the specific Region value is set to the global at init of the Region).

Revision history for this message
RaiMan (raimund-hocke) said :
#5

the feature findAny will be available in version 1.2 and it will be threaded internally (the searches are done in parallel).

Revision history for this message
Anunaya (anunayathakur1) said :
#6

Hi Raiman & Eugene

Thanks a lot. This solved my problem.

You guys are awesome:)

Please let me know when will version 1.2 would be released

Revision history for this message
Brad (blueoni) said :
#7

Sorry for resurrecting an old topic, but I'm using the code in Comment #4 and was wondering if/how I can tell which was matched?

for example:
#usage
thereg=Region(324,321,648,429)
btn = findAny(["btn_bg1.png","btn_bg2.png","btn_bg3.png"], 20)
if btn;
    if btn.filename == "btn_bg1.png": btn.rightClick()
    else: btn.click()
else:
    # do some error handling