gpt4 book ai didi

python - 使用 Python 解析像素数据的最有效/最快速的方法?

转载 作者:太空狗 更新时间:2023-10-30 02:31:15 24 4
gpt4 key购买 nike

我创建了一个简单的 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

我已经找到了可以做到这一点的东西,但速度没有我想要的那么快。这是使用具有任意值的 Python 图像库 (PIL) 的解决方案:

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

然后我可以获取该 RGB 值并将其与该函数获得的先前值进行比较。如果它改变了,那么屏幕上就会发生一些事情,这意味着程序做了一些事情,因此脚本可以相应地运行。然而,脚本需要快速 react ,特别是因为这只是一个更大的函数的一部分,有其自身的复杂性和缺陷,所以我正在一点一点地优化代码,从这个。

此解决方案将脚本限制为在 i7 4770k CPU 上每秒约 30 次迭代。看起来很快,但是将它与其他本身以类似速率解析像素信息的函数相结合,事情就开始加起来了。我的目标是在单个函数上每秒至少 200 次,也许 150 次迭代,以便最终脚本可以以每秒 5-10 次迭代的速度运行。

那么,长话短说:还有什么其他方法可以更快地从屏幕上解析像素?

最佳答案

好吧,经过一些挖掘后发现确实可以使用 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
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 次迭代。让我们将其用作进行比较的基本速度。

这是 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。这比以前的解决方案至少快了 2 个数量级,而且是惊人的 29600 % 改进。它是如此之快以致于 count+=1 增量减慢了它的速度。我对 100k 次迭代进行了一些测试,因为 1000 次对于这段代码来说太低了,平均值大致保持不变,14-16k 次迭代/秒。它还在 7-8 秒内完成了这项工作,而之前的那些是在我开始写这篇文章时就开始的,而且……好吧,它们还在继续。

好的,就是这样!希望这可以帮助任何有类似目标并面临类似问题的人。请记住,Python 找到了一种方法。

关于python - 使用 Python 解析像素数据的最有效/最快速的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23147244/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com