CV2.VideoWriter save new video with 5s interval - python

I was trying to save video from an streaming URL for every 1 min duration and the filename will increment.
so the cam is streaming I have loaded the video with cv2 and start writing the first file ,after 5s the file will save and another file will create and the frame will write on this file, file name should increment ex. "filename1.avi", "filename2.avi" etc.
But the video is save on same file and didn't create another video file.
def show_video_stream(rtsp_address: str):
"""Visualize stream given an rtsp address.
Args:
rtsp_address (str): IP address with rtsp protocol.
Example: 'rtsp://{user}:{password}#{IP}:{port}'
"""
current_time_in_second = int(time.time())
cap = cv2.VideoCapture(rtsp_address)
frame_width = int(cap.get(3))
frame_height = int(cap.get(4))
size = (frame_width, frame_height)
frame_name = rtsp_address.split('#')[1]
cv2.namedWindow(frame_name, cv2.WINDOW_NORMAL)
video_count = 0 #here result is should be dynamic so new file should initiate after every 5s.
result = cv2.VideoWriter('video_live_feed' + str(video_count) + ".avi",
cv2.VideoWriter_fourcc(*'MJPG'),
5, size)
while (True):
ret, frame = cap.read()
cv2.imshow(frame_name, frame)
# save_one_second_file(frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
result.write(frame)
after_time_in_second = int(time.time())
print(current_time_in_second)
print(after_time_in_second)
#calculating the time of the video for 5 s
if after_time_in_second - current_time_in_second == 5:
current_time_in_second = after_time_in_second
video_count = video_count + 1
print("release korlam")
result.release()
cap.release()
cv2.destroyAllWindows()
if __name__ == "__main__":
with concurrent.futures.ProcessPoolExecutor() as executor:
executor.map(show_video_stream, ip_pool)
I have used result.release() to release the write of the cap, and increment the value of the video_count variable.
I want to save video file duration 5s from an streaming video. if the video file is 15s long i will have 3 video file with 5s duration.

At the moment you only open 1 video file, with a name corresponding to video_count == 0, just before the main capture loop.
When you detect that 5 seconds have passed you increment the video_count but do not open a new video file.
I advise you to add a function to do that, and call it whenever you need to open a new file:
def open_writer(video_count):
return cv2.VideoWriter('video_live_feed' + str(video_count) + ".avi",
cv2.VideoWriter_fourcc(*'MJPG'),
5, size)
You can use it before the capture loop:
result = open_writer(video_count)
As well as after releasing the previous writer every 5 seconds:
video_count = video_count + 1
result.release()
result = open_writer(video_count) # reopen the writer with a new filename
In addition you can consider to change the 5 seconds condition to:
#------------------------------------------------vv---
if after_time_in_second - current_time_in_second >= 5:
This will make your code more robust to missing the exact second (even though at reasonable capture FPS it will probably happen rarely if at all).

Related

Problem with naming a camera captured file in a while-loop

This is my code, It takes a picture via webcam and saves it in a folder I specify. The name is then "day-time_0/1/2/3.jpg".
The problem is I would like to have it without "_0/1/2/3". But these numbers are necessary for the loop I think at least. But if I take out this count it saves a picture and over saves it every time I want to make another picture in the same interface.
Is there a way that if I am in the same interface and take several pictures that I can save them again and again with the new current time?
import cv2
import os
import time
timestr = time.strftime("%Y%m%d-%H%M%S")
def save_frame_camera_key(device_num, dir_path, basename, ext='jpg', delay=1, window_name='frame'):
cap = cv2.VideoCapture(device_num)
if not cap.isOpened():
return
os.makedirs(dir_path, exist_ok=True)
base_path = os.path.join(dir_path, basename)
n = 0
while True:
ret, frame = cap.read()
cv2.imshow(window_name, frame)
key = cv2.waitKey(delay) & 0xFF
if key == ord('c'):
cv2.imwrite('{}_{}.{}'.format(base_path, **n**, ext), frame)
** n += 1**
elif key == ord('q'):
break
cv2.destroyWindow(window_name)
save_frame_camera_key(0, 'data/temp', timestr)
As i said i tried deleting the count. Didnt work. Ive tried it with an different capture Code and it didnt work.

Read and extract keypoints from folder of videos opencv

I have a list of videos (10 sec each) in a folder and I'm trying to loop through each action video to extract keypoints and save them as json files.
path = "path to video folder"
for file in os.listdir(path):
cap = cv2.VideoCapture(path+file)
while cap.isOpened():
try:
ret, frame = cap.read()
I ran into a problem where the extracted data has some keypoints from other videos, and I just want to run this code, end with the stop time for the video is done, pause, start next video. How can I help correct this?
If you want to process multiple videos in turn you can check the ret (success) value of cap.read() to detect the end of each file. Here is a basic example you can start with:
import os
import cv2
path = "videos"
for file in os.listdir(path):
print(file)
cap = cv2.VideoCapture(path + '/' + file)
count = 0
while True:
ret, frame = cap.read()
# check for end of file
if not ret:
break
# process frame
count += 1
print(f"{count} frames read")
cap.release()

