Screen Recorded Through Python Script is Too fast - python

I could record the screen, but whenever I play the video it is very fast. How can I solve this issue?
import pyautogui
import cv2
import numpy as np
resolution = (1920, 1080)
codec = cv2.VideoWriter_fourcc(*"XVID")
filename = "Recording.avi"
fps = 60.0
out = cv2.VideoWriter(filename, codec, fps, resolution)
cv2.namedWindow("Live", cv2.WINDOW_NORMAL)
cv2.resizeWindow("Live", 480, 270)
while True:
img = pyautogui.screenshot()
frame = np.array(img)
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
out.write(frame)
cv2.imshow('Live', frame)
if cv2.waitKey(1) == ord('q'):
break
time.sleep(1/30)
out.release()
cv2.destroyAllWindows()

There are a few things you can try to make the recorded video play at a normal speed. One possible solution is to reduce the number of frames per second (fps) that are being recorded. In your code, you are setting the fps value to 60.0, which is a very high value and may be causing the recorded video to play back too quickly. Try set fps to 25 or 30. Also you can try increasing the amount of time that the sleep() function is called, which will cause the loop to pause for a longer period of time between frames.

Related

opencv cv2.CAP_PROP_FPS cuts out parts of my image

I'm using opencv in python3 on a raspberry pi compute model 4 with two cameras. I want to capture the video from the camera with 90 fps. That works fine, but for whatever reason opencv decides to cut a lot from my image when I my desired fps exceeds 40, which is a problem for me.
A captured video from a camera with 40 fps (or lower)
The same camera with 41 fps (or higher)
Here is my code, right now it is just supposed to show a window with the video of the camera:
import cv2
import time
cam = cv2.VideoCapture(1)
cam.set(cv2.CAP_PROP_FPS, 41)
width = 640
height = 480
cam.set(cv2.CAP_PROP_FRAME_WIDTH, width)
cam.set(cv2.CAP_PROP_FRAME_HEIGHT, height)
while True:
check, frame = cam.read()
cv2.imshow('video', frame)
key = cv2.waitKey(1)
if key == 27:
break
cam.release()
cv2.destroyAllWindows()
I didn't find any useful options in the opencv documentation, so I hope you can help me.
I tried to lower the resolution but that didn't change anything.

Real time taking pictures with different exposure times and automatically with OpenCV

I'm trying to make a python program with OpenCV, which opens the webcam and takes several images with different exposures in real time (40ms,95ms,150ms) and averages them in the end.
I tried to create a loop in which I change the exposure time, update the rendering (frame) and save it in a list, but the problem is that the display remains static and the rendering hardly changes (which gives after merging the images an image whose exposure time is almost 40)
I supposed that after setting exposure time, the frame update needs some time so I added the method time.sleep to suspend the execution for 3 seconds, but it was in vain.
Here is my code
import numpy as np
import cv2
import os
import time
capture = cv2.VideoCapture(0, cv2.CAP_V4L2)
while True:
(grabbed, frame) = capture.read()
if not grabbed:
break
# Resize frame
width = 1500
height = 1000
dim = (width, height)
frame = cv2.resize(frame, dim, interpolation=cv2.INTER_AREA)
cv2.imshow('RGB', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
if cv2.waitKey(1) == ord('h') or cv2.waitKey(1) == ord('H'):
#repertory = input("Enter the name of the directory: ")
if not os.path.exists(repertory):
os.mkdir(repertory)
exposure = [40,95,150]
ims = []
for i in exposure:
capture.set(cv2.CAP_PROP_EXPOSURE, i) # Setting Exposure
(grabbed, frame) = capture.read() # Updating frame
if grabbed:
cv2.imshow('RGB', frame) #Display
ims.append(frame)
# Convert to numpy
ims = np.array([np.array(im) for im in ims])
# average et conversion en uint8
imave = np.average(ims, axis=0)
imave = imave.astype(np.uint8)
# image HDR
cv2.imwrite(repertory + '/' + repertory + '_HDR8.jpg', imave)
capture.release()
cv2.destroyAllWindows()
Is there an optimal solution that allows to take pictures with differents exposure time in real time and in an automatic way?

capturing fps drops with lower resolution opencv

I have a USB camera that is able to record 60 fps. I am using openCV with simple python code on Windows to capture some videos however it is not going all smoothly!
My main problem is that, if I set the [width, height] properties to the maximum the camera accepts it is able to record 60 fps just fine otherwise (i.e. any lower resolution) the recording/streaming will drop to 30 fps max (the recording will be so funny that is either sped up or slowed down to match the specified recording fps; i.e. if the resolution specified 320X240 and recording fps set to 60 and for 10 seconds the resultant video will be squashed to 5 seconds so basically sped up 2x!!)
I don't understand why exactly that happens? any ideas?
here is a snippet of the code:
import cv2
import os
import time
def readVideo(Did):
cap = cv2.VideoCapture(Did)
# cap.set(cv2.CAP_PROP_FPS, 60) # no matter if you specify or not it selects what suits!!
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 320) # 640 is maximum
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 240) # 480 is maximum
ret,frame = cap.read()
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('./output.avi', fourcc, 60.0, (320,240)) # (width,height) must match what is stated above in CAP!
while ret:
ret,frame = cap.read()
elapsed = time.time() - start
count = count + 1 # frame numbers
cv2.putText(frame,str(cfpsBacked), (25,15),font,fontScale,fontColor,lineType)
out.write(frame)
cv2.imshow('camera',frame)
if elapsed - tick >= 1:
print("Actual count:{}",count)
tick += 1
cfpsBacked = count
count = 0
if tick - 10 == 0: # just records 10 seconds
break
if cv2.waitKey(10) & 0xFF == ord('q'):
break
out.release()
cap.release()
cv2.destroyAllWindows() # destroy all the opened windows

