在Windows上用Python快速截屏的方式

18 投票
4 回答
66764 浏览
提问于 2025-04-16 03:23

在Windows上,最快的截图方法是什么呢?使用 PIL.ImageGrab 这个工具速度比较慢,拍30张同一个小窗口的截图大约需要4到5秒。要是截图整个桌面,速度就更慢了。

4 个回答

2

你可以试试我新做的项目 DXcam:我觉得它在速度上是最快的(在Python中,而且没有太深入复杂的内容)。这个项目最初是为了深度学习在FPS游戏中的应用而创建的,FPS越高越好。此外,我(正在努力)让它更容易使用:

想要截图只需要这样做:

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
平均FPS 238.79 75.87 118.36
标准差 1.25 0.5447 0.3224

这个基准测试是在我的240Hz显示器上进行的,使用的是与显示器同步的240Hz渲染率(通过blurbuster UFO测试)。

你可以在这里了解更多细节: https://github.com/ra1nty/DXcam

6

我刚刚发现用gtk来实现这个功能。看起来速度快得多:

def image_grab_gtk(window):
    left, top, right, bot = get_rect(window)
    w = right - left
    h = bot - top

    s = gtk.gdk.Pixbuf(
        gtk.gdk.COLORSPACE_RGB, False, 8, w, h)

    s.get_from_drawable(
        gtk.gdk.get_default_root_window(),
        gtk.gdk.colormap_get_system(),
        left, top, 0, 0, w, h )

    final = Image.frombuffer(
        "RGB",
        (w, h),
        s.get_pixels(),
        "raw",
        "RGB",
        s.get_rowstride(), 1)
    return final

在我的测试中,不用转换成PIL图像时,它的速度比PIL快了8倍。即使转换后,它的速度还是快了大约2.7倍。

40

你可以直接使用win32的API。

  1. 首先,要把你想截图的应用程序设置为当前焦点,也就是让它成为你正在操作的窗口。链接文本

  2. Win32 API可以帮助你进行截图:

import win32gui
import win32ui
import win32con

w = 1920 # set this
h = 1080 # set this
bmpfilenamename = "out.bmp" #set this

hwnd = win32gui.FindWindow(None, windowname)
wDC = win32gui.GetWindowDC(hwnd)
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)
dataBitMap.SaveBitmapFile(cDC, bmpfilenamename)

# Free Resources
dcObj.DeleteDC()
cDC.DeleteDC()
win32gui.ReleaseDC(hwnd, wDC)
win32gui.DeleteObject(dataBitMap.GetHandle())

撰写回答