Python - How to save the *exact* video stream that my USB cam is streaming live?

I am using OpenCV 4.5.0 to stream a video from a USB webcam using the VideoCapture method of OpenCV. Here is the snippet of how I am reading the frames, processing them and then writing them to a file.
import cv2
import numpy as np
dev_id = 0
stream = cv2.VideoCapture(dev_id, cv2.CAP_V4L2)
fourcc = cv2.VideoWriter_fourcc(*'FMP4')
vpath = 'test.mp4'
writer = cv2.VideoWriter(vpath, fourcc, 30, (640,480), isColor=True)
if stream.isOpened():
rval, frame = stream.read()
else:
print('Could not open the stream for reading')
if not writer.isOpened():
print('Could not open the file for writing')
i = 0
while rval:
i += 1
with open('frame_{}.pkl'.format(i),'wb') as fout:
np.save(fout, frame)
writer.write(frame)
rval, frame = stream.read()
key = cv2.waitkey(1)
if key == 27: # ESC
break
writer.release()
My goal is to then read the video file that was written above and reproduce the exact same frames that I got during the live stream. I have not been able to find a way to write the live video stream to a file such that the frame extracted from the written video file matches exactly with the frame stored in the numpy array. In addition to FMP4 as the FourCC, I tried with MJPG, MP4V, XVID, LAGS, H264, MPG4. No luck so far. What am I doing wrong?
Here is how I am reading the video and comparing the frames:
vc = cv2.VideoCapture(vpath)
if vc.isOpened():
rval, frame_read = vc.read()
else:
print('Could not read video from the file')
j = 0
while rval:
j += 1
with open('frame_{}.pkl'.format(j),'rb') as fin:
frame_orig = np.load(fin)
if np.array_equal(frame_read, frame_orig):
print('same')
else:
print('different')
rval, frame_read = vc.read()
I have also tested if this is simply the indexing mismatch between the video writer and the video reader. It is not. This really looks like the difference caused by the codec used to write the frame to a file. Is there no codec which writes the same exact frame that is emitted by VideoCapture.read()?

Python: take screenshot from video