How to maintain constant FPS when grabbing frames with opencv and python?

I am using OpenCV4 along with python 3 to open a webcam, grab the frames and display them in a window, just like the first code tutorial provided here. However, it takes a different amount of time grabbing different frames: sometimes it takes 0.01 s to grab, and sometimes it takes 0.33 s, which creates lags when showing the frames in the window.
Is there a way to force a constant time when grabbing frames so that i can see the video without lag? I think it is happening with OpenCV because when i use a default windows camera viewer to see the video it displays it normally.
What i already tried is wait for some time using time.sleep() before grabbing a frame again. But this does not help.
import numpy as np
import cv2
cap = cv2.VideoCapture(0)
while(True):
# Capture frame-by-frame
ret, frame = cap.read()
# Display the resulting frame
cv2.imshow('frame',gray)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()
One potential way is to set a timestamp within the loop and keep track of the time the last frame was shown. For instance, only once a certain amount of time has elapsed then you show the frame. At the same time, you constantly read frames to keep the buffer empty to ensure that you have the most recent frame. You don't want to use time.sleep() because it will freeze the program and not keep the buffer empty. Once the timestamp hits, you show the frame and reset the timestamp.
import cv2
import time
cap = cv2.VideoCapture(0)
# Timeout to display frames in seconds
# FPS = 1/TIMEOUT
# So 1/.025 = 40 FPS
TIMEOUT = .025
old_timestamp = time.time()
while(True):
# Capture frame-by-frame
ret, frame = cap.read()
if (time.time() - old_timestamp) > TIMEOUT:
# Display the resulting frame
cv2.imshow('frame',frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
old_timestamp = time.time()
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()
When working correctly, this app will be suspended at the read() call until the next frame from the streaming webcam is available. Smooth display depends on being able to execute whatever you may have added to the loop in less than the 1/FPS seconds. It also depends on the camera being UVC compliant and it may depend on the encoding algorithm being MJPEG, which is the case for most webcams. However the fact that you see delay up to 1/3 second is curious because that is a typical GOP period for mpeg or other inter-frame encoders.
If none of the above applies to your case then I suspect the problem is platform related rather than an OCV issue. Have you tried to duplicate the problem on another system?
I was facing a similar problem, and this is the solution I came up with. This would be the exact way to set a constant fps. This works on both live video and recorded video.
import cv2
import time
cap = cv2.VideoCapture('your video location')
initial_time = time.time()
to_time = time.time()
set_fps = 25 # Set your desired frame rate
# Variables Used to Calculate FPS
prev_frame_time = 0 # Variables Used to Calculate FPS
new_frame_time = 0
while True:
while_running = time.time() # Keep updating time with each frame
new_time = while_running - initial_time # If time taken is 1/fps, then read a frame
if new_time >= 1 / set_fps:
ret, frame = cap.read()
if ret:
# Calculating True FPS
new_frame_time = time.time()
fps = 1 / (new_frame_time - prev_frame_time)
prev_frame_time = new_frame_time
fps = int(fps)
fps = str(fps)
print(fps)
cv2.imshow('joined', frame)
initial_time = while_running # Update the initial time with current time
else:
total_time_of_video = while_running - to_time # To get the total time of the video
print(total_time_of_video)
break
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()

Reduced camera resolution but higher display window in python open cv

I am working on a project which requires to do face detection on raspberry pi. I have a USB camera to do this. The frame rate was apparently very slow. So, I scaled down the capture resolution using VideoCapture.set(). This decreased the resolution to 320, 214 as I set it. This increased the capture frame rate considerably but it the feed in displayed the feed on a window on 320 X 214. I want to keep the same capture resolution but I want higher size display window. I am just a beginner to python and open cv. Please help me do it. Below is the code I wrote for just a simple camera feed.
import numpy as np
import cv2
import time
cap = cv2.VideoCapture(-1)
cap.set(3, 320) #width
cap.set(4, 216) #height
cap.set(5, 15) #frame rate
time.sleep(2)
while(cap.isOpened()):
ret, frame = cap.read()
cv2.imshow("captured video", frame)
if cv2.waitKey(33) == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
If I understand you correctly, you want the display image to be a scaled up version of the original. If so, you just need cv2.resize
display_scale = 4
height, width = frame.shape[0:2]
height_display, width_display = display_scale * height, display_scale * width
# you can choose different interpolation methods
frame_display = cv2.resize(frame, (display_width, display_height),
interpolation=cv2.INTER_CUBIC)
cv2.imshow("captured video", frame_display)

Categories