Best Python code snippet using fMBT_python
eyenfinger.py
Source:eyenfinger.py  
...32python -c '33from eyenfinger import *34autoconfigure("screenshot.png", ["Try", "to", "find", "these", "words"])35'36evaluatePreprocessFilter() highlights words detected on given image. Example:37python -c '38from eyenfinger import *39evaluatePreprocessFilter("screenshot.png", "-sharpen 5 -resize 1600x", ["File", "View"])40'41setPreprocessFilter() sets given filter to be used when reading text from images.42Debugging43---------44iClickWord() capture parameter visualises coordinates to be clicked. Example:45python -c '46from eyenfinger import *47setPreprocessFilter("-sharpen 5 -filter Mitchell -resize 1600x -level 40%,50%,3.0")48iRead(source="screenshot.png")49iClickWord("[initial", clickPos=(-2,3), capture="highlight.png", dryRun=True)50'51"""52import distutils.sysconfig53import time54import subprocess55import re56import math57import htmlentitydefs58import sys59import os60import tempfile61import atexit62import shutil63import ctypes64import platform65import struct66import warnings67def _DEPRECATED():68    warnings.warn("eyenfinger.py API is deprecated, use fmbtx11 instead.",69                  DeprecationWarning, stacklevel=2)70_g_preprocess = "-sharpen 5 -filter Mitchell -resize 1920x1600 -level 40%%,70%%,5.0 -sharpen 5"71_g_readImage = None72_g_origImage = None73_g_hocr = ""74_g_words = None75_g_lastWindow = None76_g_defaultClickDryRun = False77_g_defaultDelayedDrawing = False78_g_defaultIconMatch = 1.079_g_defaultIconColorMatch = 1.080_g_defaultIconOpacityLimit = 0.081_g_defaultInputKeyDevice = None82_g_defaultReadWithOCR = True83# windowsOffsets maps window-id to (x, y) pair.84_g_windowOffsets = {None: (0,0)}85# windowsSizes maps window-id to (width, height) pair.86_g_windowSizes = {None: (0,0)}87# screenSize is a (width, height) pair.88_g_screenSize = (0, 0)89_g_tempdir = tempfile.mkdtemp(prefix="eyenfinger.%s." % (os.getpid(),))90SCREENSHOT_FILENAME = _g_tempdir + "/screenshot.png"91LOG_FILENAME = _g_tempdir + "/eyenfinger.log"92MOUSEEVENT_MOVE, MOUSEEVENT_CLICK, MOUSEEVENT_DOWN, MOUSEEVENT_UP = range(4)93# Xkeys contains key names known to X11, see keysymdef.h.94Xkeys = [95    "BackSpace", "Tab", "Linefeed", "Clear", "Return", "Pause",96    "Scroll_Lock", "Sys_Req", "Escape", "Delete", "Home", "Left",97    "Up", "Right", "Down", "Prior", "Page_Up", "Next", "Page_Down",98    "End", "Begin", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8",99    "F9", "F10", "F11", "F12", "Shift_L", "Shift_R", "Control_L",100    "Control_R", "Caps_Lock", "Shift_Lock", "Meta_L", "Meta_R",101    "Alt_L", "Alt_R", "space", "exclam", "quotedbl", "numbersign",102    "dollar", "percent", "ampersand", "apostrophe", "quoteright",103    "parenleft", "parenright", "asterisk", "plus", "comma", "minus",104    "period", "slash", "0", "1", "2", "3", "4", "5", "6", "7", "8",105    "9", "colon", "semicolon", "less", "equal", "greater", "question",106    "at", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L",107    "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y",108    "Z", "bracketleft", "backslash", "bracketright", "asciicircum",109    "underscore", "grave", "quoteleft", "a", "b", "c", "d", "e", "f",110    "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s",111    "t", "u", "v", "w", "x", "y", "z", "braceleft", "bar",112    "braceright"]113# InputKeys contains key names known to input devices, see114# linux/input.h or http://www.usb.org/developers/hidpage. The order is115# significant, because keyCode = InputKeys.index(keyName).116InputKeys = [117    "RESERVED", "ESC","1", "2", "3", "4", "5", "6", "7", "8", "9", "0",118    "MINUS", "EQUAL", "BACKSPACE", "TAB",119    "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P",120    "LEFTBRACE", "RIGHTBRACE", "ENTER", "LEFTCTRL",121    "A", "S", "D", "F", "G", "H", "J", "K", "L",122    "SEMICOLON", "APOSTROPHE", "GRAVE", "LEFTSHIFT", "BACKSLASH",123    "Z", "X", "C", "V", "B", "N", "M",124    "COMMA", "DOT", "SLASH", "RIGHTSHIFT", "KPASTERISK", "LEFTALT",125    "SPACE", "CAPSLOCK",126    "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10",127    "NUMLOCK", "SCROLLLOCK",128    "KP7", "KP8", "KP9", "KPMINUS",129    "KP4", "KP5", "KP6", "KPPLUS",130    "KP1", "KP2", "KP3", "KP0", "KPDOT",131    "undefined0",132    "ZENKAKUHANKAKU", "102ND", "F11", "F12", "RO",133    "KATAKANA", "HIRAGANA", "HENKAN", "KATAKANAHIRAGANA", "MUHENKAN",134    "KPJPCOMMA", "KPENTER", "RIGHTCTRL", "KPSLASH", "SYSRQ", "RIGHTALT",135    "LINEFEED", "HOME", "UP", "PAGEUP", "LEFT", "RIGHT", "END", "DOWN",136    "PAGEDOWN", "INSERT", "DELETE", "MACRO",137    "MUTE", "VOLUMEDOWN", "VOLUMEUP",138    "POWER",139    "KPEQUAL", "KPPLUSMINUS", "PAUSE", "SCALE", "KPCOMMA", "HANGEUL",140    "HANGUEL", "HANJA", "YEN", "LEFTMETA", "RIGHTMETA", "COMPOSE"]141_inputKeyShorthands = {142    "-": "MINUS", "=": "EQUAL",143    "[": "LEFTBRACE", "]": "RIGHTBRACE", "\n": "ENTER",144    ";": "SEMICOLON",145    ",": "COMMA", ".": "DOT", "/": "SLASH",146    " ": "SPACE" }147class EyenfingerError(Exception):148    pass149class BadMatch (EyenfingerError):150    pass151class BadWindowName (EyenfingerError):152    pass153class BadSourceImage(EyenfingerError):154    pass155class BadIconImage(EyenfingerError):156    pass157class NoOCRResults(EyenfingerError):158    pass159try:160    import fmbt161    def _log(msg):162        fmbt.adapterlog("eyenfinger: %s" % (msg,))163except ImportError:164    def _log(msg):165        file(LOG_FILENAME, "a").write("%13.2f %s\n" %166                                      (time.time(), msg))167try:168    import ctypes169    _libpath = ["",170                ".",171                os.path.join(".", ".libs"),172                os.path.dirname(__file__),173                os.path.join(os.path.dirname(__file__), ".libs"),174                distutils.sysconfig.get_python_lib(plat_specific=1)]175    for _dirname in _libpath:176        try:177            eye4graphics = ctypes.CDLL(os.path.join(_dirname, "eye4graphics.so"))178            break179        except: pass180    else:181        raise ImportError("%s cannot load eye4graphics.so" % (__file__,))182    class Bbox(ctypes.Structure):183        _fields_ = [("left", ctypes.c_int32),184                    ("top", ctypes.c_int32),185                    ("right", ctypes.c_int32),186                    ("bottom", ctypes.c_int32),187                    ("error", ctypes.c_int32)]188except Exception, e:189    Bbox = None190    eye4graphics = None191    _log('Loading icon recognition library failed: "%s".' % (e,))192# See struct input_event in /usr/include/linux/input.h193if platform.architecture()[0] == "32bit":194    _InputEventStructSpec = 'IIHHi'195else:196    _InputEventStructSpec = 'QQHHi'197# Event and keycodes are in input.h, too.198_EV_KEY = 0x01199# _inputKeyNameCodeMap is a dictionary keyName -> keyCode200_inputKeyNameCodeMap = {}201for code, name in enumerate(InputKeys):202    _inputKeyNameCodeMap[name] = code203def _inputKeyNameToCode(keyName):204    if keyName in _inputKeyNameCodeMap:205        return _inputKeyNameCodeMap[keyName]206    elif keyName in _inputKeyShorthands:207        return _inputKeyNameCodeMap[_inputKeyShorthands[keyName]]208    else:209        raise ValueError('Invalid key name "%s"' % (keyName,))210def error(msg, exitstatus=1):211    sys.stderr.write("eyenfinger: %s\n" % (msg,))212    sys.exit(1)213def printEventsFromFile(filename):214    fd = os.open(filename, os.O_RDONLY)215    try:216        while 1:217            evString = os.read(fd, struct.calcsize(_InputEventStructSpec))218            if not evString: break219            tim, tus, typ, cod, val = struct.unpack(_InputEventStructSpec, evString)220            if cod < len(InputKeys):221                nam = InputKeys[cod]222            else:223                nam = "N/A"224            print "time: %8s, susc: %8s, type: %8s, keyCode: %5s name: %10s value: %8s" % \225                (tim, tus, typ, cod, nam, val)226    finally:227        os.close(fd)228def printEventsFromDevice(deviceName):229    devices = dict(_listInputDevices())230    if not deviceName in devices:231        error('Unknown device "%s". Available devices: %s' %232              (deviceName, sorted(devices.keys())))233    else:234        printEventsFromFile(devices[deviceName])235def _exitHandler():236    shutil.rmtree(_g_tempdir, ignore_errors=True)237atexit.register(_exitHandler)238def _runcmd(cmd):239    p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)240    output = p.stdout.read()241    exit_status = p.wait()242    if p.wait() != 0:243        _log("runcmd: " + cmd)244        _log("exit status: " + str(exit_status))245        _log("stdout: " + output)246        _log("stderr: " + p.stderr.read())247    else:248        p.stderr.read()249    return exit_status, output250def _runDrawCmd(inputfilename, cmd, outputfilename):251    if not _g_defaultDelayedDrawing:252        return _runcmd("convert %s %s %s" % (inputfilename, cmd, outputfilename))253    # Do delayed drawing to save test execution time. If the output254    # file does not exist, just copy inputfile to outputfile and start255    # logging delayed draw commands to256    # outputfile.delayeddraw. Otherwise append latest command to257    # outputfile.delayeddraw.258    delayedCmd = "convert %s %s %s\n" % (outputfilename, cmd, outputfilename)259    delayedDrawFilename = outputfilename + ".delayeddraw"260    try:261        if os.access(outputfilename, os.R_OK) == False:262                shutil.copy(inputfilename, outputfilename)263                file(delayedDrawFilename, "w").write(delayedCmd)264        else:265            file(delayedDrawFilename, "a").write(delayedCmd)266    except:267        _log("error on delayed drawing: %s" % (delayedCmd,))268        raise269    _log("delayed drawing: %s" % (delayedCmd,))270    return (0, "")271def _safeForShell(s):272    # convert all non-ascii and bad chars to _273    try: s = unicode(s, "utf-8")274    except: pass275    return ''.join([(c, "_")[ord(c)>128 or c in "'\"\\`"] for c in s])276def _coordsToInt((x,y), (width, height)=(None, None)):277    """278    Convert percentages to screen coordinates279    """280    if (width == None or height == None):281        width, height = screenSize()282    if 0.0 <= x <= 1.0 and type(x) == float:283        x = int(round(x * width))284    else:285        x = int(x)286    if 0.0 <= y <= 1.0 and type(y) == float:287        y = int(round(y * height))288    else:289        y = int(y)290    return (x, y)291def setPreprocessFilter(preprocess):292    global _g_preprocess293    _g_preprocess = preprocess294def iSetDefaultClickDryRun(dryRun):295    """296    Set the default value for optional dryRun parameter for iClick*297    functions.298    """299    global _g_defaultClickDryRun300    _g_defaultClickDryRun = dryRun301def iSetDefaultDelayedDrawing(delayedDrawing):302    """303    Set the default for delaying drawing operations on captured304    screenshots.305    If delayedDrawing == False, drawing actions on screenshots (like306    highlighting icon and clicked coordinates) takes place during the307    function execution (like iClickIcon).308    If delayedDrawing == True, the screenshot is saved without309    highlighted areas, and <screenshot filename>.delayeddraw file310    contains all draw commands that can be executed after the test311    run. This may save a lot test execution time and CPU on the device312    that runs eyenfinger.313    The default is False.314    """315    global _g_defaultDelayedDrawing316    _g_defaultDelayedDrawing = delayedDrawing317def iSetDefaultIconMatch(match):318    """319    Set the default icon matching value, ranging from 0 to 1. The320    value will be used in iClickIcon and iVerifyIcon, if the optional321    match parameter is omitted. Value 1.0 will use pixel-perfect322    matching (the default), values below 1.0 will use fuzzy matching.323    Fuzzy matching is EXPERIMENTAL.324    """325    global _g_defaultIconMatch326    _g_defaultIconMatch = match327def iSetDefaultIconColorMatch(colorMatch):328    """329    Set the default color matching value, ranging from 0 to 1. When330    using pixel-perfect matching this will allow given error in pixel331    colors.332    For instance, when comparing 24 bit RGB images, value 0.97 will333    allow 256 - int(256 * .97) = 8 difference on each color channel.334    """335    global _g_defaultIconColorMatch336    _g_defaultIconColorMatch = colorMatch337def iSetDefaultIconOpacityLimit(opacityLimit):338    """339    Set the default minimum opacity for pixels to be matched. Defaults340    to 0.0, all pixels are matched independently of their opacity.341    """342    global _g_defaultIconOpacityLimit343    _g_defaultIconOpacityLimit = opacityLimit344def iSetDefaultInputKeyDevice(deviceName):345    """346    Use deviceName as a default input device for iInputKey.347    iSetDefaultInputKeyDevice("/dev/input/event0")348    iInputKey(["enter"])349    """350    global _g_defaultInputKeyDevice351    _g_defaultInputKeyDevice = deviceName352def iSetDefaultReadWithOCR(ocr):353    """354    Set the default for using OCR when reading images or windows.355    """356    global _g_defaultReadWithOCR357    _g_defaultReadWithOCR = ocr358def screenSize():359    """360    Returns the size of the screen as a pair (width, height).361    """362    if _g_screenSize == (0, 0):363        _getScreenSize()364    return _g_screenSize365def windowSize():366    """367    Returns the size of the window as a pair (width, height).368    Choose a window first, for instance with iRead() or iUseWindow().369    """370    if _g_lastWindow == None:371        raise BadWindowName("undefined window")372    return _g_windowSizes[_g_lastWindow]373def windowXY():374    """375    Returns screen coordinates of the top-left corner of the window as376    a pair (x, y).377    Choose a window first, for instance with iRead() or iUseWindow().378    """379    if _g_lastWindow == None:380        raise BadWindowName("undefined window")381    return _g_windowOffsets[_g_lastWindow]382def imageSize(imageFilename):383    """384    Returns image size as pair (width, height).385    """386    struct_bbox = Bbox(0,0,0,0,0)387    err = eye4graphics.imageDimensions(ctypes.byref(struct_bbox),388                                       imageFilename)389    if err != 0:390        return None, None391    return struct_bbox.right, struct_bbox.bottom392def iRead(windowId = None, source = None, preprocess = None, ocr=None, capture=None, ocrArea=(0, 0, 1.0, 1.0), ocrPageSegModes=(3,)):393    """394    DEPRECATED - use fmbtx11.Screen.refreshScreenshot instead.395    Read the contents of the given window or other source. If neither396    of windowId or source is given, reads the contents of active397    window. iClickWord and iVerifyWord can be used after reading with398    OCR.399    Parameters:400        windowId     id (0x....) or the title of the window to be read.401                     Defaults to None.402        source       name of the file to be read, for instance a screen403                     capture. Defaults to None.404        preprocess   preprocess specification to override the default405                     that is set using setPreprocessFilter. Defaults406                     to None. Set to "" to disable preprocessing before407                     OCR.408        ocr          words will be read using OCR if True409                     (the default). Read object can be used with410                     iClickIcon and iVerifyIcon without OCR, too.411        capture      save image with read words highlighted to this412                     file. Default: None (nothing is saved).413        ocrArea      (top, left, right, bottom) coordinates -414                     area of the image to be read with OCR.415        ocrPageSegModes416                     tuple of integers, see tesseract -pagesegmodes417    Returns list of words detected by OCR from the read object.418    """419    global _g_hocr420    global _g_lastWindow421    global _g_words422    global _g_readImage423    global _g_origImage424    _g_words = None425    _g_readImage = None426    _g_origImage = None427    if ocr == None:428        ocr = _g_defaultReadWithOCR429    if not source:430        iUseWindow(windowId)431        # take a screenshot432        _runcmd("xwd -root -screen -out %s.xwd && convert %s.xwd -crop %sx%s+%s+%s +repage '%s'" %433               (SCREENSHOT_FILENAME, SCREENSHOT_FILENAME,434                _g_windowSizes[_g_lastWindow][0], _g_windowSizes[_g_lastWindow][1],435                _g_windowOffsets[_g_lastWindow][0], _g_windowOffsets[_g_lastWindow][1],436                SCREENSHOT_FILENAME))437        source = SCREENSHOT_FILENAME438    else:439        iUseImageAsWindow(source)440    _g_origImage = source441    orig_width, orig_height = _g_windowSizes[_g_lastWindow][0], _g_windowSizes[_g_lastWindow][1]442    x1, y1 = _coordsToInt(ocrArea[:2], (orig_width, orig_height))443    x2, y2 = _coordsToInt(ocrArea[2:], (orig_width, orig_height))444    if x2 <= x1 or y2 <= y1:445        raise EyenfingerError("Invalid area size: %s => %s" % (ocrArea, (x1, y1, x2, y2)))446    if orig_width <= 0 or orig_height <= 0:447        raise EyenfingerError("Invalid image size: %sx%s" % (orig_width, orig_height))448    if not ocr:449        if capture:450            drawWords(_g_origImage, capture, [], [])451        return []452    if preprocess == None:453        preprocess = _g_preprocess454    # convert to text455    _g_readImage = _g_origImage + "-pp.png"456    if ocrArea == (0, 0, 1.0, 1.0):457        croparea = ""458        wordXOffset = 0459        wordYOffset = 0460    else:461        croparea = "-crop %sx%s+%s+%s +repage" % (x2-x1, y2-y1, x1, y1)462        wordXOffset = x1463        wordYOffset = y1464        # rescale possible resize preprocessing parameter465        resize_m = re.search('-resize ([0-9]+)x([0-9]*)', preprocess)466        if resize_m:467            origXResize = int(resize_m.group(1))468            newXResize = int(origXResize/float(orig_width) * (x2-x1))469            preprocess = (preprocess[:resize_m.start()] +470                          ("-resize %sx" % (newXResize,)) +471                          preprocess[resize_m.end():])472    _g_words = {}473    for psm in ocrPageSegModes:474        cmd = "convert %s %s %s %s && tesseract %s %s -l eng -psm %s hocr" % (475                _g_origImage, croparea, preprocess, _g_readImage,476                _g_readImage, SCREENSHOT_FILENAME, psm)477        _, _g_hocr = _runcmd(cmd)478        hocr_filename = SCREENSHOT_FILENAME + ".html"479        if not os.access(hocr_filename, os.R_OK):480            raise NoOCRResults("HOCR output missing. Tesseract OCR 3.02 or greater required.")481        # store every word and its coordinates482        _g_words.update(_hocr2words(file(hocr_filename).read()))483    # convert word coordinates to the unscaled pixmap484    try:485        ocr_page_line = [line for line in file(hocr_filename).readlines() if "class='ocr_page'" in line][0]486    except IndexError:487        raise NoOCRResults("Could not read ocr_page class information from %s" % (hocr_filename,))488    scaled_width, scaled_height = re.findall('bbox 0 0 ([0-9]+)\s*([0-9]+)', ocr_page_line)[0]489    scaled_width, scaled_height = float(scaled_width) / (float(x2-x1)/orig_width), float(scaled_height) / (float(y2-y1)/orig_height)490    for word in sorted(_g_words.keys()):491        for appearance, (wordid, middle, bbox) in enumerate(_g_words[word]):492            _g_words[word][appearance] = \493                (wordid,494                 (int(middle[0]/scaled_width * orig_width) + wordXOffset,495                  int(middle[1]/scaled_height * orig_height) + wordYOffset),496                 (int(bbox[0]/scaled_width * orig_width) + wordXOffset,497                  int(bbox[1]/scaled_height * orig_height) + wordYOffset,498                  int(bbox[2]/scaled_width * orig_width) + wordXOffset,499                  int(bbox[3]/scaled_height * orig_height) + wordYOffset))500            _log('found "' + word + '": (' + str(bbox[0]) + ', ' + str(bbox[1]) + ')')501    if capture:502        drawWords(_g_origImage, capture, _g_words, _g_words)503    return sorted(_g_words.keys())504def iVerifyWord(word, match=0.33, appearance=1, capture=None):505    """506    DEPRECATED - use fmbtx11.Screen.verifyOcrText instead.507    Verify that word can be found from previously iRead() image.508    Parameters:509        word         word that should be checked510        appearance   if word appears many times, appearance to511                     be clicked. Defaults to the first one.512        match        minimum matching score513        capture      save image with verified word highlighted514                     to this file. Default: None (nothing is saved).515    Returns pair: ((score, matchingWord), (left, top, right, bottom)), where516        score        score of found match (1.0 for perfect match)517        matchingWord corresponding word detected by OCR518        (left, top, right, bottom)519                     bounding box of the word in read image520    Throws BadMatch error if word is not found.521    Throws NoOCRResults error if there are OCR results available522    on the current screen.523    """524    if _g_words == None:525        raise NoOCRResults('iRead has not been called with ocr=True')526    score, matching_word = findWord(word)527    if capture:528        drawWords(_g_origImage, capture, [word], _g_words)529    if score < match:530        raise BadMatch('No matching word for "%s". The best candidate "%s" with score %.2f, required %.2f' %531                            (word, matching_word, score, match))532    return ((score, matching_word), _g_words[matching_word][appearance-1][2])533def iVerifyText(text, match=0.33, capture=None):534    """535    DEPRECATED - use fmbtx11.Screen.verifyOcrText instead.536    Verify that text can be found from previously iRead() image.537    Parameters:538        text         multiple words that should be checked539        match        minimum matching score540        capture      save image with verified text highlighted541                     to this file. Default: None (nothing is saved).542    Returns pair:543        ((score, matchingText), (left, top, right, bottom)), where544        score        score of found match (1.0 for perfect match)545        matchingText corresponding text detected by OCR546        (left, top, right, bottom)547                     bounding box of the text in read image548    Throws BadMatch error if text is not found.549    Throws NoOCRResults error if there are OCR results available550    on the current screen.551    """552    if _g_words == None:553        raise NoOCRResults('iRead has not been called with ocr=True')554    score_text_bbox_list = findText(text, match)555    if len(score_text_bbox_list) == 0:556        raise BadMatch('No match >= %s for text "%s"' % (score, text))557    score, text, bbox = score_text_box_list[0]558    if capture:559        drawBbox(_g_origImage, capture, bbox, "%.2f %s" % (score, text))560    return ((score, matching_text), bbox)561def iVerifyIcon(iconFilename, match=None, colorMatch=None, opacityLimit=None, capture=None, area=(0.0, 0.0, 1.0, 1.0), _origin="iVerifyIcon"):562    """563    DEPRECATED - use fmbtx11.Screen.verifyBitmap instead.564    Verify that icon can be found from previously iRead() image.565    Parameters:566        iconFilename   name of the icon file to be searched for567        match          minimum matching score between 0 and 1.0,568                       1.0 is perfect match (default)569        colorMatch     1.0 (default) requires exact color match. Value570                       below 1.0 defines maximum allowed color571                       difference. See iSetDefaultIconColorMatch.572        opacityLimit   0.0 (default) requires exact color values573                       independently of opacity. If lower than 1.0,574                       pixel less opaque than given value are skipped575                       in pixel perfect comparisons.576        capture        save image with verified icon highlighted577                       to this file. Default: None (nothing is saved).578        area           rectangle (left, top, right, bottom). Search579                       icon inside this rectangle only. Values can be580                       absolute coordinates, or floats in range [0.0,581                       1.0] that will be scaled to image dimensions.582                       The default is (0.0, 0.0, 1.0, 1.0), that is583                       full rectangle.584    Returns pair: (score, (left, top, right, bottom)), where585        score          score of found match (1.0 for perfect match)586        (left, top, right, bottom)587                       bounding box of found icon588    Throws BadMatch error if icon is not found.589    """590    if not eye4graphics:591        _log('ERROR: %s("%s") called, but eye4graphics not loaded.' % (_origin, iconFilename))592        raise EyenfingerError("eye4graphics not available")593    if not _g_origImage:594        _log('ERROR %s("%s") called, but source not defined (iRead not called).' % (_origin, iconFilename))595        raise BadSourceImage("Source image not defined, cannot search for an icon.")596    if not (os.path.isfile(iconFilename) and os.access(iconFilename, os.R_OK)):597        _log('ERROR %s("%s") called, but the icon file is not readable.' % (_origin, iconFilename))598        raise BadIconImage('Icon "%s" is not readable.' % (iconFilename,))599    if match == None:600        match = _g_defaultIconMatch601    if match > 1.0:602        _log('ERROR %s("%s"): invalid match value, must be below 1.0. ' % (_origin, iconFilename,))603        raise ValueError("invalid match value: %s, should be 0 <= match <= 1.0" % (match,))604    if colorMatch == None:605        colorMatch = _g_defaultIconColorMatch606    if not 0.0 <= colorMatch <= 1.0:607        _log('ERROR %s("%s"): invalid colorMatch value, must be between 0 and 1. ' % (_origin, iconFilename,))608        raise ValueError("invalid colorMatch value: %s, should be 0 <= colorMatch <= 1.0" % (colorMatch,))609    if opacityLimit == None:610        opacityLimit = _g_defaultIconOpacityLimit611    if not 0.0 <= opacityLimit <= 1.0:612        _log('ERROR %s("%s"): invalid opacityLimit value, must be between 0 and 1. ' % (_origin, iconFilename,))613        raise ValueError("invalid opacityLimit value: %s, should be 0 <= opacityLimit <= 1.0" % (opacityLimit,))614    if area[0] > area[2] or area[1] >= area[3]:615        raise ValueError("invalid area: %s, should be rectangle (left, top, right, bottom)" % (area,))616    leftTopRightBottomZero = (_coordsToInt((area[0], area[1]), windowSize()) +617                               _coordsToInt((area[2], area[3]), windowSize()) +618                               (0,))619    struct_area_bbox = Bbox(*leftTopRightBottomZero)620    struct_bbox = Bbox(0,0,0,0,0)621    threshold = int((1.0-match)*20)622    err = eye4graphics.findSingleIcon(ctypes.byref(struct_bbox),623                                      _g_origImage, iconFilename, threshold,624                                      ctypes.c_double(colorMatch),625                                      ctypes.c_double(opacityLimit),626                                      ctypes.byref(struct_area_bbox))627    bbox = (int(struct_bbox.left), int(struct_bbox.top),628            int(struct_bbox.right), int(struct_bbox.bottom))629    if err == -1 or err == -2:630        msg = '%s: "%s" not found, match=%.2f, threshold=%s, closest threshold %s.' % (631            _origin, iconFilename, match, threshold, int(struct_bbox.error))632        if capture:633            drawIcon(_g_origImage, capture, iconFilename, bbox, 'red')634        _log(msg)635        raise BadMatch(msg)636    elif err != 0:637        _log("%s: findSingleIcon returned %s" % (_origin, err,))638        raise BadMatch("%s not found, findSingleIcon returned %s." % (iconFilename, err))639    if threshold > 0:640        score = (threshold - int(struct_bbox.error)) / float(threshold)641    else:642        score = 1.0643    if capture:644        drawIcon(_g_origImage, capture, iconFilename, bbox, area=leftTopRightBottomZero[:4])645    return (score, bbox)646def iClickIcon(iconFilename, clickPos=(0.5,0.5), match=None,647               colorMatch=None, opacityLimit=None,648               mouseButton=1, mouseEvent=MOUSEEVENT_CLICK, dryRun=None, capture=None):649    """650    DEPRECATED - use fmbtx11.Screen.tapBitmap instead.651    Click coordinates relative to the given icon in previously iRead() image.652    Parameters:653        iconFilename read icon from this file654        clickPos     position to be clicked,655                     relative to word top-left corner of the bounding656                     box around the word. X and Y units are relative657                     to width and height of the box.  (0,0) is the658                     top-left corner, (1,1) is bottom-right corner,659                     (0.5, 0.5) is the middle point (default).660                     Values below 0 or greater than 1 click outside661                     the bounding box.662        match        1.0 (default) requires exact match. Value below 1.0663                     defines minimum required score for fuzzy matching664                     (EXPERIMENTAL). See iSetDefaultIconMatch.665        colorMatch   1.0 (default) requires exact color match. Value666                     below 1.0 defines maximum allowed color667                     difference. See iSetDefaultIconColorMatch.668        opacityLimit 0.0 (default) requires exact color values669                     independently of opacity. If lower than 1.0,670                     pixel less opaque than given value are skipped671                     in pixel perfect comparisons.672        mouseButton  mouse button to be synthesized on the event, default is 1.673        mouseEvent   event to be synthesized, the default is MOUSEEVENT_CLICK,674                     others: MOUSEEVENT_MOVE, MOUSEEVENT_DOWN, MOUSEEVENT_UP.675        dryRun       if True, does not synthesize events. Still returns676                     coordinates of the clicked position and illustrates677                     the clicked position on the capture image if678                     given.679        capture      name of file where image of highlighted icon and680                     clicked point are saved.681    Returns pair (score, (clickedX, clickedY)), where682        score        score of found match (1.0 for perfect match)683        (clickedX, clickedY)684                     X and Y coordinates of clicked position on the685                     screen.686    Throws BadMatch error if could not find a matching word.687    """688    _DEPRECATED()689    score, bbox = iVerifyIcon(iconFilename, match=match,690                              colorMatch=colorMatch, opacityLimit=opacityLimit,691                              capture=capture, _origin="iClickIcon")692    clickedXY = iClickBox(bbox, clickPos, mouseButton, mouseEvent, dryRun,693                          capture, _captureText = iconFilename)694    return (score, clickedXY)695def iClickWord(word, appearance=1, clickPos=(0.5,0.5), match=0.33,696               mouseButton=1, mouseEvent=1, dryRun=None, capture=None):697    """698    DEPRECATED - use fmbtx11.Screen.tapOcrText instead.699    Click coordinates relative to the given word in previously iRead() image.700    Parameters:701        word         word that should be clicked702        appearance   if word appears many times, appearance to703                     be clicked. Defaults to the first one.704        clickPos     position to be clicked,705                     relative to word top-left corner of the bounding706                     box around the word. X and Y units are relative707                     to width and height of the box.  (0,0) is the708                     top-left corner, (1,1) is bottom-right corner,709                     (0.5, 0.5) is the middle point (default).710                     Values below 0 or greater than 1 click outside711                     the bounding box.712        capture      name of file where image of highlighted word and713                     clicked point are saved.714    Returns pair: ((score, matchingWord), (clickedX, clickedY)), where715        score        score of found match (1.0 for perfect match)716        matchingWord corresponding word detected by OCR717        (clickedX, clickedY)718                     X and Y coordinates of clicked position on the719                     screen.720    Throws BadMatch error if could not find a matching word.721    Throws NoOCRResults error if there are OCR results available722    on the current screen.723    """724    _DEPRECATED()725    (score, matching_word), bbox = iVerifyWord(word, appearance=appearance, match=match, capture=False)726    clickedX, clickedY = iClickBox(bbox, clickPos, mouseButton, mouseEvent, dryRun, capture=False)727    windowId = _g_lastWindow728    _log('iClickWord("%s"): word "%s", match %.2f, bbox %s, window offset %s, click %s' %729         (word, matching_word, score,730          bbox, _g_windowOffsets[windowId],731          (clickedX, clickedY)))732    if capture:733        drawWords(_g_origImage, capture, [word], _g_words)734        drawClickedPoint(capture, capture, (clickedX, clickedY))735    return ((score, matching_word), (clickedX, clickedY))736def iClickBox((left, top, right, bottom), clickPos=(0.5, 0.5),737              mouseButton=1, mouseEvent=1, dryRun=None,738              capture=None, _captureText=None):739    """740    DEPRECATED - use fmbtx11.Screen.tapItem instead.741    Click coordinates relative to the given bounding box, default is742    in the middle of the box.743    Parameters:744        (left, top, right, bottom)745                     coordinates of the box inside the window.746                     (0, 0) is the top-left corner of the window.747        clickPos     (offsetX, offsetY) position to be clicked,748                     relative to the given box. (0, 0) is the749                     top-left, and (1.0, 1.0) is the lower-right750                     corner of the box.  The default is (0.5, 0.5),751                     that is, the middle point of the box. Values752                     smaller than 0 and bigger than 1 are allowed,753                     too.754        mouseButton  mouse button to be synthesized on the event, default is 1.755        mouseEvent   event to be synthesized, the default is MOUSEEVENT_CLICK,756                     others: MOUSEEVENT_MOVE, MOUSEEVENT_DOWN, MOUSEEVENT_UP.757        dryRun       if True, does not synthesize events. Still returns758                     coordinates of the clicked position and illustrates759                     the clicked position on the capture image if760                     given.761        capture      name of file where the last screenshot with762                     clicked point highlighted is saved. The default763                     is None (nothing is saved).764    Returns pair (clickedX, clickedY)765                     X and Y coordinates of clicked position on the766                     screen.767    """768    clickWinX = int(left + clickPos[0]*(right-left))769    clickWinY = int(top + clickPos[1]*(bottom-top))770    (clickedX, clickedY) = iClickWindow((clickWinX, clickWinY),771                                        mouseButton, mouseEvent,772                                        dryRun, capture=False)773    if capture:774        if _captureText == None:775            _captureText = "Box: %s, %s, %s, %s" % (left, top, right, bottom)776        drawIcon(_g_origImage, capture, _captureText, (left, top, right, bottom))777        drawClickedPoint(capture, capture, (clickedX, clickedY))778    return (clickedX, clickedY)779def iClickWindow((clickX, clickY), mouseButton=1, mouseEvent=1, dryRun=None, capture=None):780    """781    DEPRECATED - use fmbtx11.Screen.tap instead.782    Click given coordinates in the window.783    Parameters:784        (clickX, clickY)785                     coordinates to be clicked inside the window.786                     (0, 0) is the top-left corner of the window.787                     Integer values are window coordinates. Floating788                     point values from 0.0 to 1.0 are scaled to window789                     coordinates: (0.5, 0.5) is the middle of the790                     window, and (1.0, 1.0) the bottom-right corner of791                     the window.792        mouseButton  mouse button to be synthesized on the event, default is 1.793        mouseEvent   event to be synthesized, the default is MOUSEEVENT_CLICK,794                     others: MOUSEEVENT_MOVE, MOUSEEVENT_DOWN, MOUSEEVENT_UP.795        dryRun       if True, does not synthesize events. Still796                     illustrates the clicked position on the capture797                     image if given.798        capture      name of file where the last screenshot with799                     clicked point highlighted is saved. The default800                     is None (nothing is saved).801    Returns pair (clickedX, clickedY)802                     X and Y coordinates of clicked position on the803                     screen.804    """805    # Get the size of the window806    wndSize = windowSize()807    (clickX, clickY) = _coordsToInt((clickX, clickY), wndSize)808    # Get the position of the window809    wndPos = windowXY()810    # If coordinates are given as percentages, convert to window coordinates811    clickScrX = clickX + wndPos[0]812    clickScrY = clickY + wndPos[1]813    iClickScreen((clickScrX, clickScrY), mouseButton, mouseEvent, dryRun, capture)814    return (clickScrX, clickScrY)815def iClickScreen((clickX, clickY), mouseButton=1, mouseEvent=1, dryRun=None, capture=None):816    """817    DEPRECATED - use fmbtx11.Screen.tap instead.818    Click given absolute coordinates on the screen.819    Parameters:820        (clickX, clickY)821                     coordinates to be clicked on the screen. (0, 0)822                     is the top-left corner of the screen. Integer823                     values are screen coordinates. Floating point824                     values from 0.0 to 1.0 are scaled to screen825                     coordinates: (0.5, 0.5) is the middle of the826                     screen, and (1.0, 1.0) the bottom-right corner of827                     the screen.828        mouseButton  mouse button to be synthesized on the event, default is 1.829        mouseEvent   event to be synthesized, the default is MOUSEEVENT_CLICK,830                     others: MOUSEEVENT_MOVE, MOUSEEVENT_DOWN, MOUSEEVENT_UP.831        dryRun       if True, does not synthesize events. Still832                     illustrates the clicked position on the capture833                     image if given.834        capture      name of file where the last screenshot with835                     clicked point highlighted is saved. The default836                     is None (nothing is saved).837    """838    _DEPRECATED()839    if mouseEvent == MOUSEEVENT_CLICK:840        params = "'mouseclick %s'" % (mouseButton,)841    elif mouseEvent == MOUSEEVENT_DOWN:842        params = "'mousedown %s'" % (mouseButton,)843    elif mouseEvent == MOUSEEVENT_UP:844        params = "'mouseup %s'" % (mouseButton,)845    else:846        params = ""847    clickX, clickY = _coordsToInt((clickX, clickY))848    if capture:849        drawClickedPoint(_g_origImage, capture, (clickX, clickY))850    if dryRun == None:851        dryRun = _g_defaultClickDryRun852    if not dryRun:853        # use xte from the xautomation package854        _runcmd("xte 'mousemove %s %s' %s" % (clickX, clickY, params))855def iGestureScreen(listOfCoordinates, duration=0.5, holdBeforeGesture=0.0, holdAfterGesture=0.0, intermediatePoints=0, capture=None, dryRun=None):856    """857    DEPRECATED - use fmbtx11.Screen.drag instead.858    Synthesizes a gesture on the screen.859    Parameters:860        listOfCoordinates861                     The coordinates through which the cursor moves.862                     Integer values are screen coordinates. Floating863                     point values from 0.0 to 1.0 are scaled to screen864                     coordinates: (0.5, 0.5) is the middle of the865                     screen, and (1.0, 1.0) the bottom-right corner of866                     the screen.867        duration     gesture time in seconds, excluding868                     holdBeforeGesture and holdAfterGesture times.869        holdBeforeGesture870                     time in seconds to keep mouse down before the871                     gesture.872        holdAfterGesture873                     time in seconds to keep mouse down after the874                     gesture.875        intermediatePoints876                     the number of intermediate points to be added877                     between each of the coordinates. Intermediate878                     points are added to straight lines between start879                     and end points.880        capture      name of file where the last screenshot with881                     the points through which the cursors passes is882                     saved. The default is None (nothing is saved).883        dryRun       if True, does not synthesize events. Still884                     illustrates the coordinates through which the cursor885                     goes.886    """887    _DEPRECATED()888    # The params list to be fed to xte889    params = []890    # The list of coordinates through which the cursor has to go891    goThroughCoordinates = []892    for pos in xrange(len(listOfCoordinates)):893        x, y = _coordsToInt(listOfCoordinates[pos])894        goThroughCoordinates.append((x,y))895        if pos == len(listOfCoordinates) - 1:896            break # last coordinate added897        nextX, nextY = _coordsToInt(listOfCoordinates[pos+1])898        (x,y), (nextX, nextY) = (x, y), (nextX, nextY)899        for ip in range(intermediatePoints):900            goThroughCoordinates.append(901                (int(round(x + (nextX-x)*(ip+1)/float(intermediatePoints+1))),902                 int(round(y + (nextY-y)*(ip+1)/float(intermediatePoints+1)))))903    # Calculate the time (in micro seconds) to sleep between moves.904    if len(goThroughCoordinates) > 1:905        moveDelay = 1000000 * float(duration) / (len(goThroughCoordinates)-1)906    else:907        moveDelay = 0908    if not dryRun:909        # Build the params list.910        params.append("'mousemove %d %d'" % goThroughCoordinates[0])911        params.append("'mousedown 1 '")912        if holdBeforeGesture > 0:913            params.append("'usleep %d'" % (holdBeforeGesture * 1000000,))914        for i in xrange(1, len(goThroughCoordinates)):915            params.append("'usleep %d'" % (moveDelay,))916            params.append("'mousemove %d %d'" % goThroughCoordinates[i])917        if holdAfterGesture > 0:918            params.append("'usleep %d'" % (holdAfterGesture * 1000000,))919        params.append("'mouseup 1'")920        # Perform the gesture921        _runcmd("xte %s" % (" ".join(params),))922    if capture:923        intCoordinates = [ _coordsToInt(point) for point in listOfCoordinates ]924        drawLines(_g_origImage, capture, intCoordinates, goThroughCoordinates)925    return goThroughCoordinates926def iGestureWindow(listOfCoordinates, duration=0.5, holdBeforeGesture=0.0, holdAfterGesture=0.0, intermediatePoints=0, capture=None, dryRun=None):927    """928    DEPRECATED - use fmbtx11.Screen.drag instead.929    Synthesizes a gesture on the window.930    Parameters:931        listOfCoordinates932                     The coordinates through which the cursor moves.933                     Integer values are window coordinates. Floating934                     point values from 0.0 to 1.0 are scaled to window935                     coordinates: (0.5, 0.5) is the middle of the936                     window, and (1.0, 1.0) the bottom-right corner of937                     the window.938        duration     gesture time in seconds, excluding939                     holdBeforeGesture and holdAfterGesture times.940        holdBeforeGesture941                     time in seconds to keep mouse down before the942                     gesture.943        holdAfterGesture944                     time in seconds to keep mouse down after the945                     gesture.946        intermediatePoints947                     the number of intermediate points to be added948                     between each of the coordinates. Intermediate949                     points are added to straight lines between start950                     and end points.951        capture      name of file where the last screenshot with952                     the points through which the cursors passes is953                     saved. The default is None (nothing is saved).954        dryRun       if True, does not synthesize events. Still955                     illustrates the coordinates through which the cursor956                     goes.957    """958    screenCoordinates = [ _windowToScreen(*_coordsToInt((x,y),windowSize())) for (x,y) in listOfCoordinates ]959    return iGestureScreen(screenCoordinates, duration, holdBeforeGesture, holdAfterGesture, intermediatePoints, capture, dryRun)960def iType(word, delay=0.0):961    """962    DEPRECATED - use fmbtx11.Screen.type instead.963    Send keypress events.964    Parameters:965        word is either966            - a string containing letters and numbers.967              Each letter/number is using press and release events.968            - a list that contains969              - keys: each key is sent using press and release events.970              - (key, event)-pairs: the event (either "press" or "release")971                is sent.972              - (key1, key2, ..., keyn)-tuples. 2n events is sent:973                key1 press, key2 press, ..., keyn press,974                keyn release, ..., key2 release, key1 release.975            Keys are defined in eyenfinger.Xkeys, for complete list976            see keysymdef.h.977        delay is given as seconds between sent events978    Examples:979        iType('hello')980        iType([('Shift_L', 'press'), 'h', 'e', ('Shift_L', 'release'), 'l', 'l', 'o'])981        iType([('Control_L', 'Alt_L', 'Delete')])982    """983    _DEPRECATED()984    args = []985    for char in word:986        if type(char) == tuple:987            if char[1].lower() == 'press':988                args.append("'keydown %s'" % (char[0],))989            elif char[1].lower() == 'release':990                args.append("'keyup %s'" % (char[0],))991            else:992                rest = []993                for key in char:994                    args.append("'keydown %s'" % (key,))995                    rest.insert(0, "'keyup %s'" % (key,))996                args = args + rest997        else:998            # char is keyname or single letter/number999            args.append("'key %s'" % (char,))1000    usdelay = " 'usleep %s' " % (int(delay*1000000),)1001    _runcmd("xte %s" % (usdelay.join(args),))1002def iInputKey(*args, **kwargs):1003    """1004    DEPRECATED - use fmbtx11.Screen.pressKey instead.1005    Send keypresses using Linux evdev interface1006    (/dev/input/eventXX).1007    iInputKey(keySpec[, keySpec...], hold=<float>, delay=<float>, device=<str>)1008    Parameters:1009        keySpec      is one of the following:1010                     - a string of one-character-long key names:1011                       "aesc" will send four keypresses: A, E, S and C.1012                     - a list of key names:1013                       ["a", "esc"] will send two keypresses: A and ESC.1014                       Key names are listed in eyenfinger.InputKeys.1015                     - an integer:1016                       116 will press the POWER key.1017                     - "_" or "^":1018                       only press or release event will be generated1019                       for the next key, respectively.1020                     If a key name inside keySpec is prefixed by "_"1021                     or "^", only press or release event is generated1022                     for that key.1023        hold         time (in seconds) to hold the key before1024                     releasing. The default is 0.1.1025        delay        delay (in seconds) after key release. The default1026                     is 0.1.1027        device       name of the input device or input event file to1028                     which all key presses are sent. The default can1029                     be set with iSetDefaultInputKeyDevice().  For1030                     instance, "/dev/input/event0" or a name of a1031                     device in /proc/bus/input/devices.1032    """1033    _DEPRECATED()1034    hold = kwargs.get("hold", 0.1)1035    delay = kwargs.get("delay", 0.1)1036    device = kwargs.get("device", _g_defaultInputKeyDevice)1037    inputKeySeq = []1038    press, release = 1, 11039    for a in args:1040        if a == "_": press, release = 1, 01041        elif a == "^": press, release = 0, 11042        elif type(a) == str:1043            for char in a:1044                if char == "_": press, release = 1, 01045                elif char == "^": press, release = 0, 11046                else:1047                    inputKeySeq.append((press, release, _inputKeyNameToCode(char.upper())))1048                    press, release = 1, 11049        elif type(a) in (tuple, list):1050            for keySpec in a:1051                if type(keySpec) == int:1052                    inputKeySeq.append((press, release, keySpec))1053                    press, release = 1, 11054                else:1055                    if keySpec.startswith("_"):1056                        press, release = 1, 01057                        keySpec = keySpec[1:]1058                    elif keySpec.startswith("^"):1059                        press, release = 0, 11060                        keySpec = keySpec[1:]1061                    if keySpec:1062                        inputKeySeq.append((press, release, _inputKeyNameToCode(keySpec.upper())))1063                        press, release = 1, 11064        elif type(a) == int:1065            inputKeySeq.append((press, release, a))1066            press, release = 1, 11067        else:1068            raise ValueError('Invalid keySpec "%s"' % (a,))1069    if inputKeySeq:1070        _writeInputKeySeq(_deviceFilename(device), inputKeySeq, hold=hold, delay=delay)1071def _deviceFilename(deviceName):1072    if not _deviceFilename.deviceCache:1073        _deviceFilename.deviceCache = dict(_listInputDevices())1074    if not deviceName in _deviceFilename.deviceCache:1075        return deviceName1076    else:1077        return _deviceFilename.deviceCache[deviceName]1078_deviceFilename.deviceCache = {}1079def _listInputDevices():1080    nameAndFile = []1081    for l in file("/proc/bus/input/devices"):1082        if l.startswith("N: Name="):1083            nameAndFile.append([l.split('"')[1]])1084        elif l.startswith("H: Handlers=") and "event" in l:1085            try:1086                eventFilename = re.findall("(event[0-9]+)", l)[0]1087                nameAndFile[-1].append("/dev/input/%s" % (eventFilename,))1088            except:1089                _log('WARNING: Could not recognise event[0-9] filename from row "%s".' % (l.strip(),))1090    return nameAndFile1091def _writeInputKeySeq(filename, keyCodeSeq, hold=0.1, delay=0.1):1092    if type(filename) != str or len(filename) == 0:1093        raise ValueError('Invalid input device "%s"' % (filename,))1094    fd = os.open(filename, os.O_WRONLY | os.O_NONBLOCK)1095    for press, release, keyCode in keyCodeSeq:1096        if press:1097            bytes = os.write(fd, struct.pack(_InputEventStructSpec,1098                                             int(time.time()), 0, _EV_KEY, keyCode, 1))1099            if bytes > 0:1100                bytes += os.write(fd, struct.pack(_InputEventStructSpec,1101                                                  0, 0, 0, 0, 0))1102            time.sleep(hold)1103        if release:1104            bytes += os.write(fd, struct.pack(_InputEventStructSpec,1105                                              int(time.time()), 0, _EV_KEY, keyCode, 0))1106            if bytes > 0:1107                bytes += os.write(fd, struct.pack(_InputEventStructSpec,1108                                                  0, 0, 0, 0, 0))1109            time.sleep(delay)1110    os.close(fd)1111def findWord(word, detected_words = None, appearance=1):1112    """1113    Returns pair (score, corresponding-detected-word)1114    """1115    if detected_words == None:1116        detected_words = _g_words1117        if _g_words == None:1118            raise NoOCRResults()1119    scored_words = []1120    for w in detected_words:1121        scored_words.append((_score(w, word), w))1122    scored_words.sort()1123    if len(scored_words) == 0:1124        raise BadMatch("No words found.")1125    return scored_words[-1]1126def findText(text, detected_words = None, match=-1):1127    def biggerBox(bbox_list):1128        left, top, right, bottom = bbox_list[0]1129        for l, t, r, b in bbox_list[1:]:1130            left = min(left, l)1131            top = min(top, t)1132            right = max(right, r)1133            bottom = max(bottom, b)1134        return (left, top, right, bottom)1135    words = text.split()1136    word_count = len(words)1137    detected_texts = [] # strings of <word_count> words1138    if detected_words == None:1139        detected_words = _g_words1140        if _g_words == None:1141            raise NoOCRResults()1142    # sort by numeric word id1143    words_by_id = []1144    for word in detected_words:1145        for wid, middle, bbox in detected_words[word]:1146            words_by_id.append(1147                (int(wid.split("_")[1]), word, bbox))1148    words_by_id.sort()1149    for i in xrange(len(words_by_id)-word_count+1):1150        detected_texts.append(1151            (" ".join([w[1] for w in words_by_id[i:i+word_count]]),1152             biggerBox([w[2] for w in words_by_id[i:i+word_count]])))1153    norm_text = " ".join(words) # normalize whitespace1154    scored_texts = []1155    for t in detected_texts:1156        scored_texts.append((_score(t[0], norm_text), t[0], t[1]))1157    scored_texts.sort()1158    return [st for st in scored_texts if st[0] >= match]1159def _score(w1, w2):1160    closeMatch = {1161        '1l': 0.1,1162        '1I': 0.2,1163        'Il': 0.21164        }1165    def levenshteinDistance(w1, w2):1166        m = [range(len(w1)+1)]1167        for j in xrange(len(w2)+1):1168            m.append([])1169            m[-1].append(j+1)1170        i, j = 0, 01171        for j in xrange(1, len(w2)+1):1172            for i in xrange(1, len(w1)+1):1173                if w1[i-1] == w2[j-1]:1174                    m[j].append(m[j-1][i-1])1175                else:1176                    # This is not part of Levenshtein:1177                    # if characters often look similar,1178                    # don't add full edit distance (1.0),1179                    # use the value in closeMatch instead.1180                    chars = ''.join(sorted(w1[i-1] + w2[j-1]))1181                    if chars in closeMatch:1182                        m[j].append(m[j-1][i-1]+closeMatch[chars])1183                    else:1184                        # Standard Levenshtein continues...1185                        m[j].append(min(1186                                m[j-1][i] + 1,  # delete1187                                m[j][i-1] + 1,  # insert1188                                m[j-1][i-1] + 1 # substitute1189                                ))1190        return m[j][i]1191    return 1 - (levenshteinDistance(w1, w2) / float(max(len(w1),len(w2))))1192def _hocr2words(hocr):1193    rv = {}1194    hocr = hocr.replace("<strong>","").replace("</strong>","").replace("<em>","").replace("</em>","")1195    hocr.replace("'", "'")1196    for name, code in htmlentitydefs.name2codepoint.iteritems():1197        if code < 128:1198            hocr = hocr.replace('&' + name + ';', chr(code))1199    ocr_word = re.compile('''<span class=['"]ocrx?_word["'] id=['"]([^']*)["'] title=['"]bbox ([0-9]+) ([0-9]+) ([0-9]+) ([0-9]+)["'][^>]*>([^<]*)</span>''')1200    for word_id, bbox_left, bbox_top, bbox_right, bbox_bottom, word in ocr_word.findall(hocr):1201        bbox_left, bbox_top, bbox_right, bbox_bottom = \1202            int(bbox_left), int(bbox_top), int(bbox_right), int(bbox_bottom)1203        if not word in rv:1204            rv[word] = []1205        middle_x = (bbox_right + bbox_left) / 2.01206        middle_y = (bbox_top + bbox_bottom) / 2.01207        rv[word].append((word_id, (middle_x, middle_y),1208                         (bbox_left, bbox_top, bbox_right, bbox_bottom)))1209    return rv1210def _getScreenSize():1211    global _g_screenSize1212    _, output = _runcmd("xwininfo -root | awk '/Width:/{w=$NF}/Height:/{h=$NF}END{print w\" \"h}'")1213    s_width, s_height = output.split(" ")1214    _g_screenSize = (int(s_width), int(s_height))1215def iUseWindow(windowIdOrName = None):1216    global _g_lastWindow1217    if windowIdOrName == None:1218        if _g_lastWindow == None:1219            _g_lastWindow = iActiveWindow()1220    elif windowIdOrName.startswith("0x"):1221        _g_lastWindow = windowIdOrName1222    else:1223        _g_lastWindow = _runcmd("xwininfo -name '%s' | awk '/Window id: 0x/{print $4}'" %1224                              (windowIdOrName,))[1].strip()1225        if not _g_lastWindow.startswith("0x"):1226            raise BadWindowName('Cannot find window id for "%s" (got: "%s")' %1227                                (windowIdOrName, _g_lastWindow))1228    _, output = _runcmd("xwininfo -id %s | awk '/Width:/{w=$NF}/Height:/{h=$NF}/Absolute upper-left X/{x=$NF}/Absolute upper-left Y/{y=$NF}END{print x\" \"y\" \"w\" \"h}'" %1229                       (_g_lastWindow,))1230    offset_x, offset_y, width, height = output.split(" ")1231    _g_windowOffsets[_g_lastWindow] = (int(offset_x), int(offset_y))1232    _g_windowSizes[_g_lastWindow] = (int(width), int(height))1233    _getScreenSize()1234    return _g_lastWindow1235def iUseImageAsWindow(imageFilename):1236    global _g_lastWindow1237    global _g_screenSize1238    if not eye4graphics:1239        _log('ERROR: iUseImageAsWindow("%s") called, but eye4graphics not loaded.' % (imageFilename,))1240        raise EyenfingerError("eye4graphics not available")1241    if not os.access(imageFilename, os.R_OK):1242        raise BadSourceImage("The input file could not be read or not present.")1243    _g_lastWindow = imageFilename1244    imageWidth, imageHeight = imageSize(imageFilename)1245    if imageWidth == None:1246        _log('iUseImageAsWindow: Failed reading dimensions of image "%s".' % (imageFilename,))1247        raise BadSourceImage('Failed to read dimensions of "%s".' % (imageFilename,))1248    _g_windowOffsets[_g_lastWindow] = (0, 0)1249    _g_windowSizes[_g_lastWindow] = (imageWidth, imageHeight)1250    _g_screenSize = _g_windowSizes[_g_lastWindow]1251    return _g_lastWindow1252def iActiveWindow(windowId = None):1253    """ return id of active window, in '0x1d0f14' format """1254    if windowId == None:1255        _, output = _runcmd("xprop -root | awk '/_NET_ACTIVE_WINDOW\(WINDOW\)/{print $NF}'")1256        windowId = output.strip()1257    return windowId1258def drawBbox(inputfilename, outputfilename, bbox, caption):1259    """1260    Draw bounding box1261    """1262    if inputfilename == None:1263        return1264    draw_commands = ""1265    left, top, right, bottom = bbox1266    color = "green"1267    draw_commands += """ -stroke %s -fill blue -draw "fill-opacity 0.2 rectangle %s,%s %s,%s" """ % (1268        color, left, top, right, bottom)1269    draw_commands += """ -stroke none -fill %s -draw "text %s,%s '%s'" """ % (1270        color, left, top, _safeForShell(caption))1271    _runDrawCmd(inputfilename, draw_commands, outputfilename)1272def drawWords(inputfilename, outputfilename, words, detected_words):1273    """1274    Draw boxes around words detected in inputfilename that match to1275    given words. Result is saved to outputfilename.1276    """1277    if inputfilename == None:1278        return1279    draw_commands = ""1280    for w in words:1281        score, dw = findWord(w, detected_words)1282        left, top, right, bottom = detected_words[dw][0][2]1283        if score < 0.33:1284            color = "red"1285        elif score < 0.5:1286            color = "brown"1287        else:1288            color = "green"1289        draw_commands += """ -stroke %s -fill blue -draw "fill-opacity 0.2 rectangle %s,%s %s,%s" """ % (1290            color, left, top, right, bottom)1291        draw_commands += """ -stroke none -fill %s -draw "text %s,%s '%s'" """ % (1292            color, left, top, _safeForShell(w))1293        draw_commands += """ -stroke none -fill %s -draw "text %s,%s '%.2f'" """ % (1294            color, left, bottom+10, score)1295    _runDrawCmd(inputfilename, draw_commands, outputfilename)1296def drawIcon(inputfilename, outputfilename, iconFilename, bboxes, color='green', area=None):1297    if inputfilename == None:1298        return1299    if type(bboxes) == tuple:1300        bboxes = [bboxes]1301        show_number = False1302    else:1303        show_number = True1304    draw_commands = ""1305    for index, bbox in enumerate(bboxes):1306        left, top, right, bottom = bbox[0], bbox[1], bbox[2], bbox[3]1307        draw_commands += """ -stroke %s -fill blue -draw "fill-opacity 0.2 rectangle %s,%s %s,%s" """ % (color, left, top, right, bottom)1308        if show_number:1309            caption = "%s %s" % (index+1, iconFilename)1310        else:1311            caption = iconFilename1312        draw_commands += """ -stroke none -fill %s -draw "text %s,%s '%s'" """ % (1313            color, left, top, caption)1314    if area != None:1315        draw_commands += """ -stroke yellow -draw "fill-opacity 0.0 rectangle %s,%s %s,%s" """ % (area[0]-1, area[1]-1, area[2], area[3])1316    _runDrawCmd(inputfilename, draw_commands, outputfilename)1317def drawClickedPoint(inputfilename, outputfilename, clickedXY):1318    """1319    clickedXY contains absolute screen coordinates1320    """1321    if inputfilename == None:1322        return1323    x, y = clickedXY1324    x -= _g_windowOffsets[_g_lastWindow][0]1325    y -= _g_windowOffsets[_g_lastWindow][1]1326    draw_commands = """ -stroke red -fill blue -draw "fill-opacity 0.2 circle %s,%s %s,%s" """ % (1327        x, y, x + 20, y)1328    draw_commands += """ -stroke none -fill red -draw "point %s,%s" """ % (x, y)1329    _runDrawCmd(inputfilename, draw_commands, outputfilename)1330def _screenToWindow(x,y):1331    """1332    Converts from absolute coordinats to window coordinates1333    """1334    offsetX = _g_windowOffsets[_g_lastWindow][0]1335    offsetY = _g_windowOffsets[_g_lastWindow][1]1336    return (x-offsetX, y-offsetY)1337def _windowToScreen(x,y):1338    """1339    Converts from window coordinates to screen coordinates1340    """1341    offsetX = _g_windowOffsets[_g_lastWindow][0]1342    offsetY = _g_windowOffsets[_g_lastWindow][1]1343    return (x+offsetX, y+offsetY)1344def drawLines(inputfilename, outputfilename, orig_coordinates, final_coordinates):1345    """1346    coordinates contains the coordinates connected by lines1347    """1348    if inputfilename == None:1349        return1350    # The command which will be run1351    drawCommand = ''1352    for pos in xrange(len(final_coordinates)-1):1353        # Get the pair coordinates1354        (x, y) = (final_coordinates[pos][0], final_coordinates[pos][1])1355        (nextX, nextY) = (final_coordinates[pos+1][0], final_coordinates[pos+1][1])1356        # Convert to window coordinates1357        (drawX, drawY) = _screenToWindow(x,y)1358        (drawnextX, drawnextY) = _screenToWindow(nextX, nextY)1359        # Draw a pair of circles. User-given points are blue1360        if (x, y) in orig_coordinates:1361            drawCommand +=  "-fill blue -stroke red -draw 'fill-opacity 0.2 circle %d, %d %d, %d' " % (drawX, drawY, drawX-5, drawY-5)1362        # Computer-generated points are white1363        else:1364            drawCommand +=  "-fill white -stroke red -draw 'fill-opacity 0.2 circle %d, %d %d, %d' " % (drawX, drawY, drawX-5, drawY-5)1365        # Draw the line between the points1366        drawCommand += "-stroke black -draw 'line %d, %d, %d, %d' " % (drawX, drawY, drawnextX, drawnextY)1367    if len(final_coordinates) > 0:1368        lastIndex = len(final_coordinates)-11369        (finalX, finalY) = _screenToWindow(final_coordinates[lastIndex][0], final_coordinates[lastIndex][1])1370        drawCommand +=  "-fill blue -stroke red -draw 'fill-opacity 0.2 circle %d, %d %d, %d' " % (finalX, finalY, finalX-5, finalY-5)1371    _runDrawCmd(inputfilename, drawCommand, outputfilename)1372def evaluatePreprocessFilter(imageFilename, ppfilter, words):1373    """1374    Visualise how given words are detected from given image file when1375    using given preprocessing filter.1376    """1377    global _g_preprocess1378    evaluatePreprocessFilter.count += 11379    preprocessed_filename = '%s-pre%s.png' % (imageFilename, evaluatePreprocessFilter.count)1380    _runcmd("convert '%s' %s '%s' && tesseract %s eyenfinger.autoconfigure hocr" %1381           (imageFilename, ppfilter, preprocessed_filename,1382            preprocessed_filename))1383    detected_words = _hocr2words(file("eyenfinger.autoconfigure.html").read())1384    scored_words = []1385    for w in words:1386        try:1387            score, word = findWord(w, detected_words)1388        except BadMatch:1389            return1390        scored_words.append((score, word, w))1391    scored_words.sort()1392    avg_score = sum([s[0] for s in scored_words])/float(len(scored_words))1393    evaluatePreprocessFilter.scores.append( (scored_words[0][0] + avg_score, scored_words[0][0], avg_score, ppfilter) )1394    evaluatePreprocessFilter.scores.sort()1395    # set the best preprocess filter so far as a default1396    _g_preprocess = evaluatePreprocessFilter.scores[-1][-1]1397    drawWords(preprocessed_filename, preprocessed_filename, words, detected_words)1398    sys.stdout.write("%.2f %s %s %s\n" % (sum([s[0] for s in scored_words])/float(len(scored_words)), scored_words[0], preprocessed_filename, ppfilter))1399    sys.stdout.flush()1400evaluatePreprocessFilter.count = 01401evaluatePreprocessFilter.scores = []1402def autoconfigure(imageFilename, words):1403    """1404    Search for image preprocessing configuration that will maximise1405    the score of finding given words in the image.1406    Returns configuration as a string.1407    """1408    # check image width1409    iUseImageAsWindow(imageFilename)1410    image_width = _g_windowSizes[_g_lastWindow][0]1411    resize_filters = ['Mitchell', 'Catrom', 'Hermite', 'Gaussian']1412    levels = [(20, 20), (50, 50), (80, 80), (5, 5), (95, 95),1413              (30, 30), (40, 40), (60, 60), (70, 70), (60, 60),1414              (10, 30), (30, 50), (50, 70), (70, 90), (80, 100)]1415    zoom = [1, 2]1416    for f in resize_filters:1417        for z in zoom:1418            for blevel, wlevel in levels:1419                evaluatePreprocessFilter(1420                    imageFilename,1421                    "-sharpen 5 -level %s%%,%s%%,3.0 -sharpen 5" % (blevel, wlevel),1422                    words)1423                evaluatePreprocessFilter(1424                    imageFilename,1425                    "-sharpen 5 -filter %s -resize %sx -sharpen 5 -level %s%%,%s%%,3.0 -sharpen 5" % (f, z * image_width, blevel, wlevel),1426                    words)1427                evaluatePreprocessFilter(1428                    imageFilename,1429                    "-sharpen 5 -filter %s -resize %sx -level %s%%,%s%%,3.0 -sharpen 5" % (1430                        f, z * image_width, blevel, wlevel),1431                    words)1432                evaluatePreprocessFilter(1433                    imageFilename,1434                    "-sharpen 5 -filter %s -resize %sx -level %s%%,%s%%,3.0" % (1435                        f, z * image_width, blevel, wlevel),1436                    words)1437                evaluatePreprocessFilter(1438                    imageFilename,1439                    "-sharpen 5 -level %s%%,%s%%,3.0 -filter %s -resize %sx -sharpen 5" % (1440                        blevel, wlevel, f, z * image_width),1441                    words)1442                evaluatePreprocessFilter(1443                    imageFilename,1444                    "-sharpen 5 -level %s%%,%s%%,1.0 -filter %s -resize %sx" % (1445                        blevel, wlevel, f, z * image_width),1446                    words)1447                evaluatePreprocessFilter(1448                    imageFilename,1449                    "-sharpen 5 -level %s%%,%s%%,10.0 -filter %s -resize %sx" % (1450                        blevel, wlevel, f, z * image_width),...Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