The idea is that, user should be able to load a video from their local machine and tell the program to take a screenshot from the video every 5sec or 30sec. Is there any library to help me with this task? Any idea from how to proceed would be helpful.
install opencv-python (which is an unofficial pre-built OpenCV package for Python) by issuing the following command:
pip install opencv-python
# Importing all necessary libraries
import cv2
import os
import time
# Read the video from specified path
cam = cv2.VideoCapture("C:/Users/User/Desktop/videoplayback.mp4")
try:
# creating a folder named data
if not os.path.exists('data'):
os.makedirs('data')
# if not created then raise error
except OSError:
print('Error: Creating directory of data')
# frame
currentframe = 0
while (True):
time.sleep(5) # take schreenshot every 5 seconds
# reading from frame
ret, frame = cam.read()
if ret:
# if video is still left continue creating images
name = './data/frame' + str(currentframe) + '.jpg'
print('Creating...' + name)
# writing the extracted images
cv2.imwrite(name, frame)
# increasing counter so that it will
# show how many frames are created
currentframe += 1
else:
break
# Release all space and windows once done
cam.release()
cv2.destroyAllWindows()
the above answer is partially right but time.sleep here does not help at all but rather it makes the process slower. however, if you want to take a screenshot at a certain time of a video you need to understand that every time you do "ret, frame = cam.read()" it reads the next frame of the video. every second in a video has a number of frames depends on the video. you get that number using:
frame_per_second = cam.get(cv2.CAP_PROP_FPS)
so if you need to take a screenshot of the 3rd second you can keep the iteration as is in the above answer and just add
if currentframe == (3*frame_per_second):
cv2.imwrite(name, frame)
this will take a screenshot of the first frame in the 3rd second.
#ncica & Data_sniffer solution remake
import cv2
import os
import time
step = 10
frames_count = 3
cam = cv2.VideoCapture('video/example.MP4')
currentframe = 0
frame_per_second = cam.get(cv2.CAP_PROP_FPS)
frames_captured = 0
while (True):
ret, frame = cam.read()
if ret:
if currentframe > (step*frame_per_second):
currentframe = 0
name = 'photo/frame' + str(frames_captured) + '.jpg'
print(name)
cv2.imwrite(name, frame)
frames_captured+=1
if frames_captured>frames_count-1:
ret = False
currentframe += 1
if ret==False:
break
cam.release()
cv2.destroyAllWindows()
#a generic function incorporating all the comments mentioned above.
def get_frames(inputFile,outputFolder,step,count):
'''
Input:
inputFile - name of the input file with directoy
outputFolder - name and path of the folder to save the results
step - time lapse between each step (in seconds)
count - number of screenshots
Output:
'count' number of screenshots that are 'step' seconds apart created from video 'inputFile' and stored in folder 'outputFolder'
Function Call:
get_frames("test.mp4", 'data', 10, 10)
'''
#initializing local variables
step = step
frames_count = count
currentframe = 0
frames_captured = 0
#creating a folder
try:
# creating a folder named data
if not os.path.exists(outputFolder):
os.makedirs(outputFolder)
#if not created then raise error
except OSError:
print ('Error! Could not create a directory')
#reading the video from specified path
cam = cv2.VideoCapture(inputFile)
#reading the number of frames at that particular second
frame_per_second = cam.get(cv2.CAP_PROP_FPS)
while (True):
ret, frame = cam.read()
if ret:
if currentframe > (step*frame_per_second):
currentframe = 0
#saving the frames (screenshots)
name = './data/frame' + str(frames_captured) + '.jpg'
print ('Creating...' + name)
cv2.imwrite(name, frame)
frames_captured+=1
#breaking the loop when count achieved
if frames_captured > frames_count-1:
ret = False
currentframe += 1
if ret == False:
break
#Releasing all space and windows once done
cam.release()
cv2.destroyAllWindows()
To add on data_sniffer's answer. I would recommend using round (Math function) on frame_per_second when checking as if the frame rate is a decimal number then it will go into an infinite loop.
The solutions provided do not work for me in several cases.
The FPS from cv2.CAP_PROP_FPS is a floating point value and the FPS rate of my testvid.mp4 was 23.976023976023978 according to this property.
When looping through current_frame / fps % 3, we will almost always have leftovers because of this floating point value. Same goes for (3*frame_per_second):, causing our imwrite to never be reached.
I solved this issue by using the same calculations, but storing the remainders and comparing those:
current_frame = 0
fps_calculator_previous = 0
while (True):
ret, frame = cam.read()
if ret:
# Still got video left.
file_name = f"./data_generation/out/{_fn}-{current_frame}.jpg"
fps_calculator = (current_frame / fps) % every_x_sec
if(fps_calculator - fps_calculator_previous < 0):
print("Found a frame to write!")
cv2.imwrite(file_name, frame)
fps_calculator_previous = fps_calculator
current_frame += 1
else:
break
This seems to work well for me with any value for both cv2.CAP_PROP_FPS as well as every_x_sec
My video was 18 minutes and 7 seconds long, and I captured 362 unique frames from that with every_x_sec set to 3.
Edited #ncica's code and noted that it is working fine.
import cv2
import os
import time
cam = cv2.VideoCapture("/path/to/videoIn.mp4")
try:
if not os.path.exists('data'):
os.makedirs('data')
except OSError:
print('Error: Creating directory of data')
intvl = 2 #interval in second(s)
fps= int(cam.get(cv2.CAP_PROP_FPS))
print("fps : " ,fps)
currentframe = 0
while (True):
ret, frame = cam.read()
if ret:
if(currentframe % (fps*intvl) == 0):
name = './data/frame' + str(currentframe) + '.jpg'
print('Creating...' + name)
cv2.imwrite(name, frame)
currentframe += 1
else:
break
cam.release()
cv2.destroyAllWindows()
The trick is it is looping frame-by-frame.
So, here we are capturing frames that we want and write disk as snapshot image file.
eg : If you want snapshot two second by two second intvl must be 2

Python OpenCV, can't write a video (.avi) to file

I'm writing a programme in Windows XP using Python and OpenCV that adds image frames captured from a webcam to a video (.avi), but only when a certain condition is met. For testing purposes this condition is time based, but this will change. The only problem is, my programme does not output anything. Everything seems to run fine, but then when I check for the .avi file that it should be outputting, there is nothing.
Here's my code. I've been told my style is a little unconventional, but hopefully you can see what I'm up to. Thank you in advance.
import cv, time ##Import modules
cv.NamedWindow("Experiment", cv.CV_WINDOW_AUTOSIZE) ##Open window
camera_index = 1
capture = cv.CaptureFromCAM(camera_index)
x = time.clock()+5
try:
while 1:
if time.clock() < x: ##Clock to capture 5 seconds of footage
frame = cv.QueryFrame(capture) ##Capture webcam frame
cv.ShowImage("Experiment", frame) ##Display image
writer = cv.CreateVideoWriter("C:\/test.avi", cv.CV_FOURCC('F', 'M', 'P', '4'),
24, (640, 480), 1) ##Write video file (codec = MPEG-4 - .avi)
if writer: ##Write frame to file
cv.WriteFrame(writer, frame)
if not writer: ##Failure to register video writer
print "Error: Video writer malfunction"
sys.exit(1)
cv.DestroyWindow("Experiment")
break
else:
if writer:
print "Video capture succeeded"
cv.DestroyWindow("Experiment")
camera_index += 1
capture = cv.CaptureFromCAM(-1)
break
c = cv.WaitKey(10)
if(c=="n"):
camera_index += 1
capture = cv.CaptureFromCAM(-1)
except:
print "Video capture failed" ##Total systems failure escape routine!!!
cv.DestroyWindow("Experiment")
--Edit--
If I change cv.CV_FOURCC('F', 'M', 'P', '4') in line 12 to "-1" a video is output, but it is 0 bytes.

Categories