Trim (remove frames from) live video from webcam using python - python

I have a webcam that captures video stream. After 30 seconds I want to remove 1 sec of the video from the start and keep capturing the video stream and so on. In short, I only want to save the latest 30 seconds of the live video.
OpenCV does not provide video processing
ffmpeg trims the video but creates a new output file, I don't want to keep copies.
#Create a video write before entering the loop
#Create a video write before entering the loop
video_writer = cv2.VideoWriter(
video_file, video_codec, fps, (int(cap.get(3)), int(cap.get(4)))
)
#video_file is the file being saved
start = time.time()
i=0
seconds='1'
while cap.isOpened():
ret, frame = cap.read()
if ret == True:
cv2.imshow("frame", frame)
if time.time() - start > 10:
print('video > 10 sec')
subprocess.call(['ffmpeg', '-i', video_file, '-ss', seconds, 'output.avi'])
break
# Write the frame to the current video writer
video_writer.write(frame)
if i%24 == 0:
cv2.imwrite('image'+str(i)+'.jpg',frame)
i+=1
if cv2.waitKey(1) & 0xFF == ord("q"):
break
else:
break
cap.release()
cv2.destroyAllWindows()
What I am looking for is how we can trip a live video and keep saving future frames so that the video don't exceed 30 seconds and keeps the latest frames.

You can use the segment muxer:
ffmpeg -i input -f segment -segment_time 30 -segment_wrap 2 -reset_timestamps 1 output_%d.avi
This will create two files: output_0.avi and output_1.avi. Every 30 seconds the output will alternate between these files and overwrite earlier versions.
You could use -segment_wrap 1 and only output 1 file, but you risk losing video. For example stopping recording at 32 seconds will leave you with a 2 second video instead of a 30 second video + a 2 second video.

Related

Python, OpenCV: stopping capture at end of file

(Using OpenCV 4.1)
I am trying to capture screenshots from videos. My intention is to have the script capture a frame every five minutes up to 20 captures.
My test video is 20 minutes long. Once the script loops 4 times, I want it to quit. However, it loops a 5th time and captures 2 seconds from the end of the video. Then it loops a 6th time and captures the same frame as the 4th loop. It keeps repeating these last two loops until there are 20 frames captured.
How do I get the script to recognize that it has reached the end of the video and stop?
Note: the last frame captured may not be the last frame in the video. For example, if the video is 23 minutes long, the last frame captured should be near the 20-minute mark.
import datetime
import sys
import time
from cv2 import cv2
def milsec_to_hr_min_sec(milliseconds): # Returned from CAP_PROP_POS_MSEC
ms = int(milliseconds)
seconds = str(int((ms / 1000) % 60))
minutes = str(int((ms / (1000 * 60)) % 60))
hours = str(int((ms / (1000 * 60 * 60)) % 24))
return hours, minutes, seconds
def FrameCapture(path): # Extract frame
cap = cv2.VideoCapture(path)
framerate = cap.get(cv2.CAP_PROP_FPS)
count = 1
framecount = 0
# checks whether frames were extracted
while True:
while count < 21 and framecount < cap.get(cv2.CAP_PROP_FRAME_COUNT):
# Capture frame every 5 minutes
framecount = count * framerate * 60 * 5
cap.set(1, framecount)
# capture frame at timestamp
success, image = cap.read()
if success:
cv2.imwrite(
path + " (screencap #%d).jpg" % count, image,
)
# Convert timestamp to hr:min:sec
hours, minutes, seconds = milsec_to_hr_min_sec(
cap.get(cv2.CAP_PROP_POS_MSEC)
)
print(
str(success)
+ " "
+ "Captured: screencap #{} at timestamp ".format(count)
+ hours
+ "h "
+ minutes
+ "m "
+ seconds
+ "s"
)
count += 1
if cv2.waitKey(1) & 0xFF == ord("q"):
break
else:
break
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()
print("Finished capture")
# Driver Code
if __name__ == "__main__":
# Calling the function
fn = "\\full\path\to\file"
FrameCapture(fn)
Please forgive the hack-y nature of my scripts. I pieced them together with parts found from searches.
At the beginning of the "while" loop you may use the following code:
ret, frames = cap.read()
if frames is None:
break
There are two ways of doing it:
Loop through a while(true) loop and break when frame.empty().
Obtain the frame count using: int nFrames = vid_cap.get(CAP_PROP_FRAME_COUNT); //Get the number of frames avaiable in the video and use a for_loop to loop through the frames.
This code will get all frames from your video
def get_list_frame_by_video(file_path_video):
vs = cv2.VideoCapture(file_path_video)
list_frame = []
print("____start load video____")
len_frames = int(vs.get(cv2.CAP_PROP_FRAME_COUNT))
while True:
is_cap, frame = vs.read()
if frame is None:
continue
list_frame.append(frame)
if len_frames == len(list_frame):
break
print("____complete load video____")
return list_frame
A simple way is:
sucess, img = cap.read()
if img is None:
print(' Successful process ')
break
You just have to add this line and process will be ended if 'cap' is empty

Multi-threading on python for running 2 inter-related threads simultaneously (or may be background processing)

