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.
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).
OpenCV provides a very simple interface to do this. Let's capture a video from the camera (I am using the built-in webcam on my laptop), convert it into grayscale video and display it. Just a simple task to get started. To capture a video, you need to create a VideoCapture object.
There is an other solution with mss which provide much better frame rate. (Tested on a Macbook Pro with MacOS Sierra)
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
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.
For reference, check this link: OpenCV/Numpy example with mss
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With