2014-04-18 2 views
4

특정 프로그램이 실행될 때마다 활성화되는 간단한 Python 스크립트를 만들었습니다. 이 프로그램은 화면에 정보를 보내 스크립트가 잡아서 분석해야합니다. 다음과 같이 스크립트의 논리의파이썬으로 픽셀 데이터를 구문 분석하는 가장 효율적/가장 빠른 방법은 무엇입니까?

일부 표현 될 수있다

while a certain condition is met: 
    function to continuously check pixel information on a fixed area of the screen() 
    if pixel data (e.g. RGB) changes: 
     do something 
    else: 
     continues to check 

가 이미 정확히이 일을 뭔가를 발견,하지만 아주 빨리 내가 ​​원하는만큼.

import ImageGrab 

box = (0,0,100,100) # 100x100 screen area to capture (0x0 is top left corner) 
pixel = (60,20) #target pixel coordenates (must be within the box's boundaries) 
im = ImageGrab.grab(box) #grabs the image area (aka printscreen) -> source of bottleneck 
hm = im.getpixel(pixel) # gets pixel information from the captured image in the form of an RGB value 

I는 그 RGB 값을 취하고 함수에 의해 얻어진 이전의 값과 비교할 수 여기서 임의의 값 파이썬 이미징 라이브러리 (PIL)를 사용하는 솔루션이다. 그것이 바뀌면 화면에 뭔가가 생겼다. 이는 프로그램이 뭔가를 한 것을 의미하므로 스크립트는 이에 따라 행동 할 수있다. 그러나 스크립트는 특히 복잡하고 큰 결함이있는 더 큰 함수의 일부이기 때문에 반응이 빠른이 필요하므로 코드를 비트 단위로 최적화하는 과정에 있습니다.

이 솔루션은 i7 4770k cpu에서 스크립트를 초당 ~ 30 반복으로 제한합니다. 빨리 보이지만 비슷한 속도로 픽셀 정보를 파싱하는 다른 기능을 추가하면 모든 것이 더해집니다. 최종 목표는 초당 5 ~ 10 회 반복 실행될 수 있도록 단일 함수에서 초당 200 회 이상, 아마도 150 회 반복하는 것이 목표입니다.

짧은 이야기 : 다른 방법으로 화면의 픽셀을 더 빠르게 파싱 할 수 있습니까?

+1

파이썬은이 작업을위한 도구가 아닙니다. 실시간 그래픽 처리에는 C++와 같은 더 비싼 언어가 필요합니다. 그리고 처리 코드의 성능에 제한이 없더라도 대부분의 윈도우 시스템에서 화면의 일부를 잡는 것은 느린 작업입니다. – orlp

+0

@ 대니얼 쇼 :이 질문을보십시오. http://stackoverflow.com/questions/1997678/faster-method-of-reading-screen-pixel-in-python-than-pil?rq=1 – BenjaminGolder

+0

@nightcracker 글쎄요. 그냥 .. 낙담하는거야. 적어도 조금 더 빨라지는 방법이 반드시 있어야합니다. –

답변

4

괜찮아요. 파기가 끝나면 파이썬과 pywin32 모듈 (Mark Hammond에게 감사드립니다.)에서 내가 원하는 것을 정확히 수행 할 수 있습니다. "우울한"언어 나 numpy와 그 밖의 것들에 아웃소싱 할 필요가 없습니다.

import win32ui 
window_name = "Target Window Name" # use EnumerateWindow for a complete list 
wd = win32ui.FindWindow(None, window_name) 
dc = wd.GetWindowDC() # Get window handle 
j = dc.GetPixel (60,20) # as practical and intuitive as using PIL! 
print j 
dc.DeleteDC() # necessary to handle garbage collection, otherwise code starts to slow down over many iterations 

그리고 그것 뿐이다 : 는 여기가 (수입 6) 코드의 5 개 라인입니다. 각 반복마다 선택한 픽셀의 수 (COLORREF)를 반환합니다. 이는 색상을 표현하는 방법 (RGB 또는 16 진수와 같음)과 가장 중요한 것은 구문 분석 할 수있는 데이터입니다. 가상 스톱워치 (그들에게 자신을 실행 주시기 그것을 확인)을 감싸

