ImageGrab.grab()方法太慢了

时间:2017-05-23 16:41:37

标签: python performance screenshot python-imaging-library

所以我需要每秒获得一堆屏幕截图,比如5.我正在使用它为游戏编写机器人。然而,imagegrab方法需要0.3秒,这对我来说非常慢。即使在指定bbox值之后,它仍然需要0.3秒。我想应该提一下我在Mac上。对我来说有更好的方法

我甚至尝试过运行时间为0.15-0.2秒的os.system("screencapture filename.png"),这很好,但我想要更快。

3 个答案:

答案 0 :(得分:1)

所以我如何让它为我工作是使用

os.system("screencapture -R0,0,100,100 filename.png")
im = Image.open("filename.png")

您可以相应地替换0,0,100,100。 它的运行时间小于0.1秒,更像是0.06秒。

答案 1 :(得分:1)

另一种解决方案是使用Python MSS

from mss import mss
from PIL import Image

def capture_screenshot():
    # Capture entire screen
    with mss() as sct:
        monitor = sct.monitors[1]
        sct_img = sct.grab(monitor)
        # Convert to PIL/Pillow Image
        return Image.frombytes('RGB', sct_img.size, sct_img.bgra, 'raw', 'BGRX')

img = capture_screenshot()
img.show()

此功能可以在速度较慢的笔记本电脑上以最高27 fps的速度返回屏幕截图。

答案 2 :(得分:0)

问题:在Mac上,什么比ImageGrab.grab()更好?

我在mss,pil和pyscreenshot之间进行了测试,并测量了获取各种尺寸的图像所需的平均时间,并以毫秒为单位报告了时间。

答案

看来mss远远超过了Mac上的其他版本。要捕获800x400的屏幕片段,毫米需要15毫秒,而其他两个则需要300-400毫秒。那是mms为66fps或其他两个为3fps的区别。

代码

# !pip install image
# !pip install opencv-python
# !pip install pyscreenshot

import numpy as np
from time import time


resolutions = [
    (0, 0, 100,100),(0, 0, 200,100),
    (0, 0, 200,200),(0, 0, 400,200),
    (0, 0, 400,400),(0, 0, 800,400)
]


import numpy as np
import pyscreenshot as ImageGrab
import cv2


def show(nparray):
    import cv2
    cv2.imshow('window',cv2.cvtColor(nparray, cv2.COLOR_BGR2RGB))
    # key controls in a displayed window
    # if cv2.waitKey(25) & 0xFF == ord('q'):
        # cv2.destroyAllWindows()


def mss_test(shape) :
    average = time()
    import mss
    sct = mss.mss()
    mon = {"top": shape[0], "left": shape[1], "width": shape[2]-shape[1], "height": shape[3]-shape[0]}
    for _ in range(5):
        printscreen =  np.asarray(sct.grab(mon))
    average_ms = int(1000*(time()-average)/5.)
    return average_ms, printscreen.shape




def pil_test(shape) :
    average = time()
    from PIL import ImageGrab
    for _ in range(5):
        printscreen =  np.array(ImageGrab.grab(bbox=shape))
    average_ms = int(1000*(time()-average)/5.)
    return average_ms, printscreen.shape




def pyscreenshot_test(shape):
    average = time()
    import pyscreenshot as ImageGrab
    for _ in range(5):
        printscreen = np.asarray( ImageGrab.grab(bbox=shape) )
    average_ms = int(1000*(time()-average)/5.)
    return average_ms, printscreen.shape


named_function_pair = zip("mss_test,pil_test,pyscreenshot_test".split(","),
    [mss_test,pil_test,pyscreenshot_test])

for name,function in named_function_pair:
    results = [ function(res) for res in resolutions ]
    print("Speed results for using",name)
    for res,result in zip(resolutions,results) :
        speed,shape = result
        print(res,"took",speed,"ms, produced shaped",shape)

输出

Speed results for using mss_test
(0, 0, 100, 100) took 7 ms, produced shaped (200, 200, 4)
(0, 0, 200, 100) took 4 ms, produced shaped (200, 400, 4)
(0, 0, 200, 200) took 5 ms, produced shaped (400, 400, 4)
(0, 0, 400, 200) took 6 ms, produced shaped (400, 800, 4)
(0, 0, 400, 400) took 9 ms, produced shaped (800, 800, 4)
(0, 0, 800, 400) took 15 ms, produced shaped (800, 1600, 4)

Speed results for using pil_test
(0, 0, 100, 100) took 313 ms, produced shaped (100, 100, 4)
(0, 0, 200, 100) took 321 ms, produced shaped (100, 200, 4)
(0, 0, 200, 200) took 334 ms, produced shaped (200, 200, 4)
(0, 0, 400, 200) took 328 ms, produced shaped (200, 400, 4)
(0, 0, 400, 400) took 321 ms, produced shaped (400, 400, 4)
(0, 0, 800, 400) took 320 ms, produced shaped (400, 800, 4)

Speed results for using pyscreenshot_test
(0, 0, 100, 100) took 85 ms, produced shaped (200, 200, 4)
(0, 0, 200, 100) took 101 ms, produced shaped (200, 400, 4)
(0, 0, 200, 200) took 122 ms, produced shaped (400, 400, 4)
(0, 0, 400, 200) took 163 ms, produced shaped (400, 800, 4)
(0, 0, 400, 400) took 236 ms, produced shaped (800, 800, 4)
(0, 0, 800, 400) took 400 ms, produced shaped (800, 1600, 4)

进一步的观察

尽管所有三个库都发送了相同的屏幕区域以进行抓取,但是mss和pyscreenshot都捕获了mac屏幕的物理像素,而pil则捕获了逻辑像素。仅当Mac显示分辨率从最高分辨率降低时,才会发生这种情况。就我而言,我的视网膜显示设置为“平衡”,这意味着每个逻辑像素实际上是2x2物理像素。