简体   繁体   English

捕获屏幕有比PIL.ImageGrab.grab()更好的方法吗?

[英]Is there any better way to capture the screen than PIL.ImageGrab.grab()?

I am making a screen capture program with python. 我正在用python制作一个截屏程序。 My current problem is PIL.ImageGrab.grab() gives me the same output as 2 seconds later. 我目前的问题是PIL.ImageGrab.grab()在2秒后给出了相同的输出。 For instance, for I think I am not being clear, in the following program, almost all the images are the same, have the same Image.tostring() value, even though I was moving my screen during the time the PIL.ImageGrab.grab loop was executing. 例如,因为我认为我不清楚,在下面的程序中,几乎所有图像都是相同的,具有相同的Image.tostring()值,即使我在PIL.ImageGrab期间移动我的屏幕。抓斗循环正在执行。

>>> from PIL.ImageGrab import grab
>>> l = []
>>> import time
>>> for a in l:
        l.append(grab())
        time.sleep(0.01)


    >>> for a in range(0, 30):
        l.append(grab())
        time.sleep(0.01)


>>> b = []
>>> for a in l:
        b.append(a.tostring())


>>> len(b)
30
>>> del l
>>> last = []
>>> a = 0
>>> a = -1
>>> last = ""
>>> same = -1
>>> for pic in b:
        if b == last:
            same = same + 1
        last = b


>>> same
28
>>> 

This is a problem, as all the images are the same but 1. 1 out of 30 is different. 这是一个问题,因为所有图像都是相同的,但是30个中的1个是不同的。 That would make for a absolutly horrable quality video. 这将成为一个绝对可怕的高质量视频。 Please, tell me if there is any better quality alternative to PIL.ImageGrab.grab(). 请告诉我是否有更好的替代品PIL.ImageGrab.grab()。 I need to capture the whole screen. 我需要捕捉整个屏幕。 Thanks! 谢谢!

EDIT: 编辑:

So far, it looks like the best alternative is to use pywin32. 到目前为止,看起来最好的选择是使用pywin32。 I am using that for now, but it is very slow. 我现在正在使用它,但它很慢。 I don't really care about compatability, as for now this project is personal. 我并不真正关心兼容性,因为现在这个项目是个人的。 Every time I work out the frame rate of the program, pywin32 is so slow, it's in the negatives. 每次我计算出程序的帧速率时,pywin32都是如此之慢,它是负面的。 Please tell me if there is a faster alternative. 请告诉我是否有更快的替代方案。 Thanks! 谢谢!

There are many alternatives to PIL.ImageGrab. PIL.ImageGrab有很多替代品。

If you want cross-platform, nearly every major windowing library has screen grab capabilities. 如果您想要跨平台,几乎每个主要的窗口库都有屏幕抓取功能。 Here's an example using PyQt4 : 这是使用PyQt4的示例:

import sys
from PyQt4.QtGui import QPixmap, QApplication
app = QApplication(sys.argv)
QPixmap.grabWindow(QApplication.desktop().winId()).save('screenshot.jpg', 'jpg')

If you want something different from the default settings for what Qt considers "the desktop", you'll need to dig into the PyQt or Qt documentation. 如果您想要与Qt认为“桌面”的默认设置不同的东西,您需要深入了解PyQt或Qt文档。

The downside is that these cross-platform windowing libraries are usually pretty heavy duty in terms of installation, distribution, and even sometimes how you structure your program. 缺点是这些跨平台窗口库在安装,分发方面通常都很重要,有时甚至是你如何构建程序。

The alternative is to use Windows-specific code. 另一种方法是使用特定于Windows的代码。 While it's possible to ctypes your way directly to the Windows APIs, a much simpler solution is PyWin32 . 虽然可以直接使用Windows API,但更简单的解决方案是PyWin32

import win32gui, win32ui, win32con, win32api
hwin = win32gui.GetDesktopWindow()
width = win32api.GetSystemMetrics(win32con.SM_CXVIRTUALSCREEN)
height = win32api.GetSystemMetrics(win32con.SM_CYVIRTUALSCREEN)
left = win32api.GetSystemMetrics(win32con.SM_XVIRTUALSCREEN)
top = win32api.GetSystemMetrics(win32con.SM_YVIRTUALSCREEN)
hwindc = win32gui.GetWindowDC(hwin)
srcdc = win32ui.CreateDCFromHandle(hwindc)
memdc = srcdc.CreateCompatibleDC()
bmp = win32ui.CreateBitmap()
bmp.CreateCompatibleBitmap(srcdc, width, height)
memdc.SelectObject(bmp)
memdc.BitBlt((0, 0), (width, height), srcdc, (left, top), win32con.SRCCOPY)
bmp.SaveBitmapFile(memdc, 'screenshot.bmp')

As usual with Win32, you have to specify exactly what you mean by "the desktop"; 像往常一样,你必须准确指出“桌面”的含义; this version specifies the "virtual screen" for the current session, which is the combination of all of the monitors if you're running locally at the console, or the remote view if you're running over Terminal Services. 此版本指定当前会话的“虚拟屏幕”,如果您在控制台本地运行,则为所有监视器的组合,如果您在终端服务上运行,则为远程视图。 If you want something different, you'll have to read the relevant Win32 documentation at MSDN. 如果您想要不同的东西,您必须阅读MSDN上的相关Win32文档。 But for the most part, translating from that documentation to PyWin32 is trivial. 但在大多数情况下,从文档转换到PyWin32是微不足道的。

(By the way, even though I say "Win32", the same all works for Win64.) (顺便说一句,即使我说“Win32”,同样适用于Win64。)

A modern cross-platform solution is to use Python MSS . 现代的跨平台解决方案是使用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()

On my slow laptop this function can return screenshots at up to 27 fps. 在我的慢速笔记本电脑上,此功能可以返回最高27 fps的屏幕截图。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么特定窗口的 PIL.ImageGrab.grab 无法正常工作? - Why does PIL.ImageGrab.grab of specific window doesn't work properly? 如何从 Python 中的 PIL.ImageGrab.grab() 获取实际像素颜色值? - How to get actual Pixel Color value from PIL.ImageGrab.grab() in Python? 有什么办法可以让 PIL 的 ImageGrab.grab() 保存小尺寸的照片? - Is there any way to make PIL's ImageGrab.grab() save photos with a small size? 线程中的 PIL.ImageGrab、grab() 和 load() 函数 - PIL.ImageGrab , grab() and load() functions in thread PIL imagegrab().grab().crop(...) 作物不是给定的坐标 - PIL imagegrab().grab().crop(...) crops not the given coordinates ImageGrab.grab() 在第一个屏幕上运行代码时的第二个屏幕 - ImageGrab.grab() the second screen while running code on the first screen ImageGrab.grab 不是获取 tkinter 窗口的小部件,而是获取其下的屏幕区域 - ImageGrab.grab not get widget of tkinter window, but screen area under it PIL的.crop返回图像0x0。 指定bbox的ImageGrab.grab也是如此 - PIL's .crop returns image 0x0. So does ImageGrab.grab with specified bbox 屏幕截图(PIL)Win10上的ImageGrab.grab / BitBlt仅返回背景吗? - Screenshot (PIL)ImageGrab.grab / BitBlt on Win10 only return the Background? ImageGrab.grab() 的时序 function - Timing of ImageGrab.grab() function
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM