簡體   English   中英

在 Python 中從屏幕捕獲視頻數據

[英]Capture video data from screen in Python

有沒有辦法使用 Python(可能使用 OpenCV 或 PIL)連續抓取整個或部分屏幕的幀,至少以 15 fps 或更高的速度抓取? 我已經看到它用其他語言完成,所以理論上應該是可能的。

我不需要將圖像數據保存到文件中。 我實際上只是希望它輸出一個包含原始 RGB 數據的數組(比如在一個 numpy 數組或其他東西中),因為我將把它發送到一個大型 LED 顯示器(可能在重新調整大小之后)。

還有另一種mss解決方案可以提供更好的幀速率。 (在裝有 MacOS Sierra 的 Macbook Pro 上測試)

import numpy as np
import cv2
from mss import mss
from PIL import Image

mon = {'left': 160, 'top': 160, 'width': 200, 'height': 200}

with mss() as sct:
    while True:
        screenShot = sct.grab(mon)
        img = Image.frombytes(
            'RGB', 
            (screenShot.width, screenShot.height), 
            screenShot.rgb, 
        )
        cv2.imshow('test', np.array(img))
        if cv2.waitKey(33) & 0xFF in (
            ord('q'), 
            27, 
        ):
            break

使用上述所有解決方案,我無法獲得可用的幀速率,直到我按以下方式修改我的代碼:

import numpy as np
import cv2
from mss import mss
from PIL import Image

bounding_box = {'top': 100, 'left': 0, 'width': 400, 'height': 300}

sct = mss()

while True:
    sct_img = sct.grab(bounding_box)
    cv2.imshow('screen', np.array(sct_img))

    if (cv2.waitKey(1) & 0xFF) == ord('q'):
        cv2.destroyAllWindows()
        break

使用此解決方案,我可以輕松獲得 20+ 幀/秒。

作為參考,請查看此鏈接: OpenCV/Numpy example with mss

您將需要使用 Pillow (PIL) 庫中的 ImageGrab 並將捕獲轉換為 numpy 數組。 當您擁有數組時,您可以使用 opencv 隨心所欲地使用它。 我將捕獲轉換為灰色並使用 imshow() 作為演示。

這是一個快速入門的代碼:

from PIL import ImageGrab
import numpy as np
import cv2

img = ImageGrab.grab(bbox=(100,10,400,780)) #bbox specifies specific region (bbox= x,y,width,height *starts top-left)
img_np = np.array(img) #this is the array obtained from conversion
frame = cv2.cvtColor(img_np, cv2.COLOR_BGR2GRAY)
cv2.imshow("test", frame)
cv2.waitKey(0)
cv2.destroyAllWindows()

您可以以您喜歡的頻率在那里插入一個陣列以繼續捕獲幀。 之后,您只需解碼幀。 不要忘記在循環之前添加:

fourcc = cv2.VideoWriter_fourcc(*'XVID')
vid = cv2.VideoWriter('output.avi', fourcc, 6, (640,480))

在循環內,您可以添加:

vid.write(frame) #the edited frame or the original img_np as you please

更新
最終結果看起來像這樣(如果你想實現幀流。存儲為視頻只是在捕獲的屏幕上使用 opencv 的演示):

from PIL import ImageGrab
import numpy as np
import cv2
while(True):
    img = ImageGrab.grab(bbox=(100,10,400,780)) #bbox specifies specific region (bbox= x,y,width,height)
    img_np = np.array(img)
    frame = cv2.cvtColor(img_np, cv2.COLOR_BGR2GRAY)
    cv2.imshow("test", frame)
    cv2.waitKey(0)
cv2.destroyAllWindows()

希望有幫助

基於這篇文章和其他帖子,我做了這樣的事情。 它截取屏幕截圖並寫入視頻文件而不保存img。

import cv2
import numpy as np
import os
import pyautogui

output = "video.avi"
img = pyautogui.screenshot()
img = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)
#get info from img
height, width, channels = img.shape
# Define the codec and create VideoWriter object
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter(output, fourcc, 20.0, (width, height))

while(True):
 try:
  img = pyautogui.screenshot()
  image = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)
  out.write(image)
  StopIteration(0.5)
 except KeyboardInterrupt:
  break

out.release()
cv2.destroyAllWindows()

你可以試試這個=>

import mss
import numpy

with mss.mss() as sct:
    monitor = {'top': 40, 'left': 0, 'width': 800, 'height': 640}
    img = numpy.array(sct.grab(monitor))
    print(img)

你可以試試這個代碼,因為它對我有用。 我已經在 Linux 上測試過了

