Screen Capture with OpenCV and Python-2.7 - python

I'm using Python 2.7 and OpenCV 2.4.9.
I need to capture the current frame that is being shown to the user and load it as an cv::Mat object in Python.
Do you guys know a fast way to do it recursively?
I need something like what's done in the example below, that captures Mat frames from a webcam recursively:
import cv2
cap = cv2.VideoCapture(0)
while(cap.isOpened()):
ret, frame = cap.read()
cv2.imshow('WindowName', frame)
if cv2.waitKey(25) & 0xFF == ord('q'):
cap.release()
cv2.destroyAllWindows()
break
In the example it's used the VideoCapture class to work with the captured image from the webcam.
With VideoCapture.read() a new frame is always being readed and stored into a Mat object.
Could I load a "printscreens stream" into a VideoCapture object? Could I create a streaming of my computer's screen with OpenCV in Python, without having to save and delete lots of .bmp files per second?
I need this frames to be Mat objects or NumPy arrays, so I can perform some Computer Vision routines with this frames in real time.

That's a solution code I've written using #Raoul tips.
I used PIL ImageGrab module to grab the printscreen frames.
import numpy as np
from PIL import ImageGrab
import cv2
while(True):
printscreen_pil = ImageGrab.grab()
printscreen_numpy = np.array(printscreen_pil.getdata(),dtype='uint8')\
.reshape((printscreen_pil.size[1],printscreen_pil.size[0],3))
cv2.imshow('window',printscreen_numpy)
if cv2.waitKey(25) & 0xFF == ord('q'):
cv2.destroyAllWindows()
break

I had frame rate problems with other solutions, mss solve them.
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

This is the updated answer for the answer by #Neabfi
import time
import cv2
import numpy as np
from mss import mss
mon = {'top': 160, 'left': 160, 'width': 200, 'height': 200}
with mss() as sct:
# mon = sct.monitors[0]
while True:
last_time = time.time()
img = sct.grab(mon)
print('fps: {0}'.format(1 / (time.time()-last_time)))
cv2.imw('test', np.array(img))
if cv2.waitKey(25) & 0xFF == ord('q'):
cv2.destroyAllWindows()
break
And to save to a mp4 video
import time
import cv2
import numpy as np
from mss import mss
def record(name):
with mss() as sct:
# mon = {'top': 160, 'left': 160, 'width': 200, 'height': 200}
mon = sct.monitors[0]
name = name + '.mp4'
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
desired_fps = 30.0
out = cv2.VideoWriter(name, fourcc, desired_fps,
(mon['width'], mon['height']))
last_time = 0
while True:
img = sct.grab(mon)
# cv2.imshow('test', np.array(img))
if time.time() - last_time > 1./desired_fps:
last_time = time.time()
destRGB = cv2.cvtColor(np.array(img), cv2.COLOR_BGRA2BGR)
out.write(destRGB)
if cv2.waitKey(25) & 0xFF == ord('q'):
cv2.destroyAllWindows()
break
record("Video")

Here's the Python 3 Implementation
This Function finds the Application in the List of Running Applications:
def capture_dynamic():
toplist, winlist = [], []
def enum_cb(hwnd, results):
winlist.append((hwnd, win32gui.GetWindowText(hwnd)))
win32gui.EnumWindows(enum_cb, toplist)
wnd = [(hwnd, title) for hwnd, title in winlist if 'spotify' in title.lower()]
if wnd:
wnd = wnd[0]
hwnd = wnd[0]
bbox = win32gui.GetWindowRect(hwnd)
img = ImageGrab.grab(bbox)
return img
else:
return None
This Function Displays the Images until the Letter 'q' is pressed:
import cv2
import numpy as np
while(True):
# Dynamic Version
screen_grab = capture_dynamic()
if(screen_grab == None):
print("No Window Found! Please Try Again")
break
screen_grab = np.array(screen_grab)
cv2.imshow('window',cv2.cvtColor(screen_grab, cv2.COLOR_BGR2RGB))
if cv2.waitKey(25) & 0xFF == ord('q'):
cv2.destroyAllWindows()
break
Make sure the Application you want to capture should be in the Foreground and not behind any other Application
Please Upvote!

Related

Why does my image taken with OpenCV appear smaller than that of libcamera?

