← Back to team overview

sikuli-driver team mailing list archive

Re: [Question #264487]: Help with making some Sikuli image recognition?

 

Question #264487 on Sikuli changed:
https://answers.launchpad.net/sikuli/+question/264487

RaiMan proposed the following answer:
--- repeat after 5th arrow done

referring to my sample I made for you, I would do it this way:

instead of the final
  if not popAsk("repeat?"):
    exit()

I would wait for the 5th arrow to change.
For that I would store the arrow, that matched a bit earlier:
     if col.exists(Pattern(a).similar(0.8), 0):
        print i, a, col.getLastMatch().getScore()
        type(arrows[a]) # type the associated key
        lastArrow = a  # store the match for later use  <-----
        break # leave the inner loop

now after the loop finished with the 5th arrow, we know, which arrow
matched there and wait for it to vanish:

  if reg.getCol(4).exists(Pattern(lastArrow).similar(0.9), 0):
    wait(0.5)

as we already experienced with the similarity challenge, again here you
have to set it reasonably to distinguish from the "naked" arrow (usually
it should even be Pattern(lastArrow).exact().

To not get an endless loop here, one should add a max counter, to limit
the wait time and either exit or simply assume it can repeat.

  max = 10
  if reg.getCol(4).exists(Pattern(lastArrow).similar(0.9), 0):
    wait(0.5)
    max -= 1
    if max == 0:
      continue # loop again
      # exit() # to terminate in this case (recommended while testing)

BTW: 
Modern programming or scripting languages do not have a GOTO anymore. Everything has to be setup in some nested blocks of code. This sometimes make things a bit more complicated depending on the language, but one gets used to it after a while. 
This design principal usually leads to the intensive use of modules/functions, to keep the main workflow clear and transparent.

In your case this could be like that:

def handleOneArrow(cell):
    global lastArrow # to signal an outside used variable
    # loop through the arrow types
    for a in arrows:
      # check the arrow type in segment
      if cell.exists(Pattern(a).similar(0.8), 0):
        print i, a, cell.getLastMatch().getScore()
        type(arrows[a]) # type the associated key
        lastArrow = a
        return True # leave the inner loop
    return False # no arrow matched

def decideRepeat(reg, pattern):
  max = 10
  if reg.exists(pattern, 0):
    wait(0.5)
    max -= 1
    if max == 0:
        return False # signal wait exceeded
  return True

as you might realise here: this approach heavily supports the DRY
principle (don't repeat yourself): implement functions with some
variables, that might be useful in more than one situation.

# all the stuff before the main while loop

while True: # loop until finished
  # loop through the segments
  for i in range(5):
    col = reg.getCol(i)
    if not handleOneArrow(col):
       pass # here we could handle the situation, that no arrow was found
    if not decideRepeat(reg.getCol(4), Pattern(lastArrow).similar(0.9)):
       exit() # or some other action in case of vanishing arrow not detected

now the main workflow is clear and rather fixed. adaptions will only be
needed in the functions eventually.

... and now we can see, where we could add some 'whoops code' (nice wording - hope it is not copyrighted ;-)
It does not make sense to check an arrow, when the bar is no longer there:

while True: # loop until finished
  barImage = capture(reg) # save the initial state of the bar
  # loop through the segments
  for i in range(5):
    if not barExists(reg, barImage):                   <---------
       pass # decide what to do here 
    col = reg.getCol(i)
    if not handleOneArrow(col):
       pass # here we could handle the situation, that no arrow was found
    if not decideRepeat(reg.getCol(4), Pattern(lastArrow).similar(0.9)):
       exit() # or some other action in case of vanishing arrow not detected
    barImage = capture(reg) # save the current state of the bar for next existence check

... and we add another def to the top:

def barExists(reg, barImage):
    if not reg.exists(barImage):
        return False
    return True

now we have the last problem to solve:
after having handled the bar-vanished situation we want to start allover again: but we are on the second loop level and want to proceed with the first level.
Python only knows 
continue - instantly go to the current loop head and continue
break - leave the current loop at this point and continue with the next statement after the loop

other scripting languages have a feature like
continue label
to tell what outer loop should be continued and/or
break label
to tell what outer loop level should be left

In Python in doubt we need an indicator and an additional decision, but
in our case when breaking the inner loop, the next statement will be the
While True anyway:

while True: # loop until finished
  barImage = capture(reg) # save the initial state of the bar
  # loop through the segments
  for i in range(5):
    if not barExists(reg, barImage):                   
       # do everything needed to start again with while True:
       break                        <---------
    col = reg.getCol(i)
    if not handleOneArrow(col):
       pass # here we could handle the situation, that no arrow was found
    if not decideRepeat(reg.getCol(4), Pattern(lastArrow).similar(0.9)):
       exit() # or some other action in case of vanishing arrow not detected
    barImage = capture(reg) # save the current state of the bar for next existence check

-- 
You received this question notification because you are a member of
Sikuli Drivers, which is an answer contact for Sikuli.