I want VideoCapture function from opencv to work smoothly while processing frames from it in background. As processing requires 3-4 seconds so at that time capturing video hangs.
Hence, I need to run 2 threads, i.e., one capturing video and other processing its output and printing on screen.
My code till now:
age = None
while True:
ret, frame = cam.read()
if ret == True:
# do some processing (3-4 seconds)
age = process(frame)
fr = update_age(frame, age)
cv2.imshow('hello', fr)
if cv2.waitKey(1) == 27:
break
else:
print "error"
break
cv2.destroyAllWindows()
Hence, I need a way so that my 3rd line don't have to wait 3-4 seconds to update its frame, while processing frames and printing its output runs in background.
More Clarifications(mentioned in comments also):
I don't want to separate my threads, as one thread depends on output (frame) of other thread.I just want to run my threads separately
I am showing all frames on my screen using cv2.imshow(). Hence, I need every frame captured to let my screen look smooth (and not just hang on after every 4 seconds). And output of processing is shown on screen, i.e., once a output is generated it will remain there until next output is generated after 4 seconds. (It's like a person looking in camera and his age is showing on screen but if is updating after 4 seconds)
Here's one example with multiprocessing where you would capture frames and process them later:
from multiprocessing import Process
import time
frame_data = 0
def capture_video():
print('recording...')
return frame_data
def process_frame(frame_data):
time.sleep(3)
print(frame_data)
return frame_data
if __name__ == '__main__':
while True:
data = capture_video()
p = Process(target=process_frame, args=(frame_data,))
p.start()
time.sleep(0.1)
frame_data = frame_data + 1
Example Output (removed a few initial recording... printouts for conciseness):
recording...
recording...
recording...
recording...
recording...
recording...
0
recording...
1
recording...
2
recording...
3
recording...
4
recording...

cv2.VideoCapture on python

I am running the following code:
import numpy as np
import cv2
import os
count = 0
cap = cv2.VideoCapture("/home/simon/PROJECT/real_data/00000020.mp4")
while not cap.isOpened():
cap = cv2.VideoCapture("./00000020.mp4")
cv2.waitKey(1000)
print "Wait for the header"
pos_frame = cap.get(cv2.cv.CV_CAP_PROP_POS_FRAMES)
while True:
flag, frame = cap.read()
if flag:
# The frame is ready and already captured
cv2.imshow('video', frame)
pos_frame = cap.get(cv2.cv.CV_CAP_PROP_POS_FRAMES)
print str(pos_frame)+" frames"
else:
# The next frame is not ready, so we try to read it again
cap.set(cv2.cv.CV_CAP_PROP_POS_FRAMES, pos_frame-1)
print "frame is not ready"
# It is better to wait for a while for the next frame to be ready
cv2.waitKey(1000)
if cv2.waitKey(10) & 0xFF == 27:
break
if cap.get(cv2.cv.CV_CAP_PROP_POS_FRAMES) == cap.get(cv2.cv.CV_CAP_PROP_FRAME_COUNT):
# If the number of captured frames is equal to the total number of frames,
# we stop
break
if ret == True:
frame = cv2.VideoCapture.grab()
frame = 'frame%d' % count
cv2.imwrite('frame%d.png', frame)
count += 1
else:
print 'stopped at' + count
break
And whenever I run it, it loops on the while not loop, printing "wait for header".
There is never an error code or anything like that either.
I have tried to run it as a more simple piece of code, where it doesnt have all these checks, and again that doesn't throw any errors.
I am attempting to run this code to open a video, and then save the frames as png files throughout the video.
Does anyone spot any particular problems with the code?
Or alternatively does anyone know a piece of code that would do what i want more efficiently, as I have trawled through google searches and stack overflow a lot recently and haven't found anything
Thanks in advance
Panda
You need to include a couple of DLLs in your python directory in order to play videos. Please see this for details:
https://li8bot.wordpress.com/2014/07/09/opencvpython-part-1-working-with-videos/

Convert video into individual frames using Python without ffmpeg?

I need to compare 2 videos to check whether they are the same.
So I am planning to do the following:
Split both the videos into individual frames
Compare each frame with the corresponding frame of the ref video using Python Image Lib
Count the number of different frames to decide whether they are same.
I would like to know whether there is any function in Python to help me with the first step, i.e., to split the video into individual frames. I do not want to use ffmpeg to do the splitting.
Thanks in advance for the help
You can use opencv
import cv2
video_capture = cv2.VideoCapture("rtsp://admin:admin#192.168.0.94:554/stream3")
while True:
# get frame by frame
ret, frame = video_capture.read()
cv2.imwrite('pic.png',frame)
cv2.imshow('Video', frame)
Try this:
currentFrame = 0
while(True):
# Capture frame-by-frame
ret, frame = cap.read()
# Saves image of the current frame in jpg file
name = './data/frame' + str(currentFrame) + '.jpg'
print ('Creating...' + name)
cv2.imwrite(name, frame)
# To stop duplicate images
currentFrame += 1
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()
#you can use this method

multi captures comparision opencv2.3.0 python2.7 windows

I'm trying to have my webcam do the following:
capture 10 captures for 1 minute duration (one capture every 6
seconds).
Then save them into an array or on the computer.
Then get other captures for 5 minutes duration (one capture every 6
seconds) and compare each capture with the first array.
so far I have this code:
import cv
cv.NamedWindow("Camera", 1)
# in case im using another camera:
cv.NamedWindow("Camera", 2)
capture = cv.CaptureFromCAM(0)
img = cv.QueryFrame(capture)
while True:
img = cv.QueryFrame(capture)
cv.ShowImage("Camera", img)
if cv.WaitKey(10) == 27:
break
cv.DestroyWindow("Camera")
How do I proceed with this? any ideas?
thanks in advance.

Categories