【问题标题】:ImageGrab.grab() method is too slow but alternatives don't return the rgb colourImageGrab.grab() 方法太慢但替代方案不返回 rgb 颜色
【发布时间】:2023-01-14 15:44:21
【问题描述】:

我需要能够尽可能快地返回某个像素的 RGB,但是下面的脚本太慢了(每秒返回 RBG 的速度不够快。)

while True:
    x = 960
    y = 540
    rgb = PIL.ImageGrab.grab().load()[x,y]
    if rgb == (xxx,xxx,xxx):
        mouse.click('left')
        time.sleep(0.1)
    else:
        print(rgb)

有一篇帖子解决了这个问题https://stackoverflow.com/questions/44140586/imagegrab-grab-method-is-too-slow,但是没有一个解决方案清楚地说明如何返回像素/区域的 RGB,只能截图。

我试过使用脚本

with mss.mss() as sct:
    # Get a screenshot of the center pixel of the first monitor
    sct_img = sct.grab(sct.monitors[1])
    monitor = {"top": 540, "left": 960, "width": 1, "height": 1}
    sct_img = sct.grab(monitor)
    output = "sct-{top}x{left}_{width}x{height}.png".format(**monitor)

但还没有完全弄清楚返回所选像素的 RGB。

如果我使用第二个脚本然后将输出转换为 RGB 可能会起作用,但我不太确定我将如何去做。

【问题讨论】:

  • ImageGrab 抓取整个屏幕。如果你想抓取一个像素,你可能需要使用操作系统特定的 API。你在 Windows 上吗?
  • 您需要深入研究 Windows API 才能比屏幕抓取更快地完成它。不确定 Python 是否是最好的语言。
  • 如果他们在 Windows 上,使用几乎每个人都使用的 PyWIn32 模块实际上相当容易。它只是 GetDC 和 GetPixel。它仍然不会很快;显卡制造商优化了进入屏幕,而不是来自屏幕。
  • 回复@TimRoberts 是的,我在 Windows 上,什么样的 API 和编程语言可以工作,因为我知之甚少,但绝对愿意做一些研究并弄清楚。感谢使用 pywin32 的建议,我肯定会试一试并运行一些测试以查看哪个最快。

标签: python performance python-imaging-library rgb


【解决方案1】:

同样的问题,我有 2 个显示器,所以它很慢:/ 你可以试试:

PIL.ImageGrab.grab(bbox=(x, y, 500, 300).load()[0,0]

(我不知道“500,300”到底是什么意思) 但就我个人而言,我看不出有什么大的不同

【讨论】:

  • 500, 300 是裁剪区域的右下角坐标,x, y 是左上角坐标
【解决方案2】:

关于性能:至少在 Linux (X11) 上,PIL.ImageGrab.grab() 默认使用 gnome-screenshot,如 stated in the official documentation。要禁用此功能并启用直接 X11 调用(如果可用),请设置 xdisplay=""。在我的系统中,截取 1920x1200 的完整屏幕截图,仅此设置就改进了 ~3.30 帧/秒 / 303.3ms per call to a whooping 80.27 帧/秒 / 12.45ms!

至于获取像素的(r, g, b)值,只需使用...getpixel()

def find_color(x, y, rgb_ref):
    while True:
        rgb = PIL.ImageGrab.grab(xdisplay="").getpixel((x, y))
        if rgb == rgb_ref:
            mouse.click('left')
        else:
            print(rgb)
        time.sleep(0.1)

另请注意,我将 time.sleep() 电话移到了if 块。除非您正在做基准测试,否则永远不要使用完全繁忙的循环,并且始终在 while True 循环的每个循环中插入暂停。

【讨论】:

    猜你喜欢
    • 2020-03-25
    • 2012-05-03
    • 2018-03-19
    • 1970-01-01
    • 2014-09-20
    • 2013-08-03
    • 1970-01-01
    • 2011-03-04
    相关资源
    最近更新 更多