Save image

Asked by mcklaw

Hi!

   Is there any way to save to file the result of a find() call?

Thanks in advance.

Question information

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

I'm a Mac (take into consideration with the filenames)

If anything is found by find() it returns a Match object. This contains pos and dim inside the screenshot image at the time of calling find(), means where on the screen your image was found with best similarity.

m = find(<image>)
print m

or equivilent:

find(<image>)
print find.region

the first coding saves the match for future use.

the print will show you the pos and dim and image filename (always temporary) of screenshot after the @ in the message area like this:
Match[22,27-520x55 1,00]@/var/folders/Cw/CwAqI2ylEqGdNCDuByhznU+++TI/-Tmp-/sikuli7848132577269802909.png

picture you searched for was found at [22,27-520x55] means [upper left corner - dimension] with a similarity of 1,00, which means exactly matching.

So what do you want to save to a file?

The match information?
m = str(find())
m is a string now that you can write to a file with the means of python

The screenarea matched?
this normally is the picture itself. you have it in your Sikuli script (Mac: pic files in the script bundle, Win: same in the script folder)
p = <captured picture>
print p
gives you the filename of the picture: like that: 1266762525282.png
this is already there.

Be aware, that every find may come up with up to 10 (standard) or given by Pattern().firstN() matches, witch are stored in a list following a successful find and can be recalled by find.regions.

You can ask a Match to give you its information:
m.getX(), m.getY(), m.getW(), m.getH() with X,Y upper left and W,H the dimension
m.getScore the similarity between 0.0 and 1.0

This helps when capturing interactively with capture(), that comes back with a temp filename:
pic = capture()
print pic
shows up with something like that:
/var/folders/Cw/CwAqI2ylEqGdNCDuByhznU+++TI/-Tmp-/sikuli-tmp1612566284701348630.png
If this is your case, just use python to copy the file to where you want it to be and name it as you want.

If you want to store the found screenarea in all situations:
pic = capture(m.getX(), m.getY(), m.getW(), m.getH()) where m is a match you produced before
pic again is a temp picture file containing the region given as pos,dim parameters.
this may be helpful, when similarity is not 1.0, in which cases, the matched area may not be, what you are looking for.

In all cases you should check wether find returns something not None:
m = find()
if m:
  print m
else:
  popup("Sorry")

Revision history for this message
mcklaw (victor-martinez-conte) said :
#2

Hi RaiMan,

   Thank you very much for your response. It has clarified me some points, and sorry, i was not very specific in my question.

   My problem is that i want to store a part of a screen (It's an image with letters and numbers, but there is no ORC at the moment, right?). I locate this "image" through a find().left(). I supposed (wrog) that the match object contained the image itself. With the image captured (with capture() i see). I need to store it in a standar format (png for example) with a fixed name (i have to get the image several times, so i need to numerate them) to review them manually to get the data.

Thanks in advance.

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

I hope I understand your workflow:
- the screen contains an area, you are interested in
- you want to save this area into a picture file ( .png), filename has to be distinct

scenarios:
1. the area is fixed in dimension and relative position to something you can be sure to find on your screen.
2. same as 1., but only the position and the width of the area is fixed
3. same as 1., but only position is fixed
4. nothing is fixed at all

scenario 1 is rather simple:
todo before: evaluate the relative distance (upper left corner) between the ref pic and your area and width and height of area
xOff = 200 # may be negative if positioned left
yOff = 300 # may be negative if positioned above
w = 400
h = 500
m = find(<reference pic>)
if m:
   (x, y) = (m.getX(), m.getY()) # now you have the upper left of the reference
   myArea = capture(x+xOff, y+yOff, w, h) # now contains the filename of the pic file with your area

scenario 2 and 3:
you have to try to get additional reference points to the right or below, that helps to get the dim for the capture. If not possible, you have to make assumptions and have to live with additional grafical info in your capture

scenario 4:
you have to use the interactive capture. just write down:
myArea = capture() # now contains the filename of the pic file with your area. you need a user in front of the screen!

Get the pic file myArea to where you want it:
the easiest way would be:
import os
os.system("....") # the command that copies the myArea-file to where you want

e.g. cmd = "copy " + myArea + " name" + str(counter) + ".png" # may be path information required.

For additional possibilities, you have to dive into python module os.

additional idea:
as far as I understood, your goal is to read something later on, that you have captured on the screen?
if so, you can try to use a cut and past strategy to get the text.
Sorry, but in the moment this only works, if the text is inside a textfield, where the text can be selected with type("a", KEY_CTRL) (Mac: KEY_CMD). For the other situations you would need click(<pic>, KEY_SHIFT), which does not work (bug reported) in the moment.

in all scenarios:
don't capture, just select the text, open a predefined textfile, paste it with some identifying information to the end/beginning and save the textfile again.

workflow (Windows)
just find a position inside the text field and say:
click(m)
type("a", KEY_CTRL)
type("c", KEY_CTRL) # your text is on the clipboard
switchApp("TextApp") # your text application
type(...) # the key combi to get the open dialog
paste("myFile.txt") # hopefully, the field to fill in the file name has focus and is empty, you may need the full path
type(...) to get the cursor to where you want in the text window
paste("....") # some info to make the new info unique
type("v", KEY_CTRL) # paste in your new info
type(...) # # the key combi to save and close

it may be neccessary, to place some sleep() in between, to take timing into account.

Revision history for this message
mcklaw (victor-martinez-conte) said :
#4

Hi RaiMan,

   Thank you for your quick (and detailled) response. You have understood right my workfow. I'm in scenario 4. I find the image with a find(<fixed_img>).right() (i saw this in example how to check specific checkboxes). I cound not do a copy/paste (i thought this) cos it is text but inside an image (this is why i asked about OCR).

    I tried to capture the image yesterday, but it gave to me an Heap memory error (i think image was too big). I tried to increase java memory with a -Xmx1000m in the sikuli.bat, but it didn't worked. I saw in the forum that there is a reported bug about size capture. I will try to fix the size and hope that all "text" fits into it.

  PS: i come form Jave. Dou you know a good manual to switch to python/jython? I have read that sikuli is jython, but i'm not sure :-S

Thanks in advance

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

Hi,

m = find(<fixed_img>).right()
after that, m is a match , that matches the screenarea at (m.getX()+m.getW(), m.getY(), 9999999, m.getH())
so it has the height of your <fixed_img>. That's what you want?

There are bugs in the moment with finding images, that have either width or height larger than 200-300 pixel and images, that contain far more text than grafics.

You say, you are scenario 4. So why do you need any find before you give the user the chance to capture with capture()?

coming from Java, you should look at Jython first:
a nice book in developement: http://jythonpodcast.hostjava.net/jythonbook/en/.99/
good starting point: http://wiki.python.org/jython/DocumentationAndEducation

You will learn Python on the fly;-) If you need more special python (internals of modules and classes/objects) you have to go to http://www.python.org/doc/

