Count number of same images that are horizontally parallel in the screen

Asked by eduardobedoya

I would like to count the number of same images that are horizontally parallel in the screen and sort them so the foremost left is 0 (first) and the foremost right is -1 (last)

right know Im using this

count = 0
try:
    matches = list(findAll(Pattern("1425879837185.png").exact()))
    count = len(matches)
except FindFailed:
    pass #nothing to do
print "found:", count

if count > 0:
    sortedMatches = sorted(matches, key=lambda m:m.y) # sorts top to bottom
    hover(sortedMatches[-1]) # take the last one

but don't know why it does not click in the lastone

Thanks advanced

Question information

Language:
English Edit question
Status:
Answered
For:
SikuliX Edit question
Assignee:
No assignee Edit question
Last query:
Last reply:

This question was reopened

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

to sort horizontally one needs to use the x value:

 sortedMatches = sorted(matches, key=lambda m:m.x) # sorts left to right

Revision history for this message
eduardobedoya (gonnabdh) said :
#6

Thanks RainMan

so I guess
sortedMatches = sorted(matches, key=lambda m:m.y)
sorts the matches from top left, to bottom right, am I right?
so if the images are inside a table's cells, the result will be sorted in this order...
1. Top row left image
2. Top row right image
3. Middle row right image
4. Bottom row left image

am I right? How can I achieve this?

Thanks Advanced.

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

again this has nothing to do with SikuliX, it is Python basics list handling and hence can be found in the Python docs or any tutorial, that talks about list handling.

--- sorts the matches from top left, to bottom right, am I right?
surely not.
after the sort, the first element will be that with the smallest m.y value and the last element will be that with the largest m.y value. Usually with sorting when two matches have the same m.y value, the sequence is either unpredictable or unchanged.
I do not know, how Python sorted() handles that.

I do not have the time currently to solve that, but you have to turn the list into a 2-dimensional list somehow.

Revision history for this message
eduardobedoya (gonnabdh) said :
#10

I mean if all images to find are exactly the same, how can I sort them so the first is the top left and the last is the top right,
sorry Im not a programmer, it was just not clear to me if this was a python or sikuli coding. What is the m.y value?
Right now Im googling python list handling but I cant find m.y value.
 thanks advanced.

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

m.x and m.y are the coordinates (x,y) of the matched rectangle on the screen (top left corner).

This is Sikuli specific and documented here:
http://sikulix-2014.readthedocs.org/en/latest/index.html

To solve your problem is not trivial (even for a more experienced scripter).

A list representing rows and columns looks like this:

m = []
m.append([11, 12, 13, 14])
m.append([21, 22, 23, 24])
m.append([31, 32, 33, 34])
m.append([41, 42, 43, 44])
"""
a 4 row, 4 column martrix
[[11, 12, 13, 14],
 [21, 22, 23, 24],
 [31, 32, 33, 34],
 [41, 42, 43, 44]]
"""
# the martrix indices are counted from 0
print m # the complete matrix
print m[0] # the first row
print m[2,3] # the rightmost element in the 3rd row

# to print the second column
for i in range(4):
  print m[i, 1]

depending on how exact your visual layout is (e.g. all matches in one row have the same m.y values) the filling of this matrix more or less complex.

if all the m.y values in one row are equal, this trick gives you list containing all matches ordered in row and column

sortedMatches = sorted(matches, key=lambda m: m.y * 10000 + m.x)

now you might fill the above matrix to have a row/column representation

or simply use the list as is:
say you have k elements per row, then the rightmost element in the n-th row is:
sortedMatches[n*k + k - 1]

again: you touched a very complex situation very early in your starting experience and should think over, wether this is the write approach.

version 1.1.0 has a feature to divide a region into even row and/or column elements and address these elements by index.
(see the docs)

Revision history for this message
eduardobedoya (gonnabdh) said :
#12

Thanks RaiMan, that solved my question.

Revision history for this message
eduardobedoya (gonnabdh) said :
#15

Hi RaiMan, yes Im using version 1.1.0
Currently Im reading this...
http://sikulix-2014.readthedocs.org/en/latest/region.html#Region and I found this below...
"Get evenly sized parts of a Region (as rows, columns and cells based on a raster)"
So I return to this question.

Yes my grid is very even, (all matches in one row have the same m.y values)
I understand everything you comment above,
I even understand this...
-- say you have k elements per row, then the rightmost element in the n-th row is:
sortedMatches[n*k + k - 1] _____(it took me a while xD)

But I still can't understand this...
-- sortedMatches = sorted(matches, key=lambda m: m.y * 10000 + m.x)
why 10000? is this similar to the previous formula???

Does version1.1.0 new grid features override the necessity of these two formulas above???

Thanks Advanced.

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

the sorted function accepts a so called lambda (anonymous function) as sort key

key=lambda m: m.y * 10000 + m.x

where m represents a value of the given list. after the colon you have to write down a formula, that returns ONE value.

Since in this case we want to sort with respect to 2 values (x and y), we have to translate the sort value in some usable value.

In this case, we "shift" the y value to the left (*10000, should be sufficient for normal screen sizes) and add the x value.
This gives a combined integer, that does exactly what you want:
grand order y value
local order (same y value) x value

Revision history for this message
eduardobedoya (gonnabdh) said :
#17

oh I see,
Shift has a meaning in programming
THanks
I will work on this ASAP.

But what about 1.1.0 new grid features,
you can divide the screen area into even rows and columns
does that replace both codes in your comment?
in which cases is better to use each approach?

Thanks Advanced.

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

I am really sorry: much buzz about nothing - but that is really my fault:

this works for sorting matches:

sortedMatches = sorted(matches, key = lambda m: (m.y, m.x))

the sort function specified with key= might return a list of values, that are used, to define the sort order:
- a match with a lower y value comes before any match with a higher value
- matches with same y are sorted according to their x value.

for more complex sorting, one can use this:

def order(match):
    y = match.y
    x = match.x
    # do some calculation or whatever for y and x
    return y, x

sortedMatches = sorted(matches, key = order) # the helper function is called for each element in matches

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

the grid feature is an alternative to some complex and time consuming findAll() in situations, where you can "calculate" some regular row and/or column setup of a region (some visuals, that are arranged in some tabular way).

Since it is only a calculation of subregions in a region, it is very, very fast and might reduce the searching effort to just checking, which visual is contained in a grid element (which in turn again is very fast, since these subregions usually are not much larger than the visual).

The challenge is, to setup an appropriate grid, even in situations, where the setup is dynamic (might change from case to case).

Since I saw the word "IrfanView" somewhere in you questions/comments: the view, that shows the images usually is a regular grid.

Can you help with this problem?

Provide an answer of your own, or ask eduardobedoya for more information if necessary.

To post a message you must log in.