[PYTHON] Rendre pyautogui [super-approprié] compatible avec l'environnement multi-affichage Partie2

Article précédent: Rendre pyautogui [super-approprié] compatible avec les environnements multi-écrans Part1

Objectif

Je veux passer les coordonnées obtenues par pyautogui.locateOnScreen () à pyautogui.click () telles quelles.

environnement

python 3.8.5 pyautogui 0.9.50 pyscreez 0.1.26 Windows OS uniquement win32api Ce qui précède ne peut pas être installé à partir de pip, vous devez donc télécharger et installer celui qui convient à votre environnement à partir du lien.

Enquête

La plupart des fonctions de type LocateOnXXX () appellent LocateOnScreen (), modifiez donc cette fonction.


def locateOnScreen(image, minSearchTime=0, **kwargs):
    """TODO - rewrite this
    minSearchTime - amount of time in seconds to repeat taking
    screenshots and trying to locate a match.  The default of 0 performs
    a single search.
    """
    start = time.time()
    while True:
        try:
            screenshotIm = screenshot(region=None) # the locateAll() function must handle cropping to return accurate coordinates, so don't pass a region here.
            retVal = locate(image, screenshotIm, **kwargs)
            try:
                screenshotIm.fp.close()
            except AttributeError:
                # Screenshots on Windows won't have an fp since they came from
                # ImageGrab, not a file. Screenshots on Linux will have fp set
                # to None since the file has been unlinked
                pass
            if retVal or time.time() - start > minSearchTime:
                return retVal
        except ImageNotFoundException:
            if time.time() - start > minSearchTime:
                if USE_IMAGE_NOT_FOUND_EXCEPTION:
                    raise
                else:
                    return None

Détails d'implémentation

Importer win32api

Tout endroit où la plate-forme est déterminée comme win32 à l'emplacement d'importation convient. Je l'ai écrit dans la première 25e ligne et après.

    from PIL import Image
    from PIL import ImageOps
    from PIL import ImageDraw
    if sys.platform == 'win32': # TODO - Pillow now supports ImageGrab on macOS.
 Importation # win32api ajoutée
        import win32api
        from PIL import ImageGrab
    _PILLOW_UNAVAILABLE = False

Correction de LocateOnScreen ()

Étant donné que les coordonnées et les valeurs de gauche, haut, largeur et hauteur qui correspondent à la reconnaissance d'image sont stockées dans retVal, le contenu de retVal est réécrit un peu avant de revenir en tant que valeur de retour.


def locateOnScreen(image, minSearchTime=0, **kwargs):
    """TODO - rewrite this
    minSearchTime - amount of time in seconds to repeat taking
    screenshots and trying to locate a match.  The default of 0 performs
    a single search.
    """
    start = time.time()
    while True:
        try:
            screenshotIm = screenshot(region=None) # the locateAll() function must handle cropping to return accurate coordinates, so don't pass a region here.
            retVal = locate(image, screenshotIm, **kwargs)
 # d'ici
            if not(retVal == None) and sys.platform == 'win32':
                displays = win32api.EnumDisplayMonitors()
                left_min = min([display[2][0] for display in displays])
                top_min = min([display[2][1] for display in displays])
                retVal = Box(
                    left = retVal[0] + left_min,
                    top = retVal[1] + top_min,
                    width = retVal[2],
                    height = retVal[3]
                )
 #Additions jusqu'à ici
            try:
                screenshotIm.fp.close()
            except AttributeError:
                # Screenshots on Windows won't have an fp since they came from
                # ImageGrab, not a file. Screenshots on Linux will have fp set
                # to None since the file has been unlinked
                pass
            if retVal or time.time() - start > minSearchTime:
                return retVal
        except ImageNotFoundException:
            if time.time() - start > minSearchTime:
                if USE_IMAGE_NOT_FOUND_EXCEPTION:
                    raise
                else:
                    return None

Confirmation du contenu de modification de _screenshot_win32 ()

Vérifiez également _screenshot_win32 () modifié dans Article précédent au cas où.

def _screenshot_win32(imageFilename=None, region=None):
    """
    TODO
    """

    # TODO - Use the winapi to get a screenshot, and compare performance with ImageGrab.grab()
    # https://stackoverflow.com/a/3586280/1893164
    #im = ImageGrab.grab()
    im = ImageGrab.grab(all_screens=True)

    if region is not None:
        assert len(region) == 4, 'region argument must be a tuple of four ints'
        region = [int(x) for x in region]
        im = im.crop((region[0], region[1], region[2] + region[0], region[3] + region[1]))
    if imageFilename is not None:
        im.save(imageFilename)
    return im

résultat

Les coordonnées obtenues par pyautogui.locateOnScreen () peuvent désormais être utilisées par pyautogui.click ().

problème

La vitesse de reconnaissance d'image ralentit

Bien sûr, c'est naturel, mais s'il y en a deux, la taille de l'image sera doublée, et s'il y en a trois, la taille de l'image sera triplée, donc la vitesse de reconnaissance d'image diminuera proportionnellement. Mon impression personnelle est que pyautogui ne prend pas officiellement en charge le multi-affichage à cause de ce problème de vitesse.

Affecte les autres packages qui font référence à pyscreez

Je ne sais pas s'il existe d'autres packages auxquels je fais référence, mais je ne peux pas dire qu'il n'y a pas d'impact sur l'environnement actuel à cause de la réécriture directe. Utilisons-le simplement dans un environnement de jeu, même si vous faites une erreur, ce n'est pas quelque chose à faire dans l'environnement système important actuellement en fonctionnement. Je ne pense pas qu'une telle personne existe.

finalement

Le problème du ralentissement étant important, on en conclut que la modification qui peut spécifier un affichage spécifique est plus réaliste pour le fonctionnement que tous les écrans.

C'est pourquoi il convenait parfaitement au multi-affichage. Si j'ai du temps libre, j'aimerais aussi essayer celui-là.

Recommended Posts

Rendre pyautogui [super-approprié] compatible avec l'environnement multi-affichage Partie2
Rendre pyautogui [super-approprié] compatible avec l'environnement multi-affichage Partie 1
Rendre le serveur de contrôle PLEN compatible avec ViVi PLEN2
[Python] Rendons matplotlib compatible avec le japonais
Conversion de l'environnement Django en Docker (Docker + Django + Gunicorn + nginx) Partie 2
Conversion de l'environnement Django en Docker (Docker + Django + Gunicorn + nginx) Partie 3
Comment faire un jeu de tir avec toio (partie 1)
Application Web réalisée avec Python3.4 + Django (Construction de l'environnement Part.1)