2010-04-14 8 views
0

Tout d'abord désolé pour le long morceau de code collé ci-dessous. C'est la première fois que je m'inquiète de la performance d'une application, donc je n'ai jamais vraiment eu peur de la performance. Ce morceau de code cherche à peu près une image dans une autre image, il faut 30 secondes pour exécuter sur mon ordinateur, convertissant les images en niveaux de gris et autres changements rasés de 15 secondes, j'ai besoin de 15 autres rasés. J'ai lu un tas de pages et regardé des exemples mais je n'ai pas pu trouver les mêmes problèmes dans mon code. Donc toute aide serait grandement appréciée. De son apparence (cProfile), 25 secondes sont passées dans le module Image et seulement 5 secondes dans mon code.Optimisation du code en utilisant PIL

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"))') 

Répondre

1

sans performances directement vous pourriez faire quelques trait des choses à améliorer votre code:

if not Found: 
    return "Not Found" 

est bien idiomatiques écrire état en Python. Cependant, vous n'avez pas besoin de cette clause, car cette instruction de retour ne peut être atteinte que si l'image n'a pas été trouvée.

dans GetImage vous devez créer le nom de fichier une fois avec os.path.join(os.getcwd(),"Images",name) pour minimiser les erreurs et ne pas vous répéter. En outre, cela ne fonctionnerait normalement pas si vous n'avez pas le fichier image. Puisque vous n'êtes pas de traitement d'erreurs Find, je suggère ce qui suit:

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 

Votre problème majeur est que vous faites pixel par la recherche de pixels, il va être lent sur une image de taille significative.

1

Cet algorithme demande beaucoup de calculs, je ne crois pas que vous puissiez l'accélérer sans modifier l'approche.

permet de faire un peu de maths: Dites l'écran est 1024x768 (nous sommes encore en l'an 2000) Supposons que votre image test est 100x100 Ensuite, vous finissez par faire 924 * 668 blits de 100x100 Cest l'équivalent d'environ 7848 blits en plein écran.

Il est lié à la lenteur avec cette approche de force brute.