It takes a stream generated by an RTSP protocol and process it using a machine learning algorithm but it doesn't work well the algorithm is slow on processing frames so am trying to save the stream into a small videos but I get a very small frame rate 1FPS and when I try to save 1 min it give me only 15 s am using an IP camera hikvision here is the code am using.
import time
import cv2
import numpy as np
import cv2
import imutils
from imutils.object_detection import non_max_suppression
import datetime
import numpy as np
import cv2 as cv
capture_duration = 60
for i in range(1,4):
cap = cv2.VideoCapture("rtsp://admin:admin123#192.168.1.2:554/cam/realmonitor?channel=1&subtype=0")
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH) )
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT) )
size = (width, height)
fourcc = cv2.VideoWriter_fourcc(*'XVID')
name=( str(i)+'.mp4')
out = cv2.VideoWriter(name, fourcc, 10.0, size)
start_time = time.time()
while(int(time.time() - start_time) < capture_duration):
_, frame = cap.read()
#cv2.imshow('Recording...', frame)
out.write(frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
out.release()
cv2.destroyAllWindows()
Related
I have an application that needs to capture only a few frames per second from a webcam. Setting videowriter in the below code to 3 frames per second results in the webcam's normal framerate of approximately 30 fps being saved.
What are the options to save only the recorded 3 frames per second, and let the other 27 or so go? Thanks in advance.
import cv2
import numpy as np
import time
import datetime
import pathlib
import imutils
cap = cv2.VideoCapture(0)
if (cap.isOpened() == False):
print("Unable to read camera feed")
capture_duration = 15
frame_per_sec = 3
frame_width = 80
frame_height = 60
out = cv2.VideoWriter('C:\\Users\\student\\Desktop\\videoFile.avi',cv2.VideoWriter_fourcc('m','j','p','g'),frame_per_sec, (frame_width,frame_height))
start_time = time.time()
while( int(time.time() - start_time) < capture_duration ):
ret, frame = cap.read()
if ret==True:
frame = imutils.resize(frame, width=frame_width)
out.write(frame)
cv2.imshow('frame',frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
else:
break
cap.release()
out.release()
cv2.destroyAllWindows()
You set the FPS for the output via the VideoWriter,
but you didn't attempt to set the FPS for the input via the VideoCapture.
In order to do that you can try to call cv2.VideoCapture, with the cv2.CAP_PROP_FPS property after you create cap.
For example:
cap.set(cv2.CAP_PROP_FPS, 3)
However - note that the actual behavior is dependant on the specific capture device you are using. Some support only certain FPSs. See also this post regarding it: change frame rate in opencv 3.4.2.
If it does work you will be able to simplify your code a lot - just capture frames, process them and save (without any manual fps management).
This method programmatically sets frames per second. A 6.1mb file was created when frame rate was set for 30fps, and a 0.9mb file when set for 3fps.
#!/usr/bin/env python3
import cv2
import numpy as np
import time
import datetime
import pathlib
import imutils
cap = cv2.VideoCapture(0)
if (cap.isOpened() == False):
print("Unable to read camera feed")
capture_duration = 15
frame_per_sec = 30
prev = 0
frame_width = int(cap.get(3))
frame_height = int(cap.get(4))
out = cv2.VideoWriter('C:\\videoPy\\LZ\\'outpout.avi',cv2.VideoWriter_fourcc('m','j','p','g'),frame_per_sec, (frame_width,frame_height))
start_time = time.time()
while( int(time.time() - start_time) < capture_duration ):
#start fps
time_elapsed = time.time() - prev
while(time_elapsed > 1./frame_per_sec):
ret, frame = cap.read()
if not ret:
break
if time_elapsed > 1./frame_per_sec:
prev = time.time()
#end fps
if ret==True:
frame = imutils.resize(frame, width=frame_width)
out.write(frame)
cv2.imshow('frame',frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
else:
break
cap.release()
out.release()
cv2.destroyAllWindows()
I am trying to make a screen recorder using python opencv along with the mss library.
I can not get it to record a video. Whenever I stop the application - the file size becomes static such as sizes as for example 6kB - depending on the codec I used.
I have read that the capture must be the same size as the screen resolution which it is - but it still does not record.
I have also tried to use various codecs such as *'MP4V' but whatever I try - it does not save a proper recording.
I am using a MAC with a m1 processor if that matters.
import numpy as np
import cv2
import glob
from moviepy.editor import VideoFileClip
from mss import mss
from PIL import Image
import time
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('outpute.avi', fourcc, 60, (2560,1600))
with mss() as sct:
# Part of the screen to capture
monitor = {"top": 0, "left": 0, "width": 2560, "height": 1600}
while "Screen capturing":
last_time = time.time()
# Get raw pixels from the screen, save it to a Numpy array
img = np.array(sct.grab(monitor))
# Display the picture
cv2.imshow("OpenCV/Numpy normal", img)
# Write the image
out.write(img)
print("fps: {}".format(1 / (time.time() - last_time)))
# Press "q" to quit
if cv2.waitKey(25) & 0xFF == ord("q"):
cv2.destroyAllWindows()
break
this tutorial is working, good luck!
After debugging I noticed that monitor values has to be divided by 2 in order to work. No idea why this is the case - but I debugged it and saw that this was the case.
I also realized that I had to convert from BGR to RGB before I am writing it to a video file. Otherwise it won't work.
I also changed the format, but it was not part of the problem I do not believe.
Here is the working code
import numpy as np
import cv2
import glob
from moviepy.editor import VideoFileClip
from mss import mss
from PIL import Image
import time
import pyautogui
SCREEN_SIZE = tuple((2880,1800))
fourcc = cv2.VideoWriter_fourcc(*'MP4V')
out = cv2.VideoWriter('output.mp4', fourcc, 60, (SCREEN_SIZE))
with mss() as sct:
# Part of the screen to capture
monitor = {"top": 0, "left": 0, "width": 1440, "height": 900}
while True:
last_time = time.time()
img = np.array(sct.grab(monitor))
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
out.write(img)
print("fps: {}".format(1 / (time.time() - last_time)))
if cv2.waitKey(2) & 0xFF == ord("q"):
cv2.destroyAllWindows()
break
(Ignore the extra libraries I added)
I started by showing text on my video capture with the .putText() function. But I couldn't use a custom truetype font. So I looked it up. And I found out that I could do what I want with pillow. But it just doesn't work. This is my code:
import numpy as np
import cv2
from datetime import *
from bs4 import BeautifulSoup
import requests
from PIL import ImageFont, ImageDraw, Image
cap = cv2.VideoCapture(0)
while(True):
# Capture frame-by-frame
ret, frame = cap.read()
now = datetime.now()
current_time = now.strftime("%D: %H:%M:%S")
fontpath = "./Roboto-Light.ttf"
font = ImageFont.truetype(fontpath, 22)
img_pil = Image.fromarray(frame)
draw = ImageDraw.Draw(img_pil)
draw.text((120,660), current_time, font = ImageFont.truetype(fontpath, 48), fill = (168,98,0,0)) # Hour and Minute
cv2.namedWindow('frame', cv2.WINDOW_NORMAL)
cv2.setWindowProperty('frame', cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)
# Display the resulting frame
cv2.imshow('frame',frame)
if cv2.waitKey(20) & 0xFF == ord('q'):
break
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()
ยดยดยด
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 captured a video with my camera and fixed frame rate at 25 fps and tried to read it with OpenCV.
When I read video file with OpenCV, it plays but it plays very fast.
I want my program to play video at 25 fps. How to configure OpenCV to read video file at 25 fps?
My code:
import numpy as np
import cv2
cap = cv2.VideoCapture('vtest.avi')
while(cap.isOpened()):
ret, frame = cap.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
cv2.imshow('frame',gray)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
I found some solution.
I put a delay time to capture loop. I check delay before captures new image from video file. This is my solution code.
Thanks, everybody.
import numpy as np
import cv2
from time import time as timer
import sys
video = cv2.VideoCapture('2.avi')
fps = video.get(cv2.CAP_PROP_FPS)
fps /= 1000
framerate = timer()
elapsed = int()
cv2.namedWindow('ca1', 0)
while(video.isOpened()):
start = timer()
# print(start)
ret, frame = video.read()
cv2.imshow('ca1',frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
diff = timer() - start
while diff < fps:
diff = timer() - start
elapsed += 1
if elapsed % 5 == 0:
sys.stdout.write('\r')
sys.stdout.write('{0:3.3f} FPS'.format(elapsed / (timer() - framerate)))
sys.stdout.flush()
video.release()
cv2.destroyAllWindows()
Here is a working solution for this problem:
fps = vid.get(cv2.CAP_PROP_FPS)
while True:
now = time.time()
_, frame = vid.read()
#Do your thing
timeDiff = time.time() - now
if (timeDiff < 1.0/(fps)):
time.sleep(1.0/(fps) - timeDiff)
Since this is an existing video file, you can not change its FPS. However when you read the video file, you can change the interval you read between each frame. Here is my solution to read at a fixed frame rate 25 fps. Here is the code:
import numpy as np
import cv2
import sys
cap = cv2.VideoCapture('C:/Media/videos/Wildlife.wmv')
# Check if camera opened successfully
if (cap.isOpened()== False):
print("Error opening video stream or file")
fps = 25
#if you want to have the FPS according to the video then uncomment this code
#fps = cap.get(cv2.CAP_PROP_FPS)
#calculate the interval between frame.
interval = int(1000/fps)
print("FPS: ",fps, ", interval: ", interval)
# Read the video
while(cap.isOpened()):
ret, frame = cap.read()
if ret == True:
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
cv2.imshow('Frame',gray)
if cv2.waitKey(interval) & 0xFF == ord('q'):
break
# Break the loop
else:
break
cap.release()
cv2.destroyAllWindows()
Inspired by your answer:
while(cap.isOpened()):
ret, frame = cap.read()
now = time.time()
frameLimit = 2.0
#Do your stuff
timeDiff = time.time() - now
if (timeDiff < 1.0/(frameLimit)): time.sleep( 1.0/(frameLimit) - timeDiff )
you can add the required fps in place of 'fps' below
cap.set(cv2.cv.CV_CAP_PROP_FPS, fps)