在 Python 中从屏幕捕获视频数据
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/35097837/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Capture video data from screen in Python
提问by Adam Haile
Is there a way with Python (maybe with OpenCV or PIL) to continuously grab frames of all or a portion of the screen, at least at 15 fps or more? I've seen it done in other languages, so in theory it should be possible.
有没有办法使用 Python(可能使用 OpenCV 或 PIL)连续抓取整个或部分屏幕的帧,至少以 15 fps 或更高的速度抓取?我已经看到它用其他语言完成,所以理论上应该是可能的。
I do not need to save the image data to a file. I actually just want it to output an array containing the raw RGB data (like in a numpy array or something) since I'm going to just take it and send it to a large LED display (probably after re-sizing it).
我不需要将图像数据保存到文件中。我实际上只是希望它输出一个包含原始 RGB 数据的数组(比如在一个 numpy 数组或其他东西中),因为我将把它发送到一个大型 LED 显示器(可能在重新调整大小之后)。
回答by ibininja
You will need to use ImageGrab from Pillow (PIL) Library and convert the capture to numpy array. When you have the array you can do what you please with it using opencv. I converted capture to gray color and used imshow() as a demonstration.
您将需要使用 Pillow (PIL) 库中的 ImageGrab 并将捕获转换为 numpy 数组。当您拥有数组时,您可以使用 opencv 随心所欲地使用它。我将捕获转换为灰色并使用 imshow() 作为演示。
Here is a quick code to get you started:
这是一个快速入门的代码:
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()
you can plug an array there with the frequency you please to keep capturing frames. After that you just decode the frames. don't forget to add before the loop:
您可以以您喜欢的频率在那里插入一个阵列以继续捕获帧。之后,您只需解码帧。不要忘记在循环之前添加:
fourcc = cv2.VideoWriter_fourcc(*'XVID')
vid = cv2.VideoWriter('output.avi', fourcc, 6, (640,480))
and inside the loop you can add:
在循环内,您可以添加:
vid.write(frame) #the edited frame or the original img_np as you please
UPDATE
the end result look something like this (If you want to achieve a stream of frames that is. Storing as video just a demonstration of using opencv on the screen captured):
更新
最终结果看起来像这样(如果你想实现帧流。存储为视频只是在捕获的屏幕上使用 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()
Hope that helps
希望有帮助
回答by Neabfi
There is an other solution with msswhich provide much better frame rate. (Tested on a Macbook Pro with MacOS Sierra)
还有另一种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
回答by Sandzz
You can try this=>
你可以试试这个=>
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)
回答by Istiyak
I tried all of the above but it did not give me the real-time screen update. You can try this. This code is tested and worked successfully and also give you a good fps output. You can also judge this by each loop time it's needed.
我尝试了上述所有方法,但它没有给我实时屏幕更新。你可以试试这个。此代码经过测试并成功运行,并且还为您提供了良好的 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
回答by Reza Hosseini
I've tried ImageGrab
from PIL
and it gave me 20fps which is ok but using win32 libraries gave me +40fps which is amazing!
我已经尝试过ImageGrab
了PIL
,它给了我 20fps,这还可以,但是使用 win32 库给了我 +40fps,这太棒了!
I used thiscode by Frannecklp but it didn't work just fine so I needed to modify it:
我使用了 Frannecklp 的这段代码,但它不能正常工作,所以我需要修改它:
-Firstly pip install pywin32
in case using the libraries
- 首先是pip install pywin32
在使用库的情况下
-import the libraries like this instead:
- 像这样导入库:
import cv2
import numpy as np
from win32 import win32gui
from pythonwin import win32ui
from win32.lib import win32con
from win32 import win32api
for geting a simple image screen do:
要获得简单的图像屏幕,请执行以下操作:
from grab_screen import grab_screen
import cv2
img = grab_screen()
cv2.imshow('frame',img)
and for getting frames:
和获取帧:
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
回答by szanyi krisztián
based on this post and others posts, i made something like this . Its taking a screenshot and writing into a video file without saving the img.
基于这篇文章和其他帖子,我做了这样的事情。它截取屏幕截图并写入视频文件而不保存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()
回答by mlz7
With all of the above solutions, I was unable to get a usable frame rate until I modified my code in the following way:
使用上述所有解决方案,我无法获得可用的帧速率,直到我按以下方式修改我的代码:
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
With this solution, I easily get 20+ frames/second.
使用此解决方案,我可以轻松获得 20+ 帧/秒。
For reference, check this link: OpenCV/Numpy example with mss
作为参考,请查看此链接:OpenCV/Numpy example with mss
回答by Sarath Ak
You can try this code as it is working for me. I've tested it on Linux
你可以试试这个代码,因为它对我有用。我已经在 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
Make sure that the following packages are installed:
确保安装了以下软件包:
Pillow, opencv-python, numpy, mss
枕头,opencv-python,numpy,mss
回答by Kushal Bhavsar
This task is very simple with opencv, we are just capturing screenshots in loop, and converting it into frames. I created timer for screenrecording, in start you have to enter how many seconds you want to record:) Here is the code.
这个任务使用 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()
So that's how you can use time in screen recording, you don't need to use imshow() because it shows infinitely our screen recording on-screen so output video looks weird.
所以这就是你如何在屏幕录制中使用时间,你不需要使用 imshow() 因为它在屏幕上无限显示我们的屏幕录制所以输出视频看起来很奇怪。