Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

V3.0 time stacking added #4

Merged
merged 1 commit into from
Sep 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
Changelog

V0.3
- Done
- Added time stack axis
- Display function updated
- Video limit using time duration
- Logs will tell the duration of video written, for human help
- Pending
- Getting the frame out
- Convert into class form
- Axis 3 - shuffle in the middle

V0.2
- Done
- If its q or Q it will work well to exit the code
- Multiple videos can be added to stack now
- Size fixed for single video via parameter, Giving the option to choose the size of video for user
- Limit_video index added - that video which will close the code None - infinite code run
- Video writer - when video is over - write the video in the end (if that doesn't work well - we will make it to write continuously
- If fps is fixed - thats fine who cares | if fps not fixed - calculate the fps for video
- Author name changed, gif added, gif created, image uploaded to git,
- added MIT licence so anyone can contribute and use the product https://choosealicense.com/licenses/mit/
- Pending
- Fixing the size of output video by user - done
- Write one function to loop in the videos and generate frame - thats it - and keep other functions to get input as frame and perform the actions - so if someone wants specific thing - cool they can do that - if not then use the default function - it will use too much ram
- Time based - enter the time in seconds after that it will break the video writing easy but cool - done
- Next time
- Tqdm as requirement to be added
- Sending frame out to be used
- Converting it to class - to enable frame wise stacking - if you want to do directly do hstack vstack - why using this thing?
- Grid based output or people can repeat the activity twice
- Or I can do it for them, run 2 functions in 1 function - find the size - and use it
- Axis 3 = when one frame of one and another of other - thats easy - just append the frame directly into the main stack of frames - run the adding thing twice and both frames will be added at once. - done

V0.1
- Added
- Video is streaming so to watch the output
- Vstack and hstack is added as axis 0 and 1
- q to stop the processing is added
- Future Addition
- It cant work with more than 2 videos - solved
- Getting the frame out, is not possible
- Using the frame as input to create a combined output
- Writing the videos if user passes the path - done
- Choose which video time to be taken as end of video - done
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,17 +64,20 @@ path2 = '../../../cars.mp4'

videos = [path1, path2, path1, path2]
video_size = (300,300) # w/h
limit_video = 0 # video index of video that will decide to close streaming
limit_video = 0 # video index, that will decide to close streaming
video_path = 'test.mp4'
video_duration = 4 # in seconds default None

output_video = stack_video(
videos,
axis=0,
axis=2,
size=video_size,
limit_video=limit_video,
write_path=video_path,
writer_fps=None,
display=True)
display=True,
duration=video_duration)
print(output_video)
```


Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
numpy
opencv_python
tqdm
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

setup(
name='vigenpy',
version='0.2.4',
version='0.3.0',
description=short_desc,
license='MIT',
long_description=long_desc,
Expand Down
131 changes: 92 additions & 39 deletions vigenpy/video/stack_video.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
__copyright__ = "Copyright 2021, Vinay Verma"
__credits__ = ["Vinay Verma"]
__license__ = "MIT"
__version__ = "0.1.0"
__version__ = "0.3.0"
__maintainer__ = "Vinay Verma"
__email__ = "[email protected]"
__module_name__ = "[Stack Video]"
Expand All @@ -13,47 +13,33 @@
import numpy as np
from tqdm import tqdm

def write_video(frame_list, video_name, output_shape, writer_fps):
def write_video(frame_list, video_name, output_shape, writer_fps, duration):
fourcc = cv2.VideoWriter_fourcc(*"mp4v")
height, width = output_shape

if duration is not None:
stop_frame = writer_fps * duration

out = cv2.VideoWriter(video_name, fourcc, int(writer_fps), (width, height))
frame_counter = 0
for encoded_frame in tqdm(frame_list):
frame_encoded = np.frombuffer(encoded_frame, np.uint8)
frame = cv2.imdecode(frame_encoded, cv2.IMREAD_COLOR)
out.write(frame)
out.release()
return video_name

def stack_video(
videos:list=[],
axis:int=0,
size=(300,400),
limit_video=None,
write_path=None,
writer_fps=None,
display=False
)->str:
"""
stack_video
frame_counter+=1

if duration is not None:
if frame_counter>stop_frame:
break # Video Duration Achieved

Write or display the video after stacking it
"""
if limit_video is None and write_path is not None:
print("Cant write an infinite video, Keep a limit video")
return None
out.release()

frame_list = list() # storing video frames to write
for video in videos:
if not os.path.exists(video):
print(f'Video {video} Not There')
return None
else:
print(f'Video {video} Found')
total_duration = frame_counter/writer_fps
return video_name, total_duration

caps = [cv2.VideoCapture(cam) for cam in videos]
fps = min([cap.get(cv2.CAP_PROP_FPS) for cap in caps])
print("Min FPS of Video is :",fps)
def axis_stack(caps, videos, size, axis, display):
frame_list = list() # storing video frames to write
past_frame=[]
start = True
video_over = False
Expand All @@ -63,23 +49,26 @@ def stack_video(
for i,cap in enumerate(caps):
ret, frame = cap.read()
if not ret:
# Video Still Not Over, Loop Again
caps[i] = cv2.VideoCapture(videos[i])
print('Video Ended, RESTARTING',videos[i])
frame = past_frame[i]

# Limiting Video Ended, Stop Now
if i==limit_video:
print(f'{videos[i]} Video Ended, Stopping Now',)
video_over = True
# break # stop for both cams later will buffer

if start:
# only initialize at start
# Save Past in case of frame drop
start = False
# in case of frame drop
past_frame = [frame for i in videos]

past_frame[i]=frame
frame = cv2.resize(frame, size)
frames.append(frame)
frames.append(frame) # combined frames in array

if video_over: break

Expand All @@ -90,22 +79,84 @@ def stack_video(
resized_frame = np.vstack(frames)

output_shape = resized_frame.shape[:2]
_, encoded_frame = cv2.imencode('.jpg', resized_frame)
flag, encoded_frame = cv2.imencode('.jpg', resized_frame)
frame_list.append(encoded_frame)

if display:
cv2.imshow('test',resized_frame)
wait_key = cv2.waitKey(1)

if ord('q')== wait_key or ord('Q')== wait_key:
if ord('q')==wait_key or ord('Q')==wait_key:
break
return frame_list, output_shape

def time_stack(caps, videos, size, display):
frame_list = list() # storing video frames to write
for i,cap in enumerate(caps):
while True:
ret, frame = cap.read()
if not ret:
print('Video Ended, Closed',videos[i])
break # frame is NONE

resized_frame = cv2.resize(frame, size)
output_shape = resized_frame.shape[:2]
flag, encoded_frame = cv2.imencode('.jpg', resized_frame)
frame_list.append(encoded_frame)

if display:
cv2.imshow('test',resized_frame)
wait_key = cv2.waitKey(1)

if ord('q')==wait_key or ord('Q')==wait_key:
break
return frame_list, output_shape

def stack_video(
videos:list=[],
axis:int=0,
size=(300,400),
limit_video=None,
write_path=None,
writer_fps=None,
display=False,
duration=None
)->str:
"""
stack_video

Write or display the video after stacking it
"""
if limit_video is None and write_path is not None:
print("Cant write an infinite video, Keep a limit video")
return None

for video in videos:
if not os.path.exists(video):
print(f'Video {video} Not There')
return None
else:
print(f'Video {video} Found')

caps = [cv2.VideoCapture(cam) for cam in videos]
fps = min([cap.get(cv2.CAP_PROP_FPS) for cap in caps])
print(f"Min FPS of All Videos is :{fps:.2f}")

if axis==2:
frame_list, output_shape = time_stack(caps, videos, size, display=display)

if axis==1:
frame_list, output_shape = axis_stack(caps, videos, size, axis=axis, display=display)

if axis==0:
frame_list, output_shape = axis_stack(caps, videos, size, axis=axis, display=display)

if writer_fps is None:
writer_fps = fps

if write_path:
video_name = write_video(frame_list, write_path, output_shape, writer_fps=writer_fps)
print("Video written sucessfully at :",video_name)
video_name, vid_duration = write_video(frame_list, write_path, output_shape, writer_fps=writer_fps, duration=duration)
print(f"Video written sucessfully at :{video_name} || With Duration {vid_duration:.2f} seconds")
return video_name

if display:
Expand All @@ -117,17 +168,19 @@ def stack_video(
path1 = '../../../archery.mp4'
path2 = '../../../cars.mp4'

videos = [path1, path2, path1, path2]
videos = [path1, path2]
video_size = (300,300) # w/h
limit_video = 0 # video index, that will decide to close streaming
video_path = 'test.mp4'
video_duration = 4 # in seconds default None

output_video = stack_video(
videos,
axis=0,
axis=2,
size=video_size,
limit_video=limit_video,
write_path=video_path,
writer_fps=None,
display=True)
display=True,
duration=video_duration)
print(output_video)