내 이전 솔루션 : 당신이 여기 확신하지 내 데스크톱 PC에 대한 몇 가지 벤치 마크 경우 (표준 파이썬은 CPython과 및 I7의 4770k를 구축)

import ImageGrab, time 
    box = (0,0,100,100) #100 x 100 square box to capture 
    pixel = (60,20) #pixel coordinates (must be within the box's boundaries) 
    t1 = time.time() 
    count = 0 
    while count < 1000: 
     s = ImageGrab.grab(box) #grabs the image area 
     h = s.getpixel(pixel) #gets pixel RGB value 
     count += 1 
    t2 = time.time() 
    tf = t2-t1 
    it_per_sec = int(count/tf) 
    print (str(it_per_sec) + " iterations per second") 

초당 29 회 반복 수행. 이것을 우리가 비교할 기본 속도로 사용합시다.초당

from ctypes import windll 
import time 
dc= windll.user32.GetDC(0) 
count = 0 
t1 = time.time() 
while count < 1000: 
    a= windll.gdi32.GetPixel(dc,x,y) 
    count += 1 
t2 = time.time() 
tf = t2-t1 
print int(count/tf) 

반복 보통 54 :

여기 BenjaminGolder 사용하는 ctypes 가리키는 용액이다. 그건 환상적인 86 % 개선이지만, 이 아니고, 내가 찾고 있던 순서대로이 아닙니다.

그래서, 결국, 여기가 제공된다

name = "Python 2.7.6 Shell" #just an example of a window I had open at the time 
w = win32ui.FindWindow(None, name) 
t1 = time.time() 
count = 0 
while count < 1000: 
    dc = w.GetWindowDC() 
    dc.GetPixel (60,20) 
    dc.DeleteDC() 
    count +=1 
t2 = time.time() 
tf = t2-t1 
it_per_sec = int(count/tf) 
print (str(it_per_sec) + " iterations per second") 

대략 16000 반복 픽셀 목 마른 스크립트의 두 번째. 예, 16000입니다. 에 최소이고 이전 솔루션보다 2 배 더 빠르며 백도 어 29600 % 개선되었습니다. 너무 빠르므로 count + = 1만큼 증가 시키면 속도가 느려집니다. 1000은 코드의 일부로 너무 낮았 기 때문에 100k 반복 테스트를했는데 평균은 대략 14-16k 반복/초 정도였습니다. 그것은 또한 7-8 초에 일을했는데 이전 일들은 내가 이것을 쓰기 시작할 때 어디에서 시작 했는가 ... 그들은 여전히 ​​가고있다.

좋아, 그게 전부 야! 희망이 비슷한 목적을 가진 사람을 도울 수 있고 비슷한 문제에 직면했다. 파이썬은 방법을 찾습니다.

+0

잘 했어! 대부분의 제안을 둘러 보면서 가장 좋은 답변을 만들었습니다. – BenjaminGolder

2

사실, 주석에 언급 된대로 Python 루프에서 픽셀별로 픽셀을 검사해서는 안됩니다. 당신은 Pypy를 시도해 볼 수도 있습니다 - 적절한 데이터를 생성하고 pypy하면 순수한 파이썬 코드와 픽셀 데이터를 사용하여 10 배 향상시킬 수 있습니다.

그러나 파이썬이 픽셀 조작을하기 위해 원시 코드로 라이브러리를 호출하게하는 것이 일반적입니다. PIL과 Numpy는 그런 라이브러리입니다. 파이썬에서 각 픽셀의 값을 검사하는 대신에해야할 일은, 예를 들어 이미지 직사각형 영역을 다른 부분에서 뺍니다. 그러면 다른 픽셀을 가진 행렬을 얻을 수 있습니다. Numpy를 사용하여 필요에 따라 이러한 차이를 치료하십시오. 그것은 빠를 것이고, 당신은 여전히 ​​필요한 모든 고수준의 것들에 대해 파이썬을 사용할 것입니다.

+0

im = ImageOps.grayscale (ImageGrab. a = array (im.getcolors()); a = a.sum()? –

관련 문제