web-dev-qa-db-ja.com

Pythonで画面からビデオデータをキャプチャする

Python(OpenCVまたはPILを使用)を使用して、少なくとも15 fps以上で画面のすべてまたは一部のフレームを継続的に取得する方法はありますか?他の言語なので、理論的には可能になるはずです。

画像データをファイルに保存する必要はありません。私は実際にそれを受け取って大きなLEDディスプレイに送信するので(おそらくサイズを変更した後)、生のRGBデータを含む配列(numpy配列など)を出力したいだけです。

12
Adam Haile

mss を使用する他のソリューションがあり、これによりフレームレートが大幅に向上します。 (MacOS Sierraを搭載したMacbook Proでテスト済み)

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

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

sct = mss()

while 1:
    sct.get_pixels(mon)
    img = Image.frombytes('RGB', (sct.width, sct.height), sct.image)
    cv2.imshow('test', np.array(img))
    if cv2.waitKey(25) & 0xFF == ord('q'):
        cv2.destroyAllWindows()
        break
18
Neabfi

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

[〜#〜] update [〜#〜]
最終結果は次のようになります(フレームのストリームを実現したい場合。キャプチャされた画面で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()

役立つことを願っています

10
ibininja

上記のすべてを試してみましたが、リアルタイムの画面更新は提供されませんでした。これを試すことができます。このコードはテストされ、正常に機能し、優れた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
3
Istiyak

これを試すことができます=>

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)
3
Sandzz

この投稿と他の投稿に基づいて、私はこのようなものを作りました。スクリーンショットを取り、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()
2

これを試すことができます。このコードは私のために働いています.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', np.array(img))
    if cv2.waitKey(25) & 0xFF == ord('q'):
        cv2.destroyAllWindows()
        break

次のパッケージがインストールされていることを確認してください

枕、opencv-python、numpy、mss

1
Sarath Ak

上記のすべてのソリューションでは、次の方法でコードを変更するまで、使用可能なフレームレートを取得できませんでした。

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

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

sct = mss()

while 1:

    sct_img = sct.grab(bbox)
    cv2.imshow('screen', np.array(sct_img))

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

このソリューションを使用すると、20フレーム/秒を簡単に取得できます。

参考のため、次のリンクを確認してください: https://python-mss.readthedocs.io/examples.html

1
Markoe7

ImageGrabからPILを試してみましたが、20fpsが得られましたが、win32ライブラリを使用すると+ 40fpsが得られました。

Frannecklpの this コードを使用しましたが、うまく機能しなかったため、変更する必要がありました。

-まず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
0
Reza Hosseini