When I try to capture a video screenshot of my screen in a region suddenly the .avi output file becomes a 7kb.
The is no error, so I do not know how to fix this
The output video is fine before selecting the region.
how can i fix this problem?
import cv2
import numpy as np
import pyautogui
# display screen resolution, get it from your OS settings
import tkinter as tk
from PIL.Image import Image
root = tk.Tk()
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
SCREEN_SIZE = (screen_width, screen_height)
fourcc = cv2.VideoWriter_fourcc(*"XVID")
# create the video write object
out = cv2.VideoWriter("output.avi", fourcc, 20.0, (SCREEN_SIZE))
while True:
# make a screenshot
img = pyautogui.screenshot(region=(350, 800, 500, 150))
# convert these pixels to a proper numpy array to work with OpenCV
frame = np.array(img)
# convert colors from BGR to RGB
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# write the frame
out.write(frame)
# show the frame
cv2.imshow("screenshot", frame)
# if the user clicks q, it exits
if cv2.waitKey(1) == ord("q"):
break
# make sure everything is closed when exited
cv2.destroyAllWindows()
out.release()
Related
This is the class:
import pyautogui
import cv2
import numpy as np
class VidRec:
def screen(self,fps=12.0,time=10):
SCREEN_SIZE = tuple(pyautogui.size())
fourcc = cv2.VideoWriter_fourcc(*"XVID")
out = cv2.VideoWriter("output.avi", fourcc, self.fps, (SCREEN_SIZE))
for i in range(int(self.time * self.fps)):
img = pyautogui.screenshot()
# convert these pixels to a proper numpy array to work with OpenCV
frame = np.array(img)
# convert colors from BGR to RGB
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# write the frame
out.write(frame)
# show the frame
# cv2.imshow("screenshot", frame)
# if the user clicks q, it exits
if cv2.waitKey(1) == ord("q"):
break
# make sure everything is closed when exited
cv2.destroyAllWindows()
out.release()
How I call it:
import tasks
p = tasks.VidRec()
p.screen()
I get an error even though I made default parameters in the class "def screen(self,fps=12.0,time=10):"
out = cv2.VideoWriter("output.avi", fourcc, self.fps, (SCREEN_SIZE))
AttributeError: 'VidRec' object has no attribute 'fps'
So , basically I want to design an app that record the screen not by capturing the screen as below
import datetime
from PIL import ImageGrab
import numpy as np
import cv2
time_stamp = datetime.datetime.now().strftime('%Y-%m-%d %H-%M-%S')
file_name = f'{time_stamp}.mp4'
fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v')
captured_video = cv2.VideoWriter(file_name, fourcc, 20.0, (630, 330))
while True:
img = ImageGrab.grab(bbox=(0, 0, 630, 330))
img_np = np.array(img)
img_final = cv2.cvtColor(img_np, cv2.COLOR_BGR2RGB)
cv2.imshow("Screen Recorder", img_final)
captured_video.write(img_final)
if cv2.waitKey(10) == ord('q'):
break
It give the screen capturing but I need to record a specific process
Like
I want to record the screen output of
process 31328
Nothing else. Means while recording the screen the pop ups or any mini windows or any floating window opened during the recording would not capture in our screen recorder.
I am thinking that the Linux will throw the output on screen like
We print ('hello'). We should grab that output before it reaches on screen and record it. Is it possible?
I have written a code to record the screen recorder using python but when i see the output then i found that its fps is very low .Is there any better code than mine to increase the fps of the screen recorder.
If yes then please reply.
Here is mine code:-
import cv2
import numpy as np
import pyautogui
import datetime
# display screen resolution, get it from your OS settings
SCREEN_SIZE = (1366, 768)
# define the codec
fourcc = cv2.VideoWriter_fourcc(*"XVID")
# create the video write object
now = datetime.datetime.now().strftime('%Y-%m-%d_%H-%M-%S')
out = cv2.VideoWriter("screen recorder"+now+".avi", fourcc, 5.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 the user clicks q, it exits
if cv2.waitKey(1) == ord("q"):
break
cv2.destroyAllWindows()
out.release()
img = pyautogui.screenshot(region=(0, 0, 300, 400))
The third parameter to the cv2.VideoWriter constructor is the frame rate (https://docs.opencv.org/3.4/dd/d9e/classcv_1_1VideoWriter.html#ac3478f6257454209fa99249cc03a5c59). Currently, you have it set to 5.0. For example, for 30 fps, instantiate the VideoWriter with:
out = cv2.VideoWriter("screen recorder"+now+".avi", fourcc, 30.0, (SCREEN_SIZE))
EDIT: In order to also read in images at the correct framerate, we can pause the while loop using the waitKey function. We can re-write the OP's code like so:
import cv2
import numpy as np
import pyautogui
import datetime
import time
# display screen resolution, get it from your OS settings
SCREEN_SIZE = (1366, 768)
FRAME_RATE = 30.0 # desired frame-rate
# define the codec
fourcc = cv2.VideoWriter_fourcc(*"XVID")
# create the video write object
now = datetime.datetime.now().strftime('%Y-%m-%d_%H-%M-%S')
out = cv2.VideoWriter("screen recorder"+now+".avi", fourcc, FRAME_RATE, (SCREEN_SIZE))
while True:
st = time.time() # collect start time
img = pyautogui.screenshot()
frame = np.array(img)
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
out.write(frame)
cv2.imshow("screenshot", frame)
en = time.time() # collect end time
# calculate time to wait before next frame:
delay = max(0, (1 / FRAME_RATE - (en - st)) * 1000)
# if the user clicks q, it exits
if cv2.waitKey(delay) == ord("q"):
break
cv2.destroyAllWindows()
out.release()
img = pyautogui.screenshot(region=(0, 0, 300, 400))
Note: If collecting the frames is too slow (requires more than 1 / FRAMERATE seconds), then you may want to reduce the frame rate or the resolution.
I am trying to take a video stream, from a web camera and detect circles in it using HoughCircles(). But when ever I try to run the code the video takes along time to load the image, or wont load the image at all. Any help on how to get the code to do circle detection would be greatly appreciated.
Note: I'm not trying to do anything real time. I just want to get some basic circle detection to work on a video stream from my web camera.
Here's the code:
import cv2
import numpy as np
import sys
cap = cv2.VideoCapture(0)
width = 320
height = 240
dim = (width, height)
while(True):
gray = cv2.medianBlur(cv2.cvtColor(cap.read()[1], cv2.COLOR_BGR2GRAY),5)
resized = cv2.resize(gray,dim,interpolation = cv2.INTER_AREA)
edges = cv2.Canny(gray,100,200)
circ = cv2.HoughCircles(resized,cv2.HOUGH_GRADIENT,1,30,param1=50,param2=75,
minRadius=0,maxRadius=0)
cv2.imshow('video',resized)
if circ is not None:
circ = np.uint16(np.around(circ))[0,:]
print(circ)
for j in circ:
cv2.circle(resized, (j[0], j[1]), j[2], (0, 255, 0), 2)
cv2.imshow('video',resized)
if cv2.waitKey(1)==27:# esc Key
break
cap.release()
cv2.destroyAllWindows()
Again thanks for any help.
OK I've Figured it out. I had to reduce mess around with the parameters in HoughCircles. I've changed
circ = cv2.HoughCircles(resized,cv2.HOUGH_GRADIENT,1,30,param1=50,param2=75, minRadius=0,maxRadius=0)
to
cv2.HoughCircles(resized,cv2.HOUGH_GRADIENT,1,50,param1=50,param2=35, minRadius=0,maxRadius=0)
This allows the code to display the video stream while detecting circles at a reasonable frame rate. Also thanks #ZdaR for the help.
Here's the code that works
import cv2
import numpy as np
import serial
cap = cv2.VideoCapture(1)
width = 320
height = 240
dim = (width, height)
while(True):
gray = cv2.medianBlur(cv2.cvtColor(cap.read()[1], cv2.COLOR_BGR2GRAY),5)
resized = cv2.resize(gray,dim,interpolation = cv2.INTER_AREA)
circ = cv2.HoughCircles(resized,cv2.HOUGH_GRADIENT,1,50,param1=50,param2=35,
minRadius=0,maxRadius=0)
cv2.imshow('video',resized)
if circ is not None:
circ = np.uint16(np.around(circ))[0,:]
print(circ)
for j in circ:
cv2.circle(resized, (j[0], j[1]), j[2], (0, 255, 0), 2)
cv2.imshow('video',resized)
if cv2.waitKey(1)==27:# esc Key
break
cap.release()
cv2.destroyAllWindows()
How do I use python, mss, and opencv to capture my computer screen and save it as an array of images to form a movie? I am converting to gray-scale so it can be a 3 dimensional array. I would like to store each 2d screen shot in a 3d array for viewing and processing. I am having a hard time constructing an array that saves the sequence of screen shots as well as plays back the sequence of screen shots in cv2.
Thanks a lot
import time
import numpy as np
import cv2
import mss
from PIL import Image
with mss.mss() as sct:
fps_list=[]
matrix_list = []
monitor = {'top':40, 'left':0, 'width':800, 'height':640}
timer = 0
while timer <100:
last_time = time.time()
#get raw pizels from screen and save to numpy array
img = np.array(sct.grab(monitor))
img=cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#Save img data as matrix
matrix_list[timer,:,:] = img
#Display Image
cv2.imshow('Normal', img)
fps = 1/ (time.time()-last_time)
fps_list.append(fps)
#press q to quit
timer += 1
if cv2.waitKey(25) & 0xFF == ord('q'):
cv2.destroyAllWindows()
break
#calculate fps
fps_list = np.asarray(fps_list)
print(np.average(fps_list))
#playback image movie from screencapture
t=0
while t < 100:
cv.imshow('Playback',img_matrix[t])
t += 1
A clue perhaps, save screenshots into a list and replay them later (you will have to adapt the sleep time):
import time
import cv2
import mss
import numpy
with mss.mss() as sct:
monitor = {'top': 40, 'left': 0, 'width': 800, 'height': 640}
img_matrix = []
for _ in range(100):
# Get raw pizels from screen and save to numpy array
img = numpy.array(sct.grab(monitor))
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Save img data as matrix
img_matrix.append(img)
# Display Image
cv2.imshow('Normal', img)
# Press q to quit
if cv2.waitKey(25) & 0xFF == ord('q'):
cv2.destroyAllWindows()
break
# Playback image movie from screencapture
for img in img_matrix:
cv2.imshow('Playback', img)
# Press q to quit
if cv2.waitKey(25) & 0xFF == ord('q'):
cv2.destroyAllWindows()
break
use collections.OrderedDict() to saves the sequence
import collections
....
fps_list= collections.OrderedDict()
...
fps_list[timer] = fps