Visual matching
Visual matching is the heart of OculiX. You give it a small image, it tells you where on the current screen that image appears. Everything else — clicking, typing, waiting — is built on top of that primitive.
Core classes
Section titled “Core classes”| Class | What it represents |
|---|---|
Screen | A physical monitor. Screen(0) is the primary. Multi-monitor: Screen(1), Screen(2), … |
Region | Any rectangular area you can search in. Screen is a Region covering the whole display. |
Pattern | An image plus matching parameters (similarity, targetOffset). |
Match | The result of a successful find — a Region plus a similarity score and the original pattern. |
Location | A single point (x, y). |
You can use Pattern everywhere Region expects an image, and vice-versa — the API is overloaded for both.
The five verbs
Section titled “The five verbs”Every visual operation is one of these:
find(image) # locate once, throw FindFailed if missingexists(image) # locate once, return None if missingwait(image, secs) # poll until it appears or timeoutwaitVanish(image, s) # poll until it disappears or timeoutfindAll(image) # locate every occurrence (iterator)All five accept a path ("button.png"), a Pattern, or another Region.
A worked example
Section titled “A worked example”from sikuli import *
s = Screen(0) # primary monitor
# Wait up to 10 s for the app to appearapp = s.wait("main_window.png", 10)
# Restrict search to the right pane only — faster, less ambiguousright_pane = app.right(app.getW() // 2)save = right_pane.find("save_button.png")
save.highlight(1.5) # flash a red box on screen for 1.5 ssave.click()s.wait() returns the matching Region. right_pane.find() returns a Match whose .click() does what you expect.
Similarity
Section titled “Similarity”Default similarity is 0.7 (70 %). You can override per call or globally:
# Per callclick(Pattern("button.png").similar(0.85))
# Per scriptSettings.MinSimilarity = 0.65Higher = stricter, lower = more permissive. Anti-aliased text, transparency, theme changes, and font hinting all reduce match scores — relax similarity rather than re-capture the image each time.
Target offset
Section titled “Target offset”By default OculiX clicks the center of a match. To click somewhere else relative to the image:
# Click 30 px to the right and 5 px down from the center of the iconicon = Pattern("icon.png").targetOffset(30, 5)click(icon)This is the canonical way to click a label that sits next to a recognizable icon.
Region operations
Section titled “Region operations”A Region knows where it is and how to chop itself up:
r = Screen(0)
r.left(200) # 200-px-wide strip on the leftr.right(200) # 200-px-wide strip on the rightr.above(100) # 100-px strip above rr.below(100) # 100-px strip below rr.inside() # the region itselfr.nearby(50) # a 50-px-larger versionr.grow(50, 100) # asymmetric growr.morphTo(otherRegion)# resize/move to match another regionCombined with find() these make scripts dramatically more robust:
# Don't search the whole screen — only inside the dialogdialog = wait("save_dialog_title.png", 5)dialog.click("save_button.png") # search constrained to dialogAnchors — define a region relative to something you can find
Section titled “Anchors — define a region relative to something you can find”header = find("header_logo.png")search_box = header.right(800).below(0) # 800-px-wide region to the rightsearch_box.click()search_box.type("oculix")When the layout shifts but the relative position is stable, anchors keep your script working.
findAll — every occurrence
Section titled “findAll — every occurrence”# Iterate over every matchfor m in findAll("checkbox_unchecked.png"): m.click()findAll() returns an iterator of Match objects, sorted by similarity score (highest first by default).
Highlight — debug visually
Section titled “Highlight — debug visually”match = find("save_button.png")match.highlight(2) # red box for 2 smatch.highlight("green") # named colorsmatch.highlight(2, "yellow")Great for figuring out why your script clicked somewhere unexpected — highlight() shows you exactly what OculiX found.
Slow Motion mode
Section titled “Slow Motion mode”From the IDE: Run → Run Slow Motion. Each match flashes for half a second before the action fires. You see exactly what OculiX sees, in order.
Settings that affect matching
Section titled “Settings that affect matching”Settings.MinSimilarity = 0.7 # default similarity floorSettings.AlwaysResize = 1.0 # scale captures by N before matchingSettings.MoveMouseDelay = 0.3 # seconds to glide the cursorSettings.WaitScanRate = 3 # find() scans per second during wait()Settings.ObserveScanRate = 3 # observer scan rateSettings.AutoWaitTimeout = 3.0 # implicit wait before every actionAutoWaitTimeout is particularly useful: if it’s > 0, click(image) implicitly waits for the image before clicking, so you rarely need explicit wait() calls.
Performance tips
Section titled “Performance tips”- Smaller patterns match faster. Tight crops > wide screenshots.
- Restrict to a
Regioninstead of searching the wholeScreen. - Cache
Matchobjects when the layout is stable —target.click()is free;find()costs CPU. - Use
exists()for branching, notfind()—exists()returnsNoneinstead of throwing.
Common errors
Section titled “Common errors”| Error | Typical cause |
|---|---|
FindFailed | Image not visible, hidden behind another window, similarity too strict |
ImageMissing | Path is wrong, image not in the .sikuli bundle |
org.opencv.core… | Apertix mismatch — see Installation |
- Read text on screen with OCR — when you need text, not pixels
- The vision pipeline — under the hood: Apertix, template matching, OpenCV
- API reference — every method, every parameter