import numpy as np
import cv2
from mss import mss
from PIL import Image

sct = mss()

while 1:
    w, h = 800, 640
    monitor = {'top': 0, 'left': 0, 'width': w, 'height': h}
    img = Image.frombytes('RGB', (w,h), sct.grab(monitor).rgb)
    cv2.imshow('test', cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR))
    if cv2.waitKey(25) & 0xFF == ord('q'):
        cv2.destroyAllWindows()
        break

確保安裝了以下軟件包:

枕頭,opencv-python,numpy,mss

如果有人正在尋找一種更簡單、更快捷的方式來使用mss庫抓取屏幕,那么請嘗試ScreenGear我的高性能視頻處理vidgar庫中的ScreenGear類。 只需在任何機器上編寫這幾行 python 代碼(在所有平台上測試,包括 Windows 10、MacOS Serra、Linux Mint)並享受線程屏幕投射。

# import required libraries
from vidgear.gears import ScreenGear
import cv2

# define dimensions of screen w.r.t to given monitor to be captured
options = {'top': 40, 'left': 0, 'width': 100, 'height': 100}

# open video stream with defined parameters
stream = ScreenGear(monitor=1, logging=True, **options).start()

# loop over
while True:

    # read frames from stream
    frame = stream.read()

    # check for frame if Nonetype
    if frame is None:
        break


    # {do something with the frame here}


    # Show output window
    cv2.imshow("Output Frame", frame)

    # check for 'q' key if pressed
    key = cv2.waitKey(1) & 0xFF
    if key == ord("q"):
        break

# close output window
cv2.destroyAllWindows()

# safely close video stream
stream.stop()

VidGear 庫文檔: https ://abhitronix.github.io/vidgear

ScreenGear API: https ://abhitronix.github.io/vidgear/latest/gears/screengear/overview/

更多示例: https : //abhitronix.github.io/vidgear/latest/gears/screengear/usage/

我嘗試了上述所有方法,但它沒有給我實時屏幕更新。 你可以試試這個。 此代碼經過測試並成功運行,並且還為您提供了良好的 fps 輸出。 您還可以根據需要的每個循環時間來判斷。

import numpy as np
import cv2
from PIL import ImageGrab as ig
import time

last_time = time.time()
while(True):
    screen = ig.grab(bbox=(50,50,800,640))
    print('Loop took {} seconds',format(time.time()-last_time))
    cv2.imshow("test", np.array(screen))
    last_time = time.time()
    if cv2.waitKey(25) & 0xFF == ord('q'):
        cv2.destroyAllWindows()
        break

這個任務使用 opencv 非常簡單,我們只是在循環中捕獲屏幕截圖,並將其轉換為幀。 我為屏幕錄制創建了計時器,開始時您必須輸入要錄制的秒數:) 這是代碼。

import cv2
import numpy as np
import pyautogui
from win32api import GetSystemMetrics
import time

#Take resolution from system automatically
w = GetSystemMetrics(0)
h =  GetSystemMetrics(1)
SCREEN_SIZE = (w,h)
fourcc = cv2.VideoWriter_fourcc(*"XVID")
out = cv2.VideoWriter("recording.mp4", fourcc, 20.0, (SCREEN_SIZE))
tim = time.time()
tp = int(input('How many times you want to record screen?->(Define value in Seconds): '))
tp = tp+tp
f = tim+tp
while True:
    img = pyautogui.screenshot()
    frame = np.array(img)
    frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    out.write(frame)
    tu = time.time()
    if tu>f:
        break
cv2.destroyAllWindows()
out.release()

所以這就是你如何在屏幕錄制中使用時間,你不需要使用 imshow() 因為它在屏幕上無限顯示我們的屏幕錄制所以輸出視頻看起來很奇怪。

我已經嘗試過來自PIL ImageGrab ,它給了我 20fps,這還可以,但是使用 win32 庫給了我 +40fps,這太棒了!

我使用了 Frannecklp 的這段代碼,但它不能正常工作,所以我需要修改它:

- 首先pip install pywin32以防使用庫

- 像這樣導入庫:

import cv2
import numpy as np
from win32 import win32gui
from pythonwin import win32ui
from win32.lib import win32con
from win32 import win32api

要獲得簡單的圖像屏幕,請執行以下操作:

from grab_screen import grab_screen
import cv2
img = grab_screen()
cv2.imshow('frame',img)

和獲取幀:

while(True):
#frame = grab_screen((0,0,100,100))
frame = grab_screen()
cv2.imshow('frame',frame)
if cv2.waitKey(1) & 0xFF == ord('q') or x>150:
    break

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM