[英]ImageGrab.grab() method is too slow
So i need to get a bunch of screenshots every second, like 5. I am using it to program a bot for a game.所以我需要每秒获取一堆屏幕截图,比如 5。我正在使用它来为游戏编写机器人程序。 However imagegrab method takes like 0.3 seconds, which is terribly slow for me.
然而 imagegrab 方法需要 0.3 秒,这对我来说非常慢。 Even after specifying the bbox values it still takes like 0.3 seconds.
即使在指定 bbox 值之后,它仍然需要 0.3 秒。 I think should mention that I am on a mac.
我想应该提到我在Mac上。 Is there a better way for me
有没有更好的方法适合我
I even tried the os.system("screencapture filename.png")
which has a runtime of 0.15-0.2 seconds which is nice but I want to go faster.我什至尝试了运行时间为 0.15-0.2 秒的
os.system("screencapture filename.png")
,这很好,但我想更快。
Another solution is to use Python MSS<\/a> .另一种解决方案是使用
Python MSS<\/a> 。
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()
I did a test between mss, pil, and pyscreenshot and measured the average time it took to take a various sized image grabs and reported the time in milliseconds.我在 mss、pil 和 pyscreenshot 之间进行了测试,并测量了抓取各种大小的图像所需的平均时间,并以毫秒为单位报告了时间。
It appears that mss<\/a> far exceeds the others on a mac.似乎
mss<\/a>在 mac 上远远超过其他人。 To capture a 800x400 slice of the screen mms takes 15ms whereas the other two take 300-400ms.
要捕获 800x400 的屏幕切片,mms 需要 15ms,而其他两个需要 300-400ms。 That's the difference between 66fps for mms or 3fps for the other two.
这就是 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)<\/code><\/pre>
Output输出<\/h1>
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)<\/code><\/pre>
Further Observations
进一步的观察<\/h1>
Although all three libraries were sent identical screen areas to grab, both mss and pyscreenshot grabbed physical pixels of the mac screen where as pil grabbed the logical pixels.
"尽管所有三个库都发送了相同的屏幕区域进行抓取,但 mss 和 pyscreenshot 都抓取了 mac 屏幕的物理像素,而 pil 抓取了逻辑像素。 This only happens if you have your Mac display resolution turned down from its highest resolution.
仅当您将 Mac 显示分辨率从其最高分辨率调低时才会发生这种情况。 In my case I have a retinal display set to "balanced" which means that each logical pixel is actually 2x2 physical pixels.
在我的情况下,我将视网膜显示器设置为“平衡”,这意味着每个逻辑像素实际上是 2x2 物理像素。
So how I got it working for me is by using所以我如何让它为我工作是通过使用
os.system("screencapture -R0,0,100,100 filename.png")
im = Image.open("filename.png")
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.