Оптимизация кода с использованием PIL - PullRequest
0 голосов
/ 14 апреля 2010

Во-первых, извините за длинный кусок кода, вставленный ниже. Это мой первый раз, когда мне действительно приходится беспокоиться о производительности приложения, поэтому я никогда не беспокоился о производительности. Этот фрагмент кода в значительной степени ищет изображение внутри другого изображения, его запуск на моем компьютере занимает 30 секунд, преобразование изображений в оттенки серого и другие изменения, уменьшенные на 15 секунд, мне нужно еще 15, сброшенные. Я прочитал несколько страниц и посмотрел на примеры, но не смог найти те же проблемы в своем коде. Поэтому любая помощь будет принята с благодарностью.

Судя по всему (cProfile), в модуле Image тратится 25 секунд, а в моем коде всего 5 секунд.

from PIL import Image
import os, ImageGrab, pdb, time, win32api, win32con
import cProfile

def GetImage(name):
    name = name + '.bmp'
    try:
        print(os.path.join(os.getcwd(),"Images",name))
        image = Image.open(os.path.join(os.getcwd(),"Images",name))
    except:
        print('error opening image;', name)
    return image

def Find(name):
    image = GetImage(name)
    imagebbox = image.getbbox()
    screen = ImageGrab.grab()
    #screen = Image.open(os.path.join(os.getcwd(),"Images","Untitled.bmp"))
    YLimit =  screen.getbbox()[3] - imagebbox[3]
    XLimit = screen.getbbox()[2] - imagebbox[2]
    image = image.convert("L")
    Screen = screen.convert("L")
    Screen.load()
    image.load()
    #print(XLimit, YLimit)
    Found = False
    image = image.getdata()
    for y in range(0,YLimit):
        for x in range(0,XLimit):
            BoxCoordinates = x, y, x+imagebbox[2], y+imagebbox[3]
            ScreenGrab = screen.crop(BoxCoordinates)
            ScreenGrab = ScreenGrab.getdata()
            if image == ScreenGrab:
                Found = True
                #print("woop")
                return x,y
    if Found == False:
        return "Not Found"
cProfile.run('print(Find("Login"))')

Ответы [ 2 ]

1 голос
/ 14 апреля 2010

Этот алгоритм требует значительных вычислений, я не верю, что вы можете ускорить его без изменения подхода.

Давайте посчитаем: Скажем, экран 1024x768 (мы все еще в 2000 году) Скажите, что ваше тестовое изображение 100x100 Тогда вы в конечном итоге сделать 924 * 668 блит 100x100 Это эквивалентно примерно 7848 полноэкранным блиттам.

При таком подходе грубой силы он будет медленным.

1 голос
/ 14 апреля 2010

, хотя напрямую не связаны с производительностью, вы можете сделать некоторые вещи для улучшения своего кода:

if not Found:
    return "Not Found"

- идиоматический способ написания условия в Python. Однако вам не нужно это предложение, так как этот оператор возврата может быть достигнут только в том случае, если изображение не найдено.

в GetImage вы должны создать имя файла один раз с os.path.join(os.getcwd(),"Images",name), чтобы минимизировать ошибки и не повторяться. Также это не будет нормально работать, если у вас нет файла изображения. Поскольку вы не обрабатываете ошибку в Find, я бы предложил следующее:

def Find(name):
    fname = os.path.join(os.getcwd(), "Images", name + '.bmp')
    image = Image.open(fname)
    imagebbox = image.getbbox()
    screen = ImageGrab.grab()
    YLimit =  screen.getbbox()[3] - imagebbox[3]
    XLimit = screen.getbbox()[2] - imagebbox[2]
    image = image.convert("L")
    Screen = screen.convert("L")
    Screen.load()
    image.load()
    image = image.getdata()
    for y in range(0, YLimit):
        for x in range(0, XLimit):
            BoxCoordinates = x, y, x+imagebbox[2], y+imagebbox[3]
            ScreenGrab = screen.crop(BoxCoordinates)
            ScreenGrab = ScreenGrab.getdata()
            if image == ScreenGrab:
                return x, y
    # returns None implicitly

Ваша главная проблема в том, что вы делаете поиск по пикселям, это будет медленным на любом значимом изображении.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...