Python:截取和保存屏幕截图的最快方法

Python: Fastest way to take and save screenshots

我一直在努力想出一个脚本,让我每秒多次截取我的桌面屏幕截图。我用的是Win10.

PIL:

from PIL import ImageGrab
import time

while True:
    im = ImageGrab.grab()
    fname = "dropfolder/%s.png" %int(time.time())
    im.save(fname,'PNG') 

结果每张图片 1.01 秒。

PyScreeze (https://github.com/asweigart/pyscreeze):

import pyscreeze
import time

while True:
    fname = "dropfolder/%s.png" %int(time.time())
    x = pyscreeze.screenshot(fname)

结果每张图片 1.00 秒。

Win32:

import win32gui
import win32ui 
import win32con
import time

w=1920 #res
h=1080 #res

while True:
    wDC = win32gui.GetWindowDC(0)
    dcObj=win32ui.CreateDCFromHandle(wDC)
    cDC=dcObj.CreateCompatibleDC()
    dataBitMap = win32ui.CreateBitmap()
    dataBitMap.CreateCompatibleBitmap(dcObj, w, h)
    cDC.SelectObject(dataBitMap)
    cDC.BitBlt((0,0),(w, h) , dcObj, (0,0), win32con.SRCCOPY)
    fname = "dropfolder/%s.png" %int(time.time())
    dataBitMap.SaveBitmapFile(cDC, fname)
    dcObj.DeleteDC()
    cDC.DeleteDC()
    win32gui.ReleaseDC(0, wDC)
    win32gui.DeleteObject(dataBitMap.GetHandle())

结果每张图片 1.01 秒。

然后我偶然发现了线程 (Fastest way to take a screenshot with python on windows),其中建议 gtk 会产生惊人的结果。

但是使用 gtk:

import gtk
import time

img_width = gtk.gdk.screen_width()
img_height = gtk.gdk.screen_height()

while True:
    screengrab = gtk.gdk.Pixbuf(
        gtk.gdk.COLORSPACE_RGB,
        False,
        8,
        img_width,
        img_height
    )

    fname = "dropfolder/%s.png" %int(time.time())
    screengrab.get_from_drawable(
        gtk.gdk.get_default_root_window(),
        gtk.gdk.colormap_get_system(),
        0, 0, 0, 0,
        img_width,
        img_height
        ).save(fname, 'png')

结果每张图片 2.34 秒。

在我看来我做错了什么,因为人们使用 gtk 取得了很好的效果。

有什么建议可以加快这个过程吗?

谢谢!

您的第一个解决方案应该是每秒给您不止一张图片。但问题是您将覆盖同一秒内出现的任何图片,即它们都将具有相同的文件名。要解决这个问题,您可以创建包含十分之一秒的文件名,如下所示:

from PIL import ImageGrab
from datetime import datetime

while True:
    im = ImageGrab.grab()
    dt = datetime.now()
    fname = "pic_{}.{}.png".format(dt.strftime("%H%M_%S"), dt.microsecond // 100000)
    im.save(fname, 'png') 

在我的机器上,这给出了以下输出:

pic_1143_24.5.png
pic_1143_24.9.png
pic_1143_25.3.png
pic_1143_25.7.png
pic_1143_26.0.png
pic_1143_26.4.png
pic_1143_26.8.png
pic_1143_27.2.png
def d3dgrab(rect=(0, 0, 0, 0), spath=r".\pictures\cache\", sname="", title=""):
    """ take a screenshot by rect. """

    sname = sname if sname else time.strftime("%Y%m%d%H%M%S000.jpg", time.localtime())
    while os.path.isfile("%s%s" % (spath, sname)):
        sname = "%s%03d%s" % (sname[:-7], int(sname[-7:-4]) + 1, sname[-4:])

    xlen = win32api.GetSystemMetrics(win32con.SM_CXSCREEN)
    ylen = win32api.GetSystemMetrics(win32con.SM_CYSCREEN)

    assert 0 <= rect[0] <= xlen and 0 <= rect[2] <= xlen, ValueError("Illegal value of X coordination in rect: %s" % rect)
    assert 0 <= rect[1] <= ylen and 0 <= rect[3] <= ylen, ValueError("Illegal value of Y coordinatoin in rect: %s" % rect)

    if title:
        hdl = win32gui.FindWindow(None, title)
        if hdl != win32gui.GetForegroundWindow():
            win32gui.SetForegroundWindow(hdl)
        rect = win32gui.GetWindowRect(hdl)
    elif not sum(rect):
        rect = (0, 0, xlen, ylen)

    d = d3dshot.create(capture_output="numpy")
    return d.screenshot_to_disk(directory=spath, file_name=sname, region=rect)

我觉得能帮上忙

sname = sname if sname else time.strftime("%Y%m%d%H%M%S000.jpg", time.localtime())
while os.path.isfile("%s%s" % (spath, sname)):
    sname = "%s%03d%s" % (sname[:-7], int(sname[-7:-4]) + 1, sname[-4:])

这是我发现的最快的截屏方法。

万一有人在 2022 年关心:你可以试试我新创建的项目 DXcam:我认为就原始速度而言,它是最快的(在 python 中,而且不会太深入兔子洞)。它最初是为 FPS 游戏的深度学习管道创建的,FPS 越高越好。另外,我(正在尝试)将其设计为 user-friendly: 对于截图只是做

import dxcam
camera = dxcam.create()
frame = camera.grab()  # full screen
frame = camera.grab(region=(left, top, right, bottom))  # region

截屏:

camera.start(target_fps=60)  # threaded
for i in range(1000):
    image = camera.get_latest_frame()  # Will block until new frame available
camera.stop()

我从自述文件中复制了基准测试部分:

DXcam python-mss D3DShot
Average FPS 238.79 75.87 118.36
Std Dev 1.25 0.5447 0.3224

基准测试是在我的 240hz 显示器上进行的 5 次试验,同步恒定的 240hz 渲染率 w/the 显示器(使用 blurbuster ufo 测试)。

您可以在此处阅读更多详细信息:https://github.com/ra1nty/DXcam