Find match exit from pool of images using one if condition

Asked by Sankar on 2017-01-10

Hello,

Below if case is mutually exclusive i.e. only one event will occur in the application.
1. I've to see if any of the even occured, if any match exist within pool of image i.e. event, then I can enter into these condition else I can entirely skip these condition and save time. My application go through these condition 3000 times. Huge loss of time.

if (fr.exists((tempPattern = StaticImages.fn_ImWinClose())) != null) {
   try {
    fr.click(tempPattern);
   } catch (FindFailed e) {
    LogReport.error("Unable to close the dialog");
    e.printStackTrace();
   }
  } else if (fr.exists((tempPattern = StaticImages.fn_ImWinClose1())) != null) {
   try {
    fr.click(tempPattern);
   } catch (FindFailed e) {
    LogReport.error("Unable to close the dialog");
    e.printStackTrace();
   }
  } else if (fr.exists((tempPattern = StaticImages.fn_MinimizeDialog())) != null) {
   try {
    fr.click(tempPattern);
   } catch (FindFailed e) {
    LogReport.error("Unable to minimize the dialog");
    e.printStackTrace();
   }
  } else if (fr.exists(StaticImages.fn_DisabledCloseButtonDialog()) != null) {
   try {
    fr.click(StaticImages.fn_DisabledCloseDialogNoButton());
   } catch (FindFailed e) {
    LogReport.error("Unable to click on NO button on disabled Close button dialog");
    e.printStackTrace();
   }
  }

is below syntax possible ?
fr.exist(image1|| image2|| image3||image4){
     if(fr.exist(image1)) --> do
     else if(fr.exist(image2)) --> do
     else if(fr.exist(image3)) --> do
     else if(fr.exist(image4)) --> do
}

Or any other optimized solution available. Please suggest. Thank you.

Question information

Language:
English Edit question
Status:
Solved
For:
Sikuli Edit question
Assignee:
No assignee Edit question
Solved by:
RaiMan
Solved:
2017-01-17
Last query:
2017-01-17
Last reply:
2017-01-17
Best RaiMan (raimund-hocke) said : #1

If the number of possible match images is up to 3 to 5, this is a base solution, that might be packed into a def(), that accepts a list of images and returns the index of the found match:

images = (img1, img2, img3)

found = 0
if exists(images[found], 0): found += 1
else if exists(images[found], 0): found += 1
else if exists(images[found], 0): found += 1

if found == 1:
    # do what is needed
if found == 2:
    # do what is needed
...

Since the searches are done sequentially, they should be optimized by restricting the search to the smallest possible region.
exists(img, 0) only searches once and comes back immediately (no extra wait time).

If more than 5 possible images are needed, you might delegate the searches to threads, to run them in parallel.

RaiMan (raimund-hocke) said : #2

uups, I just realized it is Java code:
... but should be easy, to transcript the above Python snippet ;-)

Sankar (sankar88) said : #3

Thanks for the information, exists(img, 0) saves a lot of time.

But still many if condition with exist() function called.
Isn't it possible to check match of all the image in one exist() function ?
e.g. with one
region.exist(img1 || img2 || img3){
      then go to other if condition
 }

In my scenario, these condition occurs randomly for 2% of my action. So looking for this occurence is costly.

1) I use Python dictionary datatype for that. SikuliX supports dictionaries, including dictionaries for images

Demo code (tested).
_________
Settings.MinSimilarity = 0.95

image_dictionary = {"sumatra":"sumatra_icon.png" ,"firefox": "firefox_icon.png", "chrome": "chrome_icon.png" }

for key in image_dictionary.keys():
    if exists(image_dictionary[key]):
        hover(getLastMatch())
_______

"sumatra" here is a dictionary key (a string), and "sumatra_icon.png" stands for image of Sumatra PDF editor icon.

I go by keys, not by images themselves (which I also could), as I may need found key needed for some different operation. For instance, the code can be further enhanced with "message dictionary" to log some pre-defined message if Sumatra icon was found, etc:

_________
message_dictionary = {"sumatra":"Sumatra PDF editor" ,"firefox": "Firefox browser", "chrome": "Chrome browser" }
...

print (message_dictionary[key]) + " was found"
_________

{Note about Java. Java has similar datatype, HashMap, which can be used in similar construction }.

I prefer dictionary/hashmap for things like these, as string index can be more helpful than numeric here.

2) Things like
______
 try {
    fr.click(StaticImages.fn_DisabledCloseDialogNoButton());
   } catch (FindFailed e) {
    LogReport.error("Unable to click on NO button on disabled Close button dialog");
    e.printStackTrace();
   }
____

Can be packed into function

def try_to_click_and_log(key):
     try {
        fr.click(image_dictionary[key]);
       } catch (FindFailed e) {
        LogReport.error(message_dictionary[key]);
        e.printStackTrace();
       }

3) To speed up image search consider if you can restrict search region. For instance, if images you expect can be found only in center part of the screen, you can construct special region for that with Region(x,y,width,height).

Sankar (sankar88) said : #6

Hi Roman Podolyan,

The image what i'm trying to search is mutually exclusive, only one can occur at time.
If-else-if condition helps in breaking mostly in first event. If I use Map, it is not efficient.

My additional Question was:
Does exist(image1 || image 2 || image 3) is supported ?
If not, it will be good to have one.

Sankar (sankar88) said : #7

Thanks RaiMan, that solved my question.

Sankar (sankar88) said : #8

Hi Roman Podolyan,

Thanks for your suggestion on point-2.
I'll implement it.

> The image what i'm trying to search is mutually exclusive, only one can occur at time.
> If-else-if condition helps in breaking mostly in first event.

Aha. Well, that changes things to some extent.

Ordered list of tuples to the rescue:

_______
Settings.MinSimilarity = 0.95

image_tuples_list = [("sumatra","sumatra_icon.png"), ("firefox", "firefox_icon.png" ), ("chrome", "chrome_icon.png" )]

for key in range(0, len(image_tuples_list) - 1):
    print "Looking for " + image_tuples_list[key][0]
    if exists(image_tuples_list[key][1]):
        hover(getLastMatch())
        print image_tuples_list[key][0] + " found"
        break
______

This code goes by list of tuples one by one, it looks for images and still has the ability to get a string ID of what was found.

When the first image has been found, loop breaks and does not search for the next images.

Test output (Sumatra closed, firefox is open)
____
Looking for sumatra

Looking for firefox

firefox found, end of seaches
____