I am currently working on a project which makes use of a Raspberry Pi and its Camera Module v2.1.
I need to scan some barcodes with the camera of which I am using the OpenCV and pyzbar libraries.
I am running into some trouble with the image that OpenCV is returning, example below:
Image returned from running libcamera-hello:
Image returned from running my script:
As you can see the images are very different, the OpenCV image is more zoomed in.
I've tried resizing the image and even changing the size of the frame but it doesn't seem to help, the image just gets stretched!
Does anyone have any ideas on why this might be happening?
My script for capturing the images is below:
import cv2
from pyzbar import pyzbar
from gpiozero import Button
from readBarcodeData import read_text
button = Button(25)
def read_barcodes(frame):
barcodes = pyzbar.decode(frame)
for barcode in barcodes:
x, y , w, h = barcode.rect
barcode_info = barcode.data.decode('utf-8')
cv2.rectangle(frame, (x, y),(x+w, y+h), (0, 255, 0), 2)
with open("barcode_result.txt", mode ='w') as file:
file.write(str(barcode_info).replace("'", ""))
return frame
def main():
while True:
if button.is_pressed:
camera = cv2.VideoCapture(0)
ret, frame = camera.read()
while ret:
ret, frame = camera.read()
frame = read_barcodes(frame)
cv2.imshow('Barcode Scanner', frame)
if cv2.waitKey(0) & 0xFF == 27:
break
break
camera.release()
cv2.destroyAllWindows()
read_text()
if __name__ == '__main__':
main()
EDIT:
I have also tried capturing an image using the following code:
import cv2
vid = cv2.VideoCapture(0)
while(True):
# Capture the video frame
ret, frame = vid.read()
# Display the resulting frame
cv2.imshow('frame', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# After the loop release the cap object
vid.release()
# Destroy all the windows
cv2.destroyAllWindows()
But I still get a cropped image.
EDIT 2:
Returned properties from the video capture:
CV_CAP_PROP_FRAME_WIDTH: '640.0'
CV_CAP_PROP_FRAME_HEIGHT : '480.0'
[ WARN:0] global /tmp/pip-wheel-j62hpwu1/opencv-python_19cf39855c924932a2df50dd2b502cd2/opencv/modules/videoio/src/cap_v4l.cpp (1911) getProperty VIDEOIO(V4L2:/dev/video0): Unable to get camera FPS
CAP_PROP_FPS : '-1.0'
CAP_PROP_POS_MSEC : '911170.05'
CAP_PROP_FRAME_COUNT : '-1.0'
CAP_PROP_BRIGHTNESS : '-1.0'
CAP_PROP_CONTRAST : '-1.0'
CAP_PROP_SATURATION : '-1.0'
CAP_PROP_HUE : '-1.0'
CAP_PROP_GAIN : '-1.0'
CAP_PROP_CONVERT_RGB : '1.0'
I managed to "fix" this by using the PiCamera library to capture the image and then run it through cv2:
Code for reading in PiCamera image is below:
import cv2
from time import sleep
from pyzbar import pyzbar
from gpiozero import Button
from picamera.array import PiRGBArray
import picamera
from readBarcodeData import read_text
button = Button(25)
def read_barcodes(frame):
barcodes = pyzbar.decode(frame)
for barcode in barcodes:
x, y , w, h = barcode.rect
barcode_info = barcode.data.decode('utf-8')
cv2.rectangle(frame, (x, y),(x+w, y+h), (0, 255, 0), 2)
with open("barcode_result.txt", mode ='w') as file:
file.write(str(barcode_info).replace("'", ""))
return frame
def main():
while True:
if button.is_pressed:
with picamera.PiCamera() as camera:
rawCapture = PiRGBArray(camera)
#camera.resolution = (3280, 2464)
camera.start_preview()
#sleep(1)
camera.capture(rawCapture, format="bgr")
img = rawCapture.array
#camera = cv2.VideoCapture(0)
#ret, frame = camera.read()
ret = True
while ret:
#ret, frame = img
frame = read_barcodes(img)
#cv2.imshow('Barcode Scanner', frame)
#print(frame.shape)
#if cv2.waitKey(0) & 0xFF == 27:
#break
break
cv2.destroyAllWindows()
read_text()
if __name__ == '__main__':
main()
The image captured by PiCamera seems to return the full image with no cropping so works a treat.

Why is python screen recorder not creating .avi file?

I'm trying to make python screen recorder that outputs AVI file. The loop should stop after pressing 'q' but that doesn't work. When I interrupt the program with Ctrl + C, it doesn't output anything either. I'm using Mac OS.
import cv2
import numpy as np
import pyautogui
SCREEN_SIZE = (1440, 900)
fourcc = cv2.VideoWriter_fourcc(*"XVID")
out = cv2.VideoWriter("output2.avi", fourcc, 20.0, (SCREEN_SIZE))
while True:
img = pyautogui.screenshot()
frame = np.array(img)
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
out.write(frame)
cv2.imshow("screenshot", frame)
if cv2.waitKey(1) == ord("q"):
break
cv2.destroyAllWindows()
out.release()
I would very much appreciate your advice ;)
Here (OpenCV videowrite doesn't write video) i found the most commont problem is that it doesn't save if the resolution is wrong.
To be sure you are using the right resolution from your screen use SCREEN_SIZE = pyautogui.size()
The complete code would be:
import cv2 as cv2
import numpy as np
import pyautogui
SCREEN_SIZE = pyautogui.size() # changed this line
fourcc = cv2.VideoWriter_fourcc(*"XVID")
out = cv2.VideoWriter("output2.avi", fourcc, 20.0, SCREEN_SIZE)
while True:
img = pyautogui.screenshot()
frame = np.array(img)
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
out.write(frame)
cv2.imshow("screenshot", frame)
if cv2.waitKey(1) == ord("q"):
break
cv2.destroyAllWindows()
out.release()

OpenCV python process dead

.
I am using anaconda 4.8.3, spyder 4.1.3 and opencv-python 4.2.0.34.
When I am trying to read simple image, then the python process is suspend. when I am trying to read the video there is the same problem. After each run of program I must restart the kernel.
my code for image:
import cv2
img = cv2.imread("lena.png")
cv2.imshow("Output",img)
cv2.waitKey(0)
my code for video:
import cv2
frameWidth = 640
frameHeight = 480
cap = cv2.VideoCapture("test.mp4")
while True:
success, img = cap.read()
img = cv2.resize(img, (frameWidth, frameHeight))
cv2.imshow("Result", img)
if cv2.waitKey(1) and 0xFF == ord('q'):
break
The video and image are in the same folder as project.
Have you got any idea why this is happening?
Thanks for help.
Code for Image
import cv2
img = cv2.imread("lena.png")
cv2.imshow("Output",img)
cv2.waitKey(0)
cv2.destroyAllWindows()
Code for video
import cv2
frameWidth = 640
frameHeight = 480
cap = cv2.VideoCapture("test.mp4")
while True:
success, img = cap.read()
img = cv2.resize(img, (frameWidth, frameHeight))
cv2.imshow("Result", img)
if cv2.waitKey(1) and 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()

OpenCV putText does not work after flipping the image

I'd like to grab images from the camera and flip them left/right so that the view performs like a mirror. However, I also like to add some text to the view, but it turns out that after flipping the image using np.fliplr(frame), cv.putText does no longer work.
Here is my minimal example using python 3.5.2:
import numpy as np
import cv2
import platform
if __name__ == "__main__":
print("python version:", platform.python_version())
cap = cv2.VideoCapture(0)
while(True):
# Capture frame-by-frame
ret, frame = cap.read()
cv2.putText(frame,'Hello World : Before flip',(100, 100), cv2.FONT_HERSHEY_SIMPLEX, 1,(255,255,255),2,cv2.LINE_AA)
frame = np.fliplr(frame)
cv2.putText(frame,'Hello World : After flip',(100, 200), cv2.FONT_HERSHEY_SIMPLEX, 1,(255,255,255),2,cv2.LINE_AA)
# Process the keys
key = cv2.waitKey(1) & 0xFF
if key == ord('q'):
print("quit")
break
# show the images
cv2.imshow('frame',frame)
cap.release()
cv2.destroyAllWindows()
Resulting frame w/ flip:
Resulting frame w/o flip:
I suspect it's due to cv2.putText is not compatible with np.array which is the return value of np.fliplr(frame). I suggest that you use frame = cv2.flip(frame, 1) instead.
import numpy as np
import cv2
import platform
if __name__ == "__main__":
print("python version:", platform.python_version())
cap = cv2.VideoCapture(0)
while(True):
# Capture frame-by-frame
ret, frame = cap.read()
cv2.putText(frame,'Hello World : Before flip',(100, 100), cv2.FONT_HERSHEY_SIMPLEX, 1,(255,255,255),2,cv2.LINE_AA)
frame = cv2.flip(frame, 1)
cv2.putText(frame,'Hello World : After flip',(100, 200), cv2.FONT_HERSHEY_SIMPLEX, 1,(255,255,255),2,cv2.LINE_AA)
# Process the keys
key = cv2.waitKey(1) & 0xFF
if key == ord('q'):
print("quit")
break
# show the images
cv2.imshow('frame',frame)
cap.release()
cv2.destroyAllWindows()
Just flip the frame before putting the text:
frame = cv2.flip(frame, 1)
cv2.putText(...)

Stream video from drone Parrot 2.0. Python + cv2

I am trying to have access to the stream of my drone's camera.
Here my code:
import cv2
import numpy
import libardrone
drone = libardrone.ARDrone()
cap = drone.image
while(True):
cap = drone.image
if not cap:
continue
ret, frame = convert
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
cv2.imshow('frame',gray)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
It does not work. It does not open any frame where I can see the stream video of my drone's camera.
What's wrong? Do you have any suggestions?
Thank you!
import cv2
cam = cv2.VideoCapture('tcp://192.168.1.1:5555')
running = True
while running:
# get current frame of video
running, frame = cam.read()
if running:
cv2.imshow('frame', frame)
if cv2.waitKey(1) & 0xFF == 27:
# escape key pressed
running = False
else:
# error reading frame
print 'error reading video feed'
cam.release()
cv2.destroyAllWindows()
Try this code...This works for me.

Categories