2012-09-25 546 views
2

我正在用python製作截屏程序。我當前的問題是PIL.ImageGrab.grab()給了我2秒後的相同輸出。例如,我認爲我不清楚,在下面的程序中,幾乎所有的圖像都是相同的,即使在PIL.ImageGrab期間我正在移動屏幕,也具有相同的Image.tostring()值。搶奪循環正在執行。有沒有比PIL.ImageGrab.grab()更好的捕捉屏幕的方法?

>>> 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都非常慢,它是負面的。請告訴我,如果有更快的選擇。謝謝!

+0

如果你在X窗口,然後按[GStreamer的(http://gstreamer.freedesktop.org/ )及其[ximagesrc](http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-good-plugins/html/gst-plugins-good-plugins-ximagesrc.html)插件可以是一個好的解決方案。 –

+0

30 * 0.01 = 0.3秒。你確定在這段時間移動了窗戶嗎? – swang

+0

你想跨平臺的東西,還是特定於Windows的行嗎?你可以使用重型框架(如Qt或wx)嗎? – abarnert

回答

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,但更簡單的解決方案是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的。)

+0

我最後做了最後一個,除了WX模塊。 –

+0

後一種方法速度稍快,但產生更重的文件(對於1366x786分辨率圖像約爲5mb),並且僅限於'.bmp'圖像,與第一種方法不同。 – MadeOfAir

+0

@MadeOfAir:如果您已經使用PIL,您可以在保存之前輕鬆將'bmp'轉換爲'png'或任何其他您想要的內容。 (之所以是5MB,是因爲'bmp'文件是未壓縮的。)我相信也有更高級別的Win32 API方法用於從位圖對象創建PNG文件,但是您必須自己掃描MSDN或Google。 – abarnert