好吧,在经过一番挖掘之后,确实可以用Python和简单的pywin32模块(感谢Mark Hammond)完成我想要的事情。无需使用“骗子”语言,也无需将工作外包给numpy等。这是5行代码(其中6行带有导入):
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
就是这样。每次迭代时,它将返回所选像素的数字(COLORREF),这是一种表示颜色的方式(就像RGB或十六进制一样),最重要的是,我可以解析数据!如果您不确定,这里有一些台式机基准测试(标准Python构建cpython和i7 4770k):
我以前的解决方案是围绕虚拟秒表进行的(可以自行运行并进行检查):
import ImageGrab, time
@R_95_2419@ = (0,0,100,100) #100 x 100 square @R_95_2419@ to capture
pixel = (60,20) #pixel coordinates (must be within the @R_95_2419@'s boundaries)
t1 = time.time()
count = 0
while count < 1000:
s = ImageGrab.grab(@R_95_2419@) #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次迭代。让我们以此为基础进行比较。
这是BenjaminGolder使用ctypes指出的解决方案:
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次迭代。这真是令人赞叹的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。这比以前的解决方案 快了两个数量级,并且提高了 。它是如此之快,以至于count + = 1的增量会使它变慢。我对100k次迭代进行了一些测试,因为对于这段代码来说1000太低了,平均值保持大致相同,每秒14-16k次迭代。它还在7到8秒内完成了工作,而以前的地方是在我开始编写此书时开始的……而且他们还在继续。
好了,就是这样!希望这可以帮助具有相似目标和面临类似问题的任何人。记住,Python找到了一种方法。