[PYTHON] Machen Sie pyautogui [super-geeignet] kompatibel mit Multi-Display-Umgebung Teil2

Vorheriger Artikel: Pyautogui [super-geeignet] mit Umgebungen mit mehreren Anzeigen kompatibel machen Teil 1

Zweck

Ich möchte die von pyautogui.locateOnScreen () erhaltenen Koordinaten unverändert an pyautogui.click () übergeben.

Umgebung

python 3.8.5 pyautogui 0.9.50 pyscreez 0.1.26 Nur Betriebssystemfenster win32api Die oben genannten Funktionen können nicht über pip installiert werden. Sie müssen daher die für Ihre Umgebung geeignete Datei über den Link herunterladen und installieren.

Umfrage

Die meisten Funktionen vom Typ locateOnXXX () rufen locateOnScreen () auf. Ändern Sie daher diese Funktion.


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

Implementierungsdetails

Win32api importieren

Jeder Ort, an dem die Plattform am Importort als win32 bestimmt wird, ist in Ordnung. Ich habe es in der ersten 25. Zeile und danach geschrieben.

    from PIL import Image
    from PIL import ImageOps
    from PIL import ImageDraw
    if sys.platform == 'win32': # TODO - Pillow now supports ImageGrab on macOS.
 # Win32api Import hinzugefügt
        import win32api
        from PIL import ImageGrab
    _PILLOW_UNAVAILABLE = False

Fix locateOnScreen ()

Da die Koordinaten und Werte von left, top, width und height, die mit der Bilderkennung übereinstimmen, in retVal gespeichert sind, wird der Inhalt von retVal ein wenig umgeschrieben, bevor er als Rückgabewert zurückgegeben wird.


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)
 # von hier
            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]
                )
 #Zusätze bis hierher
            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

Bestätigung des Änderungsinhalts von _screenshot_win32 ()

Überprüfen Sie auch _screenshot_win32 (), das in Vorheriger Artikel für alle Fälle geändert wurde.

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

Ergebnis

Die von pyautogui.locateOnScreen () erhaltenen Koordinaten können jetzt von pyautogui.click () verwendet werden.

Problem

Die Bilderkennungsgeschwindigkeit verlangsamt sich

Natürlich ist es natürlich, aber wenn es zwei gibt, wird die Bildgröße verdoppelt, und wenn es drei gibt, wird die Bildgröße verdreifacht, so dass die Bilderkennungsgeschwindigkeit proportional dazu abnimmt. Mein persönlicher Eindruck ist, dass Pyautogui aufgrund dieses Geschwindigkeitsproblems Multi-Display offiziell nicht unterstützt.

Betrifft andere Pakete, die auf pyscreez verweisen

Ich weiß nicht, ob es andere Pakete gibt, auf die ich verweise, aber ich kann nicht sagen, dass es aufgrund des direkten Umschreibens keine Auswirkungen auf die aktuelle Umgebung gibt. Verwenden wir es einfach in einer Spielumgebung, auch wenn Sie einen Fehler machen, ist es in der wichtigen Systemumgebung, die derzeit in Betrieb ist, nicht zu tun. Ich glaube nicht, dass es so eine Person gibt.

Schließlich

Da das Problem der Verlangsamung groß ist, ist die Schlussfolgerung, dass es für den Betrieb realistischer ist, es so zu ändern, dass eine bestimmte Anzeige anstelle aller Bildschirme angegeben werden kann.

Deshalb war es super für Multi-Display geeignet. Wenn ich Freizeit habe, würde ich das auch gerne ausprobieren.

Recommended Posts

Machen Sie pyautogui [super-geeignet] kompatibel mit Multi-Display-Umgebung Teil2
Machen Sie pyautogui [super-geeignet] kompatibel mit der Multi-Display-Umgebung Teil1
Machen Sie PLEN Control Server kompatibel mit ViVi PLEN2
[Python] Lassen Sie uns matplotlib mit Japanisch kompatibel machen
Konvertieren der Django-Umgebung in Docker (Docker + Django + Gunicorn + Nginx) Teil 2
Konvertieren der Django-Umgebung in Docker (Docker + Django + Gunicorn + Nginx) Teil 3
Wie man ein Schießspiel mit toio macht (Teil 1)
Webanwendung erstellt mit Python3.4 + Django (Teil.1 Umgebungskonstruktion)