5

Pythonでスクリーンキャプチャプログラムを作成しています。私の現在の問題は、PIL.ImageGrab.grab()が2秒後と同じ出力を返すことです。たとえば、私ははっきりしていないと思いますが、次のプログラムでは、PIL.ImageGrabの間に画面を移動していても、ほとんどすべての画像が同じで、同じImage.tostring()値を持っています。グラブループが実行されていました。

>>> 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
>>> 

すべての画像は同じですが、30分の1が異なるため、これは問題です。それは絶対に恐ろしい品質のビデオになります。PIL.ImageGrab.grab()に代わるより良い品質の代替品があるかどうか教えてください。画面全体をキャプチャする必要があります。ありがとう!

編集:

これまでのところ、最良の代替手段はpywin32を使用することのようです。今は使っていますが、とても遅いです。今のところこのプロジェクトは個人的なものなので、互換性についてはあまり気にしません。プログラムのフレームレートを計算するたびに、pywin32は非常に遅く、ネガティブになります。より速い代替案があるかどうか教えてください。ありがとう!

4

2 に答える 2

5

PIL.ImageGrabには多くの選択肢があります。

クロスプラットフォームが必要な場合は、ほぼすべての主要なウィンドウライブラリに画面グラブ機能があります。PyQt4を使用した例を次に示します。

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

Qtが「デスクトップ」と見なすデフォルト設定とは異なるものが必要な場合は、PyQtまたはQtのドキュメントを詳しく調べる必要があります。

欠点は、これらのクロスプラットフォームのウィンドウライブラリは、通常、インストール、配布、場合によってはプログラムの構造化の点でかなり重い義務があることです。

別の方法は、Windows固有のコードを使用することです。Windows APIに直接ctypesすることは可能ですが、はるかに簡単なソリューションは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')

Win32の場合と同様に、「デスクトップ」の意味を正確に指定する必要があります。このバージョンでは、現在のセッションの「仮想画面」を指定します。これは、コンソールでローカルで実行している場合はすべてのモニターの組み合わせであり、ターミナルサービスで実行している場合はリモートビューです。別の何かが必要な場合は、MSDNで関連するWin32のドキュメントを読む必要があります。しかし、ほとんどの場合、そのドキュメントからPyWin32への変換は簡単です。

(ちなみに、「Win32」と言っても、Win64でも同じことが言えます。)

于 2012-09-25T21:36:14.210 に答える
4

最新のクロスプラットフォームソリューションは、PythonMSSを使用することです。

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()

私の遅いラップトップでは、この関数は最大27fpsでスクリーンショットを返すことができます。

于 2018-07-02T07:04:39.900 に答える