def find(image_name, precision=None, in_region=None): """Look for a single match of a Pattern or image :param image_name: String or Pattern :param precision: Matching similarity :param in_region: Region object in order to minimize the area :return: Location """ if isinstance(image_name, str) and is_ocr_text(image_name): a_match = text_search_by(image_name, True, in_region) if a_match is not None: return Location(a_match['x'] + a_match['width'] / 2, a_match['y'] + a_match['height'] / 2) else: raise FindError('Unable to find text %s' % image_name) elif isinstance(image_name, str) or isinstance(image_name, Pattern): if precision is None: precision = Settings.MinSimilarity try: pattern = Pattern(image_name) except Exception: pattern = image_name image_found = image_search(pattern, precision, in_region) if (image_found.x != -1) & (image_found.y != -1): return image_found else: raise FindError('Unable to find image %s' % image_name) else: raise ValueError(INVALID_GENERIC_INPUT)
def find(image_name, region=None): """Look for a single match of a Pattern or image. :param image_name: String or Pattern. :param region: Region object in order to minimize the area. :return: Location object. """ if isinstance(image_name, Pattern): image_found = image_search(image_name, region) if (image_found.x != -1) & (image_found.y != -1): if parse_args().highlight: highlight(region=region, pattern=image_name, location=image_found) return image_found else: raise FindError('Unable to find image %s' % image_name.get_filename()) elif isinstance(image_name, str): a_match = text_search_by(image_name, True, region) if a_match is not None: return Location(a_match['x'] + a_match['width'] / 2, a_match['y'] + a_match['height'] / 2) else: raise FindError('Unable to find text %s' % image_name) else: raise ValueError(INVALID_GENERIC_INPUT)
def wait(image_name, timeout=None, region=None): """Wait for a Pattern or image to appear. :param image_name: String or Pattern. :param timeout: Number as maximum waiting time in seconds. :param region: Region object in order to minimize the area. :return: True if found. """ if isinstance(image_name, Pattern): if timeout is None: timeout = Settings.auto_wait_timeout image_found = positive_image_search(image_name, timeout, region) if image_found is not None: if parse_args().highlight: highlight(region=region, pattern=image_name, location=image_found) return True else: raise FindError('Unable to find image %s' % image_name.get_filename()) elif isinstance(image_name, str): a_match = text_search_by(image_name, True, region) if a_match is not None: return True else: raise FindError('Unable to find text %s' % image_name) else: raise ValueError(INVALID_GENERIC_INPUT)
def paste(text): """ :param text: Text to be pasted. :return: None. """ # Load text to clipboard. pyperclip.copy(text) text_copied = False wait_scan_rate = float(Settings.wait_scan_rate) interval = 1 / wait_scan_rate max_attempts = int(Settings.auto_wait_timeout * wait_scan_rate) attempt = 0 while not text_copied and attempt < max_attempts: if pyperclip.paste() == text: text_copied = True else: time.sleep(interval) attempt += 1 if not text_copied: raise FindError('Paste method failed.') if Settings.get_os() == Platform.MAC: type(text='v', modifier=KeyModifier.CMD) else: type(text='v', modifier=KeyModifier.CTRL) # Clear clipboard. pyperclip.copy('')
def find_all(what, in_region=None): """Look for multiple matches of a Pattern or image. :param what: String or Pattern. :param in_region: Region object in order to minimize the area. :return: List[Location]. """ if isinstance(what, Pattern): return image_search_multiple(what, in_region) elif isinstance(what, str): ocr_search = OCRSearch() all_matches = ocr_search.text_search_by(what, True, in_region, True) list_of_locations = [] for match in all_matches: list_of_locations.append( Location(match['x'] + match['width'] / 2, match['y'] + match['height'] / 2)) if len(list_of_locations) > 0: return list_of_locations else: raise FindError('Unable to find text %s' % what) else: raise ValueError(INVALID_GENERIC_INPUT)
def _click_pattern(pattern, clicks=None, duration=None, in_region=None, button=None): """Click on center or offset of a Pattern. :param pattern: Input Pattern. :param clicks: Number of mouse clicks. :param duration: Speed of hovering from current location to target. :param in_region: Region object in order to minimize the area. :param button: Mouse button clicked (can be left, right, middle, 1, 2, 3). :return: None. """ if duration is None: duration = Settings.move_mouse_delay width, height = pattern.get_size() p_top = positive_image_search(pattern=pattern, region=in_region) if p_top is None: raise FindError('Unable to click on: %s' % pattern.get_file_path()) possible_offset = pattern.get_target_offset() if possible_offset is not None: _click_at( Location(p_top.x + possible_offset.x, p_top.y + possible_offset.y), clicks, duration, button) else: _click_at(Location(p_top.x + width / 2, p_top.y + height / 2), clicks, duration, button)
def findAll(what, precision=None, in_region=None): """Look for multiple matches of a Pattern or image :param what: String or Pattern :param precision: Matching similarity :param in_region: Region object in order to minimize the area :return: """ if isinstance(what, str) and is_ocr_text(what): all_matches = text_search_by(what, True, in_region, True) list_of_locations = [] for match in all_matches: list_of_locations.append( Location(match['x'] + match['width'] / 2, match['y'] + match['height'] / 2)) if len(list_of_locations) > 0: return list_of_locations else: raise FindError('Unable to find text %s' % what) elif isinstance(what, str) or isinstance(what, Pattern): try: pattern = Pattern(what) except Exception: pattern = what if precision is None: precision = Settings.MinSimilarity return image_search_multiple(pattern, precision, in_region) else: raise ValueError(INVALID_GENERIC_INPUT)
def hover(where=None, duration=0, in_region=None): """Hover over a Location, Pattern or image :param where: Location, Pattern or image name for hover target :param duration: speed of hovering from current location to target :param in_region: Region object in order to minimize the area :return: None """ if isinstance(where, str) and is_ocr_text(where): a_match = text_search_by(where, True, in_region) if a_match is not None: pyautogui.moveTo(a_match['x'] + a_match['width'] / 2, a_match['y'] + a_match['height'] / 2) else: raise FindError('Unable to find text %s' % where) elif isinstance(where, Location): pyautogui.moveTo(where.x, where.y, duration) elif isinstance(where, str) or isinstance(where, Pattern): try: pattern = Pattern(where) except Exception: pattern = where pos = image_search(pattern, region=in_region) if pos.x != -1: needle_width, needle_height = get_image_size(pattern.getFilename()) if isinstance(where, Pattern): possible_offset = where.getTargetOffset() if possible_offset is not None: move_to = Location(pos.getX() + possible_offset.getX(), pos.getY() + possible_offset.getY()) pyautogui.moveTo(move_to.getX(), move_to.y) else: move_to = Location(pos.x, pos.y) pyautogui.moveTo(move_to.getX() + needle_width / 2, move_to.getY() + needle_height / 2) else: pyautogui.moveTo(pos.x + needle_width / 2, pos.y + needle_height / 2) else: raise FindError('Unable to find image %s' % pattern.getFilename()) else: raise ValueError(INVALID_GENERIC_INPUT)
def hover(where=None, duration=0, in_region=None): """Hover over a Location, Pattern or image. :param where: Location, Pattern or image name for hover target. :param duration: Speed of hovering from current location to target. :param in_region: Region object in order to minimize the area. :return: None. """ if isinstance(where, Pattern): pos = image_search(where, region=in_region) if pos.x != -1: needle_width, needle_height = where.get_size() if isinstance(where, Pattern): possible_offset = where.get_target_offset() if possible_offset is not None: move_to = Location(pos.x + possible_offset.x, pos.y + possible_offset.y) pyautogui.moveTo(move_to.x, move_to.y) else: move_to = Location(pos.x, pos.y) pyautogui.moveTo(move_to.x + needle_width / 2, move_to.y + needle_height / 2) else: pyautogui.moveTo(pos.x + needle_width / 2, pos.y + needle_height / 2) else: raise FindError('Unable to find image %s' % where.get_filename()) elif isinstance(where, str): ocr_search = OCRSearch() a_match = ocr_search.text_search_by(where, True, in_region) if a_match is not None: pyautogui.moveTo(a_match['x'] + a_match['width'] / 2, a_match['y'] + a_match['height'] / 2) else: raise FindError('Unable to find text %s' % where) elif isinstance(where, Location): pyautogui.moveTo(where.x, where.y, duration) else: raise ValueError(INVALID_GENERIC_INPUT)
def wait(image_name, timeout=None, precision=None, in_region=None): """Wait for a Pattern or image to appear :param image_name: String or Pattern :param timeout: Number as maximum waiting time in seconds. :param precision: Matching similarity :param in_region: Region object in order to minimize the area :return: True if found """ if isinstance(image_name, str) and is_ocr_text(image_name): a_match = text_search_by(image_name, True, in_region) if a_match is not None: return True else: raise FindError('Unable to find text %s' % image_name) elif isinstance(image_name, str) or isinstance(image_name, Pattern): if timeout is None: timeout = Settings.AutoWaitTimeout if precision is None: precision = Settings.MinSimilarity try: pattern = Pattern(image_name) except Exception: pattern = image_name image_found = positive_image_search(pattern, timeout, precision, in_region) if image_found is not None: return True else: raise FindError('Unable to find image %s' % image_name) else: raise ValueError(INVALID_GENERIC_INPUT)
def wait_vanish(pattern, timeout=None, in_region=None): """Wait until a Pattern disappears. :param pattern: Pattern. :param timeout: Number as maximum waiting time in seconds. :param in_region: Region object in order to minimize the area. :return: True if vanished. """ if timeout is None: timeout = Settings.auto_wait_timeout image_found = negative_image_search(pattern, timeout, in_region) if image_found is not None: return True else: raise FindError('%s did not vanish' % pattern.get_filename())
def _mouse_press_release(where=None, action=None, button=None, in_region=None): """Mouse press/release. :param where: Location , image name or Pattern. :param action: 'press' or 'release'. :param button: 'left','right' or 'middle'. :param in_region: Region object in order to minimize the area. :return: None. """ if isinstance(where, Pattern): needle = cv2.imread(where.get_file_path()) height, width, channels = needle.shape p_top = positive_image_search(pattern=where, region=in_region) if p_top is None: raise FindError('Unable to click on: %s' % where.get_file_path()) possible_offset = where.get_target_offset() if possible_offset is not None: location = Location(p_top.x + possible_offset.x, p_top.y + possible_offset.y) pyautogui.moveTo(location.x, location.y) if action == 'press': pyautogui.mouseDown(location.x, location.y, button) elif action == 'release': pyautogui.mouseUp(location.x, location.y, button) else: location = Location(p_top.x + width / 2, p_top.y + height / 2) pyautogui.moveTo(location.x, location.y) if action == 'press': pyautogui.mouseDown(location.x, location.y, button) elif action == 'release': pyautogui.mouseUp(location.x, location.y, button) elif isinstance(where, str): mouse = Controller() ocr_search = OCRSearch() a_match = ocr_search.text_search_by(where, True, in_region) if a_match is not None: location = Location(a_match['x'] + a_match['width'] / 2, a_match['y'] + a_match['height'] / 2) mouse.move(location.x, location.y) if action == 'press': mouse.press(button) elif mouse == 'release': mouse.release(button)
def waitVanish(image_name, timeout=None, precision=None, in_region=None): """Wait until a Pattern or image disappears :param image_name: Image, Pattern or string :param timeout: Number as maximum waiting time in seconds. :param precision: Matching similarity :param in_region: Region object in order to minimize the area :return: True if vanished """ if timeout is None: timeout = Settings.AutoWaitTimeout if precision is None: precision = Settings.MinSimilarity pattern = Pattern(image_name) image_found = negative_image_search(pattern, timeout, precision, in_region) if image_found is not None: return True else: raise FindError('%s did not vanish' % image_name)
def _click_pattern(pattern, clicks=None, duration=None, in_region=None, button=None): """Click on center or offset of a Pattern :param pattern: Input Pattern :param clicks: Number of mouse clicks :param duration: Speed of hovering from current location to target :param in_region: Region object in order to minimize the area :param button: Mouse button clicked (can be left, right, middle, 1, 2, 3) :return: None """ if duration is None: duration = Settings.MoveMouseDelay needle = cv2.imread(pattern.image_path) height, width, channels = needle.shape p_top = positive_image_search(pattern=pattern, precision=Settings.MinSimilarity, region=in_region) if p_top is None: raise FindError('Unable to click on: %s' % pattern.image_path) possible_offset = pattern.getTargetOffset() if possible_offset is not None: _click_at( Location(p_top.x + possible_offset.x, p_top.y + possible_offset.y), clicks, duration, button) else: _click_at(Location(p_top.x + width / 2, p_top.y + height / 2), clicks, duration, button)
def generate_region_by_markers(top_left_marker_img=None, bottom_right_marker_img=None): """Generate a region starting from 2 markers. :param top_left_marker_img: Top left pattern used to generate the region. :param bottom_right_marker_img: Bottom right pattern used to generate the region. :return: Screen region generated. """ try: wait(top_left_marker_img, 10) exists(bottom_right_marker_img, 10) except FindError: raise FindError('Unable to find page markers.') top_left_pos = find(top_left_marker_img) hover(top_left_pos, 0) bottom_right_pos = find(bottom_right_marker_img) hover(bottom_right_pos, 0) marker_width, marker_height = get_image_size(bottom_right_marker_img) return Region(top_left_pos.x, top_left_pos.y, (bottom_right_pos.x + marker_width), bottom_right_pos.y - top_left_pos.y + marker_height)
def _get_image_path(caller, image): """Enforce proper location for all Pattern creation. :param caller: Path of calling Python module. :param image: String filename of image. :return: Full path to image on disk. """ module = os.path.split(caller)[1] module_directory = os.path.split(caller)[0] parent_directory = os.path.basename(module_directory) file_name = image.split('.')[0] names = [ image, '*****@*****.**' % file_name, '*****@*****.**' % file_name, '*****@*****.**' % file_name ] # We will look at all possible paths relative to the calling file, with this priority: # # - current platform locale folder # - common locale folder # - current platform root # - common root # # Each directory is scanned for four possible file names, depending on resolution. # If the above fails, we will look up the file name in the list of project-wide images, # and return whatever we find, with a warning message. # If we find nothing, we will raise an exception. if Settings.get_os_version() == 'win7': os_version = 'win7' else: os_version = Settings.get_os() paths = [] current_locale = parse_args().locale platform_directory = os.path.join(module_directory, 'images', os_version) platform_locale_directory = os.path.join(platform_directory, current_locale) for name in names: paths.append(os.path.join(platform_locale_directory, name)) common_directory = os.path.join(module_directory, 'images', 'common') common_locale_directory = os.path.join(common_directory, current_locale) for name in names: paths.append(os.path.join(common_locale_directory, name)) for name in names: paths.append(os.path.join(platform_directory, name)) for name in names: paths.append(os.path.join(common_directory, name)) found = False image_path = None for path in paths: if os.path.exists(path): found = True image_path = path break if found: logger.debug('Module %s requests image %s' % (module, image)) logger.debug('Found %s' % image_path) return image_path else: # If not found in correct location, fall back to global image search for now. result_list = filter(lambda x: x['name'] == image, _load_all_patterns()) if len(result_list) > 0: res = result_list[0] logger.warning( 'Failed to find image %s in default locations for module %s.' % (image, module)) logger.warning('Using this one instead: %s' % res['path']) logger.warning( 'Please move image to correct location relative to caller.') location_1 = os.path.join(parent_directory, 'images', 'common') location_2 = os.path.join(parent_directory, IrisCore.get_images_path()) logger.warning('Suggested locations: %s, %s' % (location_1, location_2)) return res['path'] else: logger.error('Pattern creation for %s failed for caller %s.' % (image, caller)) logger.error( 'Image not found. Either it is in the wrong platform folder, or it does not exist.' ) logger.debug('Paths searched:') logger.debug('\n'.join(paths)) raise FindError('Pattern not found.')
def create_region_from_patterns(top=None, bottom=None, left=None, right=None, padding_top=None, padding_bottom=None, padding_left=None, padding_right=None): """Returns a region created from combined area of one or more patterns. Argument names are just for convenience and don't influence outcome. :param top: Top pattern used to generate the region. :param bottom: Bottom pattern used to generate the region. :param left: Left pattern used to generate the region. :param right: Right pattern used to generate the region. :param padding_top: Padding to be added to the pattern's top. :param padding_bottom: Padding to be added to the pattern's bottom. :param padding_left: Padding to be added to the pattern's left. :param padding_right: Padding to be added to the pattern's right. :return: region created from combined area of one or more patterns. """ patterns = [] if top: patterns.append(top) if bottom: patterns.append(bottom) if left: patterns.append(left) if right: patterns.append(right) if len(patterns) == 0: raise ValueError('One or more patterns required.') logger.debug('Creating region from %s pattern(s).' % len(patterns)) a, b = pyautogui.size() p1 = Location(a, b) p2 = Location(0, 0) for pattern in patterns: if exists(pattern, 5): current_pattern = find(pattern) if current_pattern.x < p1.x: p1.x = current_pattern.x if current_pattern.y < p1.y: p1.y = current_pattern.y w, h = get_image_size(pattern) if current_pattern.x + w > p2.x: p2.x = current_pattern.x + w if current_pattern.y + h > p2.y: p2.y = current_pattern.y + h else: raise FindError('Pattern not found: %s ' % pattern) found_region = Region(p1.x, p1.y, p2.x - p1.x, p2.y - p1.y) if padding_top or padding_bottom or padding_left or padding_right: logger.debug('Adding padding to region.') if padding_top: found_region.y -= padding_top found_region.height += padding_top if padding_bottom: found_region.height += padding_bottom if padding_left: found_region.x -= padding_left found_region.width += padding_left if padding_right: found_region.width += padding_right return found_region