如何在Python中快速定位屏幕上的某些内容?

问题描述 投票:0回答:4

我尝试使用 pyautogui 模块和我在屏幕上定位图像的功能

pyautogui.locateOnScreen()

但是它的处理时间大约是5-10秒。有没有其他方法可以让我更快地在屏幕上找到图像?基本上,我想要一个更快版本的locateOnScreen()。

python image python-3.x image-processing pyautogui
4个回答
13
投票

官方文档说在1920x1080屏幕上应该需要1-2秒。你的时间似乎有点慢。我会尝试通过执行以下操作来优化代码:

  • 除非需要考虑颜色信息,否则请使用灰度(包括
    grayscale=True
    应将速度提高约 30%)。
  • 使用较小的图像进行检测(仅要求所需目标的一部分是唯一的并识别目标的位置)。
  • 搜索目标时不要从本地存储加载标识符图像,将其保留在内存中。
  • 如果您知道或可以预测其可能的位置(例如,根据之前的运行),则传入区域参数。

上面链接的文档中对此进行了全部描述。

如果这仍然不够快,您可以检查pyautogui的来源,看到“在屏幕上定位”使用了在Python中实现的特定算法(Knuth-Morris-Pratt搜索算法)。用 C 实现这部分可能会带来相当明显的加速。


3
投票

创建一个函数并使用线程置信度(需要opencv)

import pyautogui
import threading

def locate_cat():
    cat=None
    while cat is None:
        cat = pyautogui.locateOnScreen('Pictures/cat.png',confidence=.65,region=(1722,748, 200,450)
        return cat

如果您知道屏幕上的大致位置,则可以使用区域参数

在某些情况下,您可以在屏幕上找到并将区域分配给变量,并使用region=somevar作为参数,这样它看起来就在上次找到的同一位置,以帮助加快检测过程。

例如:

import pyautogui

def first_find():
    front_door = None
    while front_door is None:
        front_door_save=pyautogui.locateOnScreen('frontdoor.png',confidence=.95,region=1722,748, 200,450)
        front_door=front_door_save
        return front_door_save


def second_find():
    front_door=None
    while front_door is None:
        front_door = pyautogui.locateOnScreen('frontdoor.png',confidence=.95,region=front_door_save)
        return front_door

def find_person():
    person=None
    while person is None:
        person= pyautogui.locateOnScreen('person.png',confidence=.95,region=front_door)


while True:
    first_find()
    second_find()
    if front_door is None:
        pass
    if front_door is not None:
        find_person()

2
投票

我在 pyautogui 中遇到了同样的问题。虽然它是一个非常方便的图书馆,但速度相当慢。

依靠 cv2 和 PIL,我获得了 10 倍的加速:

def benchmark_opencv_pil(method):
    img = ImageGrab.grab(bbox=REGION)
    img_cv = cv.cvtColor(np.array(img), cv.COLOR_RGB2BGR)
    res = cv.matchTemplate(img_cv, GAME_OVER_PICTURE_CV, method)
    # print(res)
    return (res >= 0.8).any()

使用 TM_CCOEFF_NORMED 效果很好。 (显然,0.8阈值也可以调整)

来源:使用Python快速定位OnScreen

为了完整起见,这里是完整的基准:

import pyautogui as pg
import numpy as np
import cv2 as cv
from PIL import ImageGrab, Image
import time

REGION = (0, 0, 400, 400)
GAME_OVER_PICTURE_PIL = Image.open("./balloon_fight_game_over.png")
GAME_OVER_PICTURE_CV = cv.imread('./balloon_fight_game_over.png')


def timing(f):
    def wrap(*args, **kwargs):
        time1 = time.time()
        ret = f(*args, **kwargs)
        time2 = time.time()
        print('{:s} function took {:.3f} ms'.format(
            f.__name__, (time2-time1)*1000.0))

        return ret
    return wrap


@timing
def benchmark_pyautogui():
    res = pg.locateOnScreen(GAME_OVER_PICTURE_PIL,
                            grayscale=True,  # should provied a speed up
                            confidence=0.8,
                            region=REGION)
    return res is not None


@timing
def benchmark_opencv_pil(method):
    img = ImageGrab.grab(bbox=REGION)
    img_cv = cv.cvtColor(np.array(img), cv.COLOR_RGB2BGR)
    res = cv.matchTemplate(img_cv, GAME_OVER_PICTURE_CV, method)
    # print(res)
    return (res >= 0.8).any()


if __name__ == "__main__":

    im_pyautogui = benchmark_pyautogui()
    print(im_pyautogui)

    methods = ['cv.TM_CCOEFF', 'cv.TM_CCOEFF_NORMED', 'cv.TM_CCORR',
               'cv.TM_CCORR_NORMED', 'cv.TM_SQDIFF', 'cv.TM_SQDIFF_NORMED']


    # cv.TM_CCOEFF_NORMED actually seems to be the most relevant method
    for method in methods:
        print(method)
        im_opencv = benchmark_opencv_pil(eval(method))
        print(im_opencv)

结果显示提高了 10 倍。

benchmark_pyautogui function took 175.712 ms
False
cv.TM_CCOEFF
benchmark_opencv_pil function took 21.283 ms
True
cv.TM_CCOEFF_NORMED
benchmark_opencv_pil function took 23.377 ms
False
cv.TM_CCORR
benchmark_opencv_pil function took 20.465 ms
True
cv.TM_CCORR_NORMED
benchmark_opencv_pil function took 25.347 ms
False
cv.TM_SQDIFF
benchmark_opencv_pil function took 23.799 ms
True
cv.TM_SQDIFF_NORMED
benchmark_opencv_pil function took 22.882 ms
True

-1
投票

如果您正在寻找图像识别,您可以使用Sikuli。查看 Hello World 教程

© www.soinside.com 2019 - 2024. All rights reserved.