Have a nice time.

Am 22.02.2010 um 12:14 schrieb mcklaw:

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

mcklaw posted a new comment:
Hi RaiMan,

  Thank you for your quick (and detailled) response. You have
understood right my workfow. I'm in scenario 4. I find the image with a
find(<fixed_img>).right() (i saw this in example how to check specific
checkboxes). I cound not do a copy/paste (i thought this) cos it is text
but inside an image (this is why i asked about OCR).

   I tried to capture the image yesterday, but it gave to me an Heap
memory error (i think image was too big). I tried to increase java
memory with a -Xmx1000m in the sikuli.bat, but it didn't worked. I saw
in the forum that there is a reported bug about size capture. I will try
to fix the size and hope that all "text" fits into it.

 PS: i come form Jave. Dou you know a good manual to switch to
python/jython? I have read that sikuli is jython, but i'm not sure :-S

Thanks in advance

--
You received this question notification because you are a direct
subscriber of the question.

Revision history for this message
mcklaw (victor-martinez-conte) said :
#6

Hi RaiMan,

    The process will be working for some days (and nights) recap information unattendly (statistics of a telephone line). After that, a person have to interpret the collected data to ensure that they are in a right range. it's not viable to do a manually capture.

Cheers!

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

Hi,

ok, then it is not scenario 4, it is one of the scenarios 1 to 3.

since you need to use a find, to get to your area, I guess, that every time you want to do a capture, the screen situation has to be build up before and you cannot be sure where on the screen this information is this time. I think its a good idea, to think about how you can make it more stable (make the app fullscreen e.g.) or make the position of the information predictible with other means of the app or your system.

if you use m = find(<img>).right() and <img> does not have the height of what you want to capture, you have to do some evaluation/calculation for the capture parameters. so be sure that your find(<img>) works, before looking to the right:
m = find(<img>)
if m:
   mArea = m.right()
   picArea = capture(mArea.getX(), .... ) or capture(mArea) if dimensions are ok
   ... the rest of your coding in case of success
else:
   .... some coding in case of not found

This is especially true if the script should run unattended for such a long time. Not found may happen if someone or some program changes the screen situation while the script runs.

My experience with the actual version of Sikuli is to avoid finding images larger than 100x100, check the return of find() as often as it makes sense.

Since this may blow up your coding and you may run into indentation problems, you may look at https://answers.launchpad.net/sikuli/+question/101431 second comment, where i documented what is possible right now with the try:/except: construct.

Cheers back!

Am 22.02.2010 um 13:20 schrieb mcklaw:

   The process will be working for some days (and nights) recap
information unattendly (statistics of a telephone line). After that, a
person have to interpret the collected data to ensure that they are in
a right range. it's not viable to do a manually capture.

Cheers!

Revision history for this message
mcklaw (victor-martinez-conte) said :
#8

Hi,

   Well, i've tested that image to capture is less than heigth of find(<img>). Thanks to your point to avoid to find images larger than 100x100, cos i'd some larger :-S I'll maximize app and fix position of capture, but i wanted to find() it cos it's a web page of our ISP and they usually use to change it. Anyway, it's no a long life app, so this hack could do a better perfomance.

   By the way, sikuli is great, but I've seen the GUI a little "spartan" (no undo, no "recent files", screen capture doesn't work very well on XP, etc). Do you know if there is a roadmap to improve the GUI?